[Debate] – And what about configuration in Java EE 7 ?

How do you configure your enterprise application ? Or to be more precise “what is configuration,  what can you configure in Java EE and how can you configure it ?

What is configuration ?

Sometimes your application needs to change parts of its behavior at deployment time. You then need to provide some external configuration for some components. For example, in your development environment you don’t want to use a datasource and instead hit the database with a user & password, in your test environment you lookup for the datasource and use it. If you deploy your application in Europe you need to use the Euro as the current currency and if you deploy it in the US you need dollars. You’ve deployed your 2.3 version of your application and you want this “2.3” to appear at the bottom of your webpage as well as in your Swing Help->About menu. In a test environment everybody can access all the methods, in production security roles add certain restrictions. And so on and so forth…

In the Java EE specification there are several roles that deal with configuration (chapter 2.11) :

  • Deployer : “During Configuration, external dependencies declared by the Application Component Provider are resolved and application assembly instructions defined by the Application Assembler are followed.”
  • System Administrator : “The System Administrator is responsible for the configuration and administration of the enterprise’s computing and networking infrastructure.”

If you want to read more about configuration of the EE platform I suggest you read chapter 5 of the Java EE 6 spec.

How do we configure today ?

I first need to say that, thanks to Configuration by exception (or Convention over Configuration), you don’t need to add default configuration to your EE 6 application.  Default behavior and default configuration allows most applications to get the behavior they want most of the time, without the use of either annotations or deployment descriptors. But when we need to configure our application, how do we do it today ? The EE platform has some (optional) deployment descriptors you can use such as :

  • web.xml : you can configure parameters in your servlets with <context-param> or filters with  <init-param>
  • ejb-jar.xml : with the <env-entry> you can configure your EJBs
  • application.xml : here you can configure some application specific information such as the context-root of the web application
  • persistence.xml : it’s typically where you will configure the datasource or database access parameters
  • application-client.xml, ra.xml, webservices.xml

Usually these files are located under your WEB-INF or META-INF directory. You can then also use JNDI to access this configuration or create your own environment entries in the JNDI tree. Your methods can then access the environment using the JNDI interfaces and lookup methods on component-specific context objects (or with the @Resource annotation and the new lookup attribute @Resource(lookup="java:app/env/TheOrderQueue")). Since Java EE 6 there are several environment namespaces (java:comp, java:module, java:app, java:global). So the EE prefered approach are environement entries such as this ejb-jar.xml file :

[sourcecode language=”xml”]
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee&quot; version="3.2">
<enterprise-beans>
<session>
<ejb-name>MyEJB</ejb-name>
<ejb-class>org.agoncal.MyEJB</ejb-class>
<remote>org.agoncal.MyEJBRemote</remote>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<resource-ref>
<res-ref-name>jdbc/employee</res-ref-name>
<jndi-name>jdbc/__default</jndi-name>
</resource-ref>
<env-entry>
<env-entry-name>aMessage</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello World</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>
[/sourcecode]

Environment entries are seen as resources (you can inject them with @Resource) and they can be of any type : String, Object, JMS factories & destinations, datasources… In the code below I inject the datasource called jdbc/employee as well as a String called aMessage :

[sourcecode language=”java”]
@Stateless
public class MyEJB {
@Resource(name="jdbc/employee")
private DataSource employeeDataSource;

@Resource(name="aMessage")
private String welcomeMessage;

}
[/sourcecode]

With CDI, Qualifiers and Producers you could have the following code which makes use of the CDI typesafety :

[sourcecode language=”java”]
@Stateless
public class MyEJB {
@Inject @EmployeeDS
private DataSource employeeDataSource;

@Inject @AHelloWorldMsg
private String welcomeMessage;

}
[/sourcecode]

With CDI and Alternatives you can then inject an alternative value for welcomeMessage or a different datasource for the employeeDataSource. Alternatives can then be used to configure your application.

What’s missing ?

JNDI is cool… but can be of a drag when you use servlet containers such as Tomcat or when you do simple batch processing (you don’t want to access a remote JNDI tree) or simple Java class. And EE relies a lot on JNDI. If we look at EJBs, the world is changing : it went from a complex component model to a POJO that can run in an embedded container. So let’s treat it as a POJO.

In the code above, why do I have to treat the welcomeMessage as an environment entry I should lookup ? Why can’t I just treat it as a simple String in a POJO which value changes at deployment time? Datasources, JMS factories… are container resources, but not a welcome message. Going futher, if an EJB is a POJO as well as a Servlet a RESTful Web Service or a Managed Bean, why not just configure these component using the same configuration model ?

CDI brings alternatives and the possibility to inject alternative values. But again, why do I have to use @Produces (to produce a String for the welcome message), @Inject, @Alternative and a seperate class that gives me the value of the alternative welcome message, when I just want to configure externally the value of the String ?

What’s missing in Java EE is a simple way to configure your beans (and by bean I mean EJBs and so on).

What do we do next ?

Java EE 7 has started and we have 18 months to talk about it and make it happen. So why not having a more flexible configuration model in the platform. And because we don’t want to reinvent the wheel, let’s get some inspiration from Spring Config, or even better Seam Config (which makes even XML a bit more type-safe ;o) Taking my previous code example, I would not inject the welcomeMessage but just treat it as a simple String :

[sourcecode language=”java”]
@Stateless
public class MyEJB {
@Inject @EmployeeDS
private DataSource employeeDataSource;

private String welcomeMessage;

}
[/sourcecode]

Then, if I want to configure the welcome message the Seam Config way I’ll have an external XML file (let’s reuse the ejb-jar.xml) and use new namespaces : here the namespace r refers to the package org.agoncal. So r:MyEJB referes to the class org.agoncal.MyEJB. So, as you can see  r:welcomeMessage refers to the property org.agoncal.MyEJB.welcomeMessage in which we set the String Hello World :

[sourcecode language=”xml” highlight=”20″]
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee&quot;
xmlns:s="urn:java:ee:ejb"
xmlns:r="urn:java:org.agoncal" version="3.2">

<s:enterprise-beans>
<s:session>
<r:MyEJB>
<s:ejb-name>MyEJB</s:ejb-name>
<s:ejb-class>
<r:MyEJB/>
</s:ejb-class>
<s:remote>
<r:MyEJBRemote/>
</s:remote>
<s:session-type-stateless/>
<s:transaction-type-container/>
<r:employeeDataSource>
<r:ADifferentEmployeeDSQualifier/>
</r:employeeDataSource>
<r:welcomeMessage>Hello World</r:welcomeMessage>
</r:MyEJB>
</s:session>
</s:enterprise-beans>
</ejb-jar>
[/sourcecode]

The namespace urn:java:ee:ejb is EJB Config’s root namespace (inspired from Seam Config). This is where the built-in elements live. Here I just give a simple (mayby non accurate) example of what configuration could look like, but if you look at Seam Config, you can configure nearly everything (lists, maps, references…).

And going further ?

Well, if an EJB is a POJO with specific services (transactional, thread safe, secure…) let’s consider it like a bean : a Managed Bean with sepecific services. So let’s declare it in the beans.xml (CDI file). Same for all the managed beans. At the moment there are several deployment descriptors. What about having the possibility to have a single one (as well as multiple like today) to configure the entire plaform ? Something like application.xml could be extended, or beans.xml.

Java EE 7 is going cloud, so why not use the same way to configure your nodes, instances, platform… ?

Let’s continue this debate

I’ve written this blog because I started a thread on the Java EE 7 mailing list on configuration. I’m not an expert on configuration but I can see the benefit of having something similar to Seam Config in the EE platform. Changing (or upgrading) the way we’ve been doing configuration throught environment entries is a huge work (look at all the deployment descriptors that we should have to extend). Is it worth it ? Do you care ?

Use this blog to post your comments or the Java EE 7 mailing list.

References

7 thoughts on “[Debate] – And what about configuration in Java EE 7 ?

  1. In Spring 3.0, you can interpolate variables from a property file like this:

    public class MyService {

    @Value{“${myapp.welcome.msg}”}
    private String welcomeMessage;
    }

    Of course, you still need to tell Spring where to find the properties using a line in your XML config:

    where MYAPP_CONFIG is a system property or an environment variable. (Spring 3.1 has a new annotation for this purpose, so you no longer need _any_ XML config.

    The important point is that the configuration source is not part of the application artifacts, i.e. the properties file is somewhere in the file system and not compiled into the WAR.

    I never understood the Java EE roles of assembler, deployer etc. In real life, there’s developers delivering a WAR and administrators deploying it. And of course administrators should never have to unpack the WAR and edit web.xml or ejb-jar.xml to configure deployment time information like JDBC or JMS URLs.

    Suppose you have a WAR using some remote EJBs. For deploying the same WAR on two different servers, you have to configure the ejb-ref with a combination of deployment descriptor, container specific deployment descriptor, maybe another level of JNDI indirection – I’ve never done this myself, but it seems to be a terribly complicated procedure, where a simple property file would be enough….

    Would be great to see this process simplified in Java EE 7, with a clear distinction of compile time and deployment time configuration.

    Regards,
    Harald

    1. Harald,

      BTW, we do include property loading in CanDI XML. Not sure if Seam XML Config does the same or not…

      Cheers,
      Reza

  2. Hi ! Sorry for my English speech but I’m a French guy. What a very interesting post ! SCA (Service Component Architecture) defines how a component should be. For instance, a component has some properties and these properties can be overridden.

    In the same manner, SCA defines other abstract concepts which could be useful for Java EE 7 (cloud computing, convention over configuration, SOA, components, bindings, wiring).

    1. In addition to Sébastien suggestion I would point to OSGi “Configuration Admin Service” in compendium specification. I do think it provide a nice way to runtime configuration/administration coupled with “apache felix fileinstall” it provide a powerful solution. Would be nice to have such functionality in JEE7.

  3. I have a prez about a few issues we have in our team. If you would like to discuss on the subject, I have new idea …

    http://www.arakiri.net/pragmatic_configuration.pdf

    I would like to put somthing more DevOps friendly in the Java sphere to improve the app config, ping me.

    Another stuff more J2EE related is the concept of logical resource: you defined a resource and you put various cloned resource in your app, then you can switch with a simple startup flag.

    Example:

    you defined a logical data source, you have 3 cloned database setup in your code/conf (dev/stage/prod) and you switch at startup. At the end your code is just referencing your logical database.

    When you deploy to the prod, the setup is minimum.

  4. I didn’t know about your post when I wrote a similar one on the topic, here:

    http://blog.ringerc.id.au/2012/07/java-ee-7-needs-improvements-in-app.html

    This topic has now been raised on the Java EE 7 expert group mailing list, but it’s getting crickets.

    http://java.net/projects/javaee-spec/lists/jsr342-experts/archive/2012-07/message/30

    Please dive in on the -users list (we mortals don’t get to post on -experts) and help push the issue.

  5. To respond to your final question: I care a lot about this issue. It has driven me nuts for some time. Even your workaround above using resources still requires the “user” mess with the deployment descriptors in an ejb jar. They can’t just deploy the archive and configure it via a container web interface or command line. More importantly, the app can’t modify those resources and have the changes remain persistent, so the app can’t interact with its own configuration, only consume it.

    What I’d like to see is an enhancement of the Preferences API with:

    – A tightening of the rules to better specify how it works in a containerised environment
    – CDI producers for field injection
    – Emphasis in the documentation that the prefs API isn’t for bulk storage or serialized objects, that’s what JPA is for

    The prefs could be in an on-disk XML file, or they could be in a database maintained by the container with a pretty web UI for users to mess with them. The app doesn’t care. The container does its job by providing somewhere for the app to keep them and a way for both app and users to modify them.

    The app is free from worrying about where to squirrel away a properties file, worrying if Glassfish will eat its preferences API settings next redeploy, or needing to configure a full container JDBC data source just to store/get configuration. The user gets an easy way to save, edit, and restore prefs via the container.

Leave a Reply