How is configuration read in AKKA - java

I am creating custom configurations for my akka application written in java as follows
application.conf
akka {
actor {
debug {
# enable DEBUG logging of actor lifecycle changes
lifecycle = on
}
}
}
I am not sure how to load this configuration. It is unclear from the docs if this needs to be explicitly loaded at actrSystem creation or if it needs to be in the class path while running the jar. In both cases, is there an example I can look at
This is a maven project and the configuration file is under src/main/resources
I see that the applucation.conf exists under target/classes. Is that it?

With ConfigFactory you can load the application.conf file from src/main/resources, not necessarily need an ActorSystem to use it
According to the akka doc http://doc.akka.io/docs/akka/2.4/general/configuration.html
Akka uses the Typesafe Config Library, which might also be a good choice for the configuration of your own application or library built with or without Akka. This library is implemented in Java with no external dependencies; you should have a look at its documentation (in particular about ConfigFactory), which is only summarized in the following.
A simple test
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
public class ConfigFactoryTest {
public static void main(String[] args) {
Config conf = ConfigFactory.load("application.conf");
System.out.println(conf.getString("akka.actor.debug.lifecycle")); //should be 'on'
}
}
Also can use withFallback method
http://doc.akka.io/docs/akka/2.4/general/configuration.html#Reading_configuration_from_a_custom_location
Assume you have another properties file called fallback.conf
akka {
actor {
fallback = "fallback"
}
}
Config fallback = ConfigFactory.load("fallback.conf")
Config conf = ConfigFactory.load("application.conf").withFallback(fallback);
System.out.println(conf.getString("akka.actor.fallback")); //fallback
Here you can find examples :
https://github.com/typesafehub/config/tree/master/examples/java

Related

Read Multiple Properties File using spring profiles in Spring Boot

I am trying to load 2 properties file in spring boot.
One of them contains the metadata (Database connection and other such properties). The other contains business logic (mapping between upstream and downstream Entity. This mapping is different in Dev and Prod, hence can't have a single resource file for these).
I want to use Spring Profiles for different environments (Dev, Stage, Prod).
So, I created 3 different folders in src/main/resources 1 for each environment.
Using spring profies, I am aware how to have env specific application-env.properties file. However, I am unable to move forward on how to use the same for my use case.
PS : Not adding any code snippet, because the question doesn't require one.
Here's an example from the docs:
$ java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
You could also define this in your code before starting Spring Boot:
public static void main(String[] args) {
System.setProperty("spring.config.location", "optional:classpath:/default.properties,optional:classpath:/override.properties");
SpringApplication.run(Application.class, args);
}
To use custom prefixes for your app specific properties you can define #ConfigurationProperties class(es):
#Data
#ConfigurationProperties(prefix = "app.mapper")
public class MapperProperties {
private String foo;
}
and use it in any component:
#Component
#RequiredArgsConstructor
#EnableConfigurationProperties
public class YourComponent {
private final MapperProperties properties;
}

Can I set jetty classloading semantics using system properties?

In our project, we start embedded Jetty using only the Java API (no external xml, etc.), and then deploy war bundles to it. Now I have a situation where I'm getting ClassCastExceptions because of differing jars loaded from the .war vs. what is on the actual classpath. Reading the Jetty page on classloading (https://www.eclipse.org/jetty/documentation/current/jetty-classloading.html) I wanted to see if I could configure the WebAppClassLoader to augment the set of classes considered to be 'system' classes. There is a Java API to do this (WebAppContext.setServerClasses()) and a way to do it if you're using an xml config file:
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="serverClasses">foo.bar.,com.acme.</Set>
...
But I'd like to know if it is possible to do it using just Java system properties.
Thanks!
There are no system properties to configure server or system classes on a WebAppContext.
This is because that kind of change is considered to belong to a specific WebApp, not all WebApps.
But, you have an alternative, if you are using the DeploymentManager in your embedded-jetty, you are in luck, you have an option in code.
You'll want to create a custom AppLifeCycle.Binding which sets those properties on any deployed WebAppContext (I would recommend binding to deploying).
Here's an example that forces the WebAppContext's to always use the logging libraries from the server/system classloader.
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.AppLifeCycle;
import org.eclipse.jetty.deploy.graph.Node;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.WebAppContext;
public class CentralizedWebAppLoggingBinding implements AppLifeCycle.Binding
{
public String[] getBindingTargets()
{
return new String[]
{ "deploying" };
}
public void processBinding(Node node, App app) throws Exception
{
ContextHandler handler = app.getContextHandler();
if (handler == null)
{
throw new NullPointerException("No Handler created for App: " + app);
}
if (handler instanceof WebAppContext)
{
WebAppContext webapp = (WebAppContext)handler;
webapp.addSystemClass("org.apache.log4j.");
webapp.addSystemClass("org.slf4j.");
webapp.addSystemClass("org.apache.commons.logging.");
}
}
}
And here's an example of using DeploymentManager from embedded-jetty (with the above CentralizedWebAppLoggingBinding too.
ContextHandlerCollection contexts = new ContextHandlerCollection();
DeploymentManager deployer = new DeploymentManager();
if(debugIsEnabled)
{
DebugListener debug = new DebugListener(System.err, true, true, true);
server.addBean(debug);
deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
}
deployer.setContexts(contexts);
deployer.setContextAttribute(
"org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
WebAppProvider webAppProvider = new WebAppProvider();
webAppProvider.setMonitoredDirName(jettyBase + "/webapps");
webAppProvider.setDefaultsDescriptor(jettyHome + "/etc/webdefault.xml");
webAppProvider.setScanInterval(1);
webAppProvider.setExtractWars(true);
webAppProvider.setConfigurationManager(new PropertiesConfigurationManager());
webAppProvider.addLifeCycleListener(new CentralizedWebAppLoggingBinding());

Java Spring Derby - datasource specific to unit tests

So, I'm working on a Spring Rest API using JPA and based on an Oracle database.
I have some unit tests, mostly very specific (like regex checks).
I also have some bigger integration tests and at the moment they would interact with the real database.
What I want is to use Derby for the tests and Oracle for the real app.
In an application.properties file, I have the properties for the two datasource scenarios.
I have no other configuration file, no XML file in the entire project
#spring.datasource.url=jdbc:oracle:thin:#1.2.3.4:1521/orcl
#spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
#spring.datasource.username=user
#spring.datasource.password=password
spring.datasource.driverClassName=org.apache.derby.jdbc.EmbeddedDriver
spring.datasource.urljdbc:derby:target/database/message;create=true
spring.datasource.username=app
spring.datasource.password=app
also:
#Configuration
#PropertySource(value = { "classpath:application.properties"}, ignoreResourceNotFound = true)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
by manually commenting, uncommenting the right block in the properties file, i can either use derby or the real oracle DB
I would like to make that process automatic by having two "named datasources" that i can use. I'm no Spring expert :-)
What's the easiest/recommended way to achieve this?
Please if you mention some XML, tell me where they should go or how they should be referenced as i don't know about them and there seems to be very conflicting advice online depending on wether you use Spring, EE, different versions of JPA, etc.
Many Thanks!
You can annotate your Tests with the annotation #TestPropertySource which:
can be used to selectively override properties defined in system and
application property sources
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#integration-testing-annotations-spring
So, you can remove the test database properties from application.properties and either put them into a separate file and specify that as a value for #TestPropertySource or you can use the inline mechanism e.g.
#ContextConfiguration
#TestPropertySource(
locations = "/test.db.properties"
)
public class MyDatabaseTest{
}
or
#ContextConfiguration
#TestPropertySource(
properties = {
"spring.datasource.driverClassName=org.apache.derby.jdbc.EmbeddedDriver",
"spring.datasource.urljdbc:derby:target/database/message;create=true",
"spring.datasource.username=app",
"spring.datasource.password=app"
}
)
public class MyDatabaseTest {
}

How do you handle configuration on spring framework when developing custom libraries intended to be consumed by other applications?

I'm working on building a custom "event" library that encapsulates the technical details of an event buffer we are planning to share with multiple consumers. Ideally, we want this library to use the spring framework (note: not spring boot), and be environmentally aware. Something I am not groking from the current docs is how to make the library environmentally aware.
For example, we want to include with the library a static configuration for the queue end points the library will publish / consume from; however, we want to enable "overriding" these queues when in the development or integration environments. Ideally, I do not want to make multiple builds that swap out what the config file is, but include them all and know to read the "right" one.
Some of the things I am not understanding;
How to pass in a "profile" when debugging (it seems the Environment object won't honor the -Dspring.active.profiles property).
How to structure the #Configuration classes so that you do not hard code #Profile(prod).
Total Spring n00b, thanks in advance!
---UPDATE: Trying to provide a more concrete example.
So I have create a basic configuration class to hold the details that would be populated by configuration files:
#Configuration
public class EventConfiguration implements EnvironmentAware{
private static Environment env = null;
#Value("${events.queue1}")
private String queue1;
#Value("${events.queue2}")
private String queue2;
#Bean
public EventDispatcher eventDispatcher() {
return new EventDispatcher(this);
}
#Override
public void setEnvironment(Environment environment) {
env = environment;
}
... getters and setters
Essentially I want to either go the yaml approach and define the queues by environment "dev", "integration", "prod"; or have 3 different files following the application-{env}.properties convention.
Then, to help me understand how this works, I threw together a quick test so I can inspect the configuration / environment:
#Test
public void testContext() {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext();
Environment env = ctx.getEnvironment();
ctx.scan("com...events");
ctx.refresh();
EventDispatcher dispatcher = ctx.getBean(EventDispatcher.class);
}
I started the debugger with a -Dspring.profiles.active=dev, after having created an application-dev.profile available on the class path.
Am I on the right track? Seems weird to have to have that type of boiler plate code to instantiate the objects, plus it didnt work. The Environment object only showed "default" as the active profile.

Guice and general application configuration

For a monitoring software written in Java I consider using Google Guice as DI provider. The project needs to load its configuration from an external resource (file or database). The application is designed to run in standalone mode or in a servlet container.
At the moment the configuration does not contain bindings or parameters for dependency injection, only some global application settings (JDBC connection definitions and associated database management/monitoring objects).
I see two options:
to use another library, for example Apache Commons Configuration, which supports file and JDBC configuration sources (and many other)
or
to use a file based addon for Guice like guice-xml-config to store the application options (this would allow to configure the DI part later if it becomes necessary).
Would you recommend to use Guice for both tasks, or keep the general application configuration separate from the dependency injection? Which advantages and disadvantages would you consider the most important ones?
It's straightforward to slurp a property file in a Guice module:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
try {
Properties properties = new Properties();
properties.load(new FileReader("my.properties"));
Names.bindProperties(binder(), properties);
} catch (IOException ex) {
//...
}
}
}
Later it's easy to switch from Properties to other config sources.
[Edit]
BTW, you can get the injected properties by annotating it with #Named("myKey").
Check the governator library:
https://github.com/Netflix/governator/wiki/Configuration-Mapping
You will get a #Configuration annotation and several configuration providers. In code it helps to see where is You configuration parameters used:
#Configuration("configs.qty.things")
private int numberOfThings = 10;
Also, You will get a nice configuration report on startup:
https://github.com/Netflix/governator/wiki/Configuration-Mapping#configuration-documentation
Try Guice configuration available on maven central, it's support Properties, HOCON and JSON format.
You can inject properties from file application.conf to your service as :
#BindConfig(value = "application")
public class Service {
#InjectConfig
private int port;
#InjectConfig
private String url;
#InjectConfig
private Optional<Integer> timeout;
#InjectConfig("services")
private ServiceConfiguration services;
}
You must install the modules ConfigurationModule as
public class GuiceModule extends AbstractModule {
#Override
protected void configure() {
install(ConfigurationModule.create());
requestInjection(Service.class);
}
}
I ran into the same problem in my own project. We had already chosen Guice as DI-framework and to keep things simple wanted to use it also with configuration.
We ended up reading the configuration from properties file using Apache Commons Configuration and binding them to Guice injector like suggested in Guice FAQ How do I inject configuration parameters?.
#Override public void configure() {
bindConstant().annotatedWith(ConfigurationAnnotation.class)
.to(configuration.getString("configurationValue"));
}
Reloading of configuration supported by Commons Configuration is also quite easy implement into Guice injection.
#Override public void configure() {
bind(String.class).annotatedWith(ConfigurationAnnotation.class)
.toProvider(new Provider<String>() {
public String get() {
return configuration.getString("configurationValue");
}
});
}

Categories

Resources