TomEE custom property provider - java

I am running my application in TomEE 8. I want to read some property from my DB and pass it to application.
I saw one example from https://rmannibucau.wordpress.com/2014/08/06/tomee-and-more-advanced-resource-configuration/ . may be it is old. it is not working . while deploying application it expect the Resource Type. But example doesn't have Type in resource tag.
<Resource id="..." properties-provider="com.foo.MyPropertiesReader" />
What is the latest/correct way to load my custom properties to my application from my DB ?

I believe that Romain was trying to be concise in his examples. In his examples, it can be surmised that he was using javax.sql.DataSource or DataSource. Despite that, though, this will work for any type of resource, even custom resources. There are also already implementations that you can check out:
HerokuDatabasePropertiesProvider.java
OpenshiftMySQLPropertiesProvider.java
OpenshiftPostgreSQLPropertiesProvider.java
In the page you mentioned, Romain also notes that your class can either implement org.apache.openejb.api.resource.PropertiesResourceProvider, or supply a Properties provides(); method.
Here is a small example:
org.superbiz.provider.MyPropertiesReader.java
package org.superbiz.provider;
import org.apache.openejb.api.resource.PropertiesResourceProvider;
import org.apache.openejb.testng.PropertiesBuilder;
import java.util.Properties;
public class MyPropertiesReader implements PropertiesResourceProvider {
public Properties provides() {
return new PropertiesBuilder()
.p("JdbcDriver", "org.hsqldb.jdbcDriver")
.p("JdbcUrl", "jdbc:hsqldb:mem:moviedb")
.build();
}
}
src/main/webapp/WEB-INF/resources.xml
<resources>
<Resource id="movieDatabase"
type="DataSource"
properties-provider="org.superbiz.provider.MyPropertiesReader"/>
</resources>
These are the key snippets that I hope will help clear your doubts. Implementation of the datasource is left for you to code. :)

Related

spring boot property with profile from dependency

Problem:
I have 3 parts in the software:
Client A service
Client B service
Target C service
I want to connect to C from A and B
I wrote a library with following setup:
/src/main/java/pkg.../TargetConnector.java
/src/main/java/pkg.../TargetConfig.java
/src/main/resources/application-dev.properties
/src/main/resources/application-tst.properties
/src/main/resources/application-prd.properties
My clients A and B both have there own sources and properties:
/src/main/java/pkg.../Client{A/B}Service.java
/src/main/java/pkg.../Client{A/B}Config.java
/src/main/resources/application-dev.properties
/src/main/resources/application-tst.properties
/src/main/resources/application-prd.properties
The properties of the Connector contains some login info for the service e.g.
target.url=https://....
target.usr=blablabla
target.key=mySHAkey
which is used in the TargetConfig to preconfigure the Connector e.g.
#Value("target.url")
String url;
#Value("target.usr")
String usr;
#Value("target.key")
String key;
#Bean
public TargetConnector connector() {
return new TargetConnector(url, usr, key);
}
Now when I use the connector jar in the client I can find the configuration via packagescan. The connector class is loaded but the problem is that it does not load the properties files.
Research
I found that multiple property files cannot have the same name (e.g. clients application-{profile}.properties clashes with the one from the connector), so I tried to rename application-{profile}.properties of the targetConnector to application-connector-{profile}.properties.
The properties whoever still do not get loaded, (which makes sense since I do not have a e.g connector-dev profile but my profile is simply named dev).
Furthermore, even if I try to explicitly load one of the property files from the connector with:
#PropertySource({"classpath*:application-connector-dev.properties"})
it cannot be found
Question
My question is actually 3 tiered:
How can I load a property file in a dependency jar at all?
How can I load the profiled version of the property file if the the properties file has a different name than application.properties? e.g. application-connector.properties
How can i combine the answers from question 1 and 2 to load the profiled version of the property in the jar?
If further explanation is needed, please ask.
Answer
I went for an approach as given in the accepted answer.
I Just created 3 configs for the dev, tst, prd profiles containing the values needed and annotated the config files with the correct profiles.
You are using #Configuration annotated class. Maybe you can have one per profile. Here you are an example:
#Configuration
#Profile("profileA")
#PropertySource({"classpath:application-profileA.properties"})
public class ConfigurationProfileA{
#Value("${target.url}")
String url;
#Value("${target.usr}")
String usr;
#Value("${target.key}")
String key;
#Bean
public TargetConnector connector() {
return new TargetConnector(url, usr, key);
}
}
Do the same for profile B (maybe you can structure this better but the key points here are the annotation #Profile("") and #PropertySource(""))
Once you have your config class, Spring will use the Configuration class you want by just filling -spring.profiles.active=profileA (or the name of the profile you have written in the #Profile("") annotation)
I think there is a typo in this line #PropertySource({"classpath*:application-connector-dev.properties"})
Please check by removing the asterik.
In order to run with a specific profile, you can run with option -spring.profiles.active=dev for example
If you don’t run with a profile, it will load the default profile in application.properties that you don’t seem to have.
Furthermore, an advice would be to always have an application.properties and put in it the common properties and the default values that you would override in other properties files.
Other mistake is how you assign properties with #Value annotation, you need to use #Value("${PROPERTY_FROM_PROPERTIES_FILE}")

Java: Can you expose 3rd party interface from your own class

We’re using log4j2 to do logging throughout our application and now I want to add some additional functions to the LogManager…at the same time, I hoped it would be possible to hide the “implementation details” of the LogManager for the rest of the application, so that instead of importing the log4j2 Logger everywhere, I can expose my own interface or class, from my own proprietary LogManager (that way, it would be possible to refactor or replace the way I store log messages without affecting the entire application).
I can create my own LogManager, called LM, easily like this:
package com.xxx.yyy.logging;
import org.apache.logging.log4j.LogManager;
public class LM extends LogManager {
…add own methods here…
}
But when I call:
LM.getLogger(Application.class)
It returns an object of type org.apache.logging.log4j.Logger – is there an easy way to “wrap and expose” this interface via my own package, so that the rest of the application don’t have to be concerned with log4j?
I’ve tried something like:
package com.xxx.yyy.logging;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.message.MessageFactory;
public class LMlogger extends org.apache.logging.log4j.core.Logger implements Logger {
protected LMlogger(LoggerContext context, String name,
MessageFactory messageFactory) {
super(context, name, messageFactory);
// TODO Auto-generated constructor stub
}
};
…in order to implement the class returned as well as the expected interface, but still I can’t “down-cast” the returned Logger-object to my own LMlogger (which makes sense, as my class is the sub-class). But is there another way to keep the log4j2 implemenation details in one place only, without having to wrap each and every method of the Logger-class?
You can use the tool that log4j2 provides to generate custom Logger wrappers.
This tool was intended to add convenience methods for custom log levels or hide existing log levels, but you can use it for any purpose.
It also hides the LogManager from the client code (your app), and the generated code is in whatever package you specify, so client code won't be aware it is using log4j2.
You may need to regenerate the wrapper when you upgrade log4j2 after it had API changes (which is rare, but there will be additional API in 2.6).
Look at the following way:
Create a same-name Class org.apache.logging.log4j.LogManager in your project, and copy the source code of the original org.apache.logging.log4j.LogManager in log4j lib. Then edit the code and add what you want.
Logger or other class in the same way.
But you must make sure that your project must be loaded before the log4j lib.

Configuring New Relic custom metrics with YAML

According to the New Relic Documentation:
Starting in version 2.10.0, you can monitor specific methods in your application without modifying code by using a custom instrumentation XML file.
It also says:
Prior to 2.10.0, YAML files could be used for custom instrumentation. These YAML files are still supported.
I can't find documentation for the YAML format anywhere. I'm assuming it's pretty similar to the XML structure, but it can't be a 1-to-1 match.
"Where can I find documentation" seems like a terrible Stack Overflow question, so here is specifically what I want to know. Given the following Java class:
public class Test {
public void foo() {
bar();
}
private void bar() {
}
}
What New Relic YAML configuration would I use to track both foo and bar where foo is a transaction entry point and bar is not (assuming I inferred the meaning of that attribute correctly)?
Thanks a lot!
Patrick
I talked to the folks over at New Relic. The documentation regarding the yml configuration has been removed because it has been deprecated. The old yml configuration support is there for backward compatibility; however, new features have been added to the xml configuration that are not supported by the yml configs . . . for example, method matching without parameter specifications.
The supported approach to custom extensions is to use the XML configuration. A few notes from my experience in case it helps someone else with similar problems.
The custom xml examples documentation at the time of writing has a sample that's invalid if you try to validate it with the command mentioned in the custom monitoring by xml document.
Here's a sample script that worked for me:
<?xml version="1.0" encoding="UTF-8"?>
<extension
xmlns="https://newrelic.com/docs/java/xsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="newrelic-extension extension.xsd "
name="HelloWorldExtension" version="1.0"
>
<instrumentation>
<pointcut transactionStartPoint="true">
<className>com.autopilotllc.HelloWorld</className>
<method>
<name>sayHello</name>
</method>
</pointcut>
</instrumentation>
</extension>

Play Framework custom java extensions for template

I am using Play Framework 1.2.5, and trying to use DateTime from Joda Time instead of the usual java.util.Date. I am trying to implement a format method for use in my views.
The Play documentation says I can create my own custom java extensions for use in templates, but it doesn't seem to be working for me. I have followed the example in the docs to no avail.
My custom extension:
package ext;
import org.joda.time.DateTime;
import play.templates.JavaExtensions;
public class DateTimeExtensions extends JavaExtensions {
public static String format(DateTime datetime, String format) {
return datetime==null ? "" : datetime.toString(format);
}
}
My template code:
${subProject?.startDate?.format('yyyy-MM-dd')}
And the error I am receiving:
Exception raised was MissingMethodException : No signature of method: org.joda.time.DateTime.format() is applicable for argument types: (java.lang.String) values: [yyyy-MM-dd]
It looks like Play isn't detecting my custom extension as the documentation says it should. Does anyone have any suggestions on how to make this work?
Your extension class looks good to me. The documentation states that you have to restart your application for the extension to become active. If that doesn't work, try running play clean. Doing so deletes temporary files, including cached bytecode, which will hopefully resolve your issue.

Accessing the application.conf properties from java class with Play! 2.0

I want to add an object to the Global scope, and in order to construct it I need to pass it a path to a file.
I don't want to hard code the file path in the source, and so I want to get that path from the application.conf.
The problem is that I don't know how to access these properties from the java class.
I tried this:
Configuration.root().getString("file.path")
But it ends with a NullPointerException.
Am I wrong in assuming that there's a global Configuration instance that I can use?
Thanks.
Try Play.application().configuration().getString("your.key")
As noted in the comment (nico_ekito), please use play.Play and not play.api.Play. play.api.Play is for scala controllers (see comment by Marcus biesior Biesioroff)
Additionally, play uses https://github.com/typesafehub/config under the hood so it can also provide some insights.
Even if it seems simple, here is the scala way to get properties from configuration file :
Play 2.0 and 2.1 :
import play.api.Play.current
...
Play.application.configuration.getString("your.key")
Play 2.2 and +
import play.api.Play.current
...
current.configuration.getString("your.key")
Using Typesafe config
import com.typesafe.config.ConfigFactory
...
ConfigFactory.load().getString("your.key");
From Play 2.4 and + it is better to use dependency injection to access Configurations:
import play.Configuration;
import javax.inject.Inject;
#Inject
private Configuration configuration;
...
String value = configuration.getString("your.key");
Since Play 2 uses the Typesafe config library, I accessed my vars in application.conf like this :
ConfigFactory.load().getString("my.var");
In the play java is:
import play.Play;
...
Play.application().configuration().getString("key")
Use as following (Tested in Play 1.2.5)
${play.configuration.getProperty('my.var')}
where my.var should be specified in application.conf file
As a reference to access it from the template (for play < 2)
play.configuration['your.key']
As folks have mentioned, Play.application.configuration no longer exists.
In Play Scala 2.3.x, to read a value from conf/application.conf, you can do the following:
import play.api.Play.current
...
current.configuration.getString("key")
In Play 1.2.x
import play.Play;
...
String version = Play.configuration.getProperty("application.version.number", "1.1.1");
where the second parameter is the default value
Import this
import com.typesafe.config.Config;
and write the below lines
private Config config;
this.config = ConfigProvider.config();
String value = this.config.getString("fieldFromConfigFile");
import play.Play;
String myVal = Play.configuration.getProperty("your.key").toString();
i use this in my app and it works
Dont forget to import play.Play. Hope it'll gives you help
Starting from version 2.5 please use play.Application class which should be injected and then
application.config().getString("your.property.here")
For Java Playframework:
In Application.conf, you can put something like that:
email="example#gmail.com.pe"
some class:
import play.Play;
String email = Play.application().configuration().getString("key") // key ->email

Categories

Resources