Antonio Goncalves is a senior software architect living in Paris. Initially focused on Java development since the late 1990s, his career has taken him to different countries and companies where he works now as a Java EE consultant in software architecture. As a former BEA consultant he has a great expertise in application servers such as Weblogic, JBoss and, of course, GlassFish. He is particularly fond of Open Source and is a member of the OOSGTP (Open Source Get Together Paris). He is also the co-creator of the Paris Java User Group and talks on Les Cast Codeurs podcast. Antonio wrote a first book in French on Java EE 5 back in 2007. Since then he has join the JCP and is an Expert Member of various JSRs (Java EE 6, JPA 2.0 and EJB 3.1). He then published a second book for Apress: Beginning Java EE 6 Platform with GlassFish 3. For the last years Antonio has been talking at international conferences mainly about Java EE, including JavaOne, The Server Side Symposium, Devoxx, Jazoon… He has also written numerous technical papers and articles for IT Web sites (DevX, JaxEnter) or IT magazines (Programmez, Linux Magazine). Antonio is a DZone MVB and is not an employee of DZone and has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

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

06.13.2011
| 4962 views |
  • submit to reddit

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 :

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" 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>

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 :

@Stateless
public class MyEJB {
@Resource(name="jdbc/employee")
private DataSource employeeDataSource;

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

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

@Stateless
public class MyEJB {
@Inject @EmployeeDS
private DataSource employeeDataSource;

@Inject @AHelloWorldMsg
private String welcomeMessage;
...
}

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 :

@Stateless
public class MyEJB {
@Inject @EmployeeDS
private DataSource employeeDataSource;

private String welcomeMessage;
...
@Stateless
public class MyEJB {
@Inject @EmployeeDS
private DataSource employeeDataSource;

private String welcomeMessage;
...
}
}

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 :

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
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>

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

 

 

 

From http://agoncal.wordpress.com/2011/06/10/debate-and-what-about-configuration-in-java-ee-7/

Published at DZone with permission of Antonio Goncalves, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Henk De Boer replied on Mon, 2011/06/13 - 3:11am

For configuration, I have personally never been a really big fan of shipping an EAR with lots of unresolved "external dependencies" and a readme.txt for someone called a deployer.

I guess the ideal Java EE way of doing things is the following:

  • EAR gets shipped to guy called 'deployer'.
  • Deployer guy copies it to Glassfish and starts it.
  • On the GF console, a message appears: unresolved JMS queue "internalOrderQueue". Do you want to create it? [y/n].
  • Deployer guy thinks, hey, why not. Yes!
  • Next message: unresolved JMS queue "internalOutboundProcessorQueue". Do you want to create it? [y/n].
  • This goes on for about 100 queues. 10 minutes later, there's a new type of message: Unresolved data source "mainDS". Do you want to create it? [y/n].
  • Deployer guy says yes again. But this times it's not as simple and there's a follow up question: Enter URL of database server:
  • Deployer guys opens the readme.txt, trying to find out where the heck mainDS should go to. After some searching it appears to be: jdbc:postgresql://db14.live.mycompany.com/my_db, so deployer guy enters this URL and hits enter.
  • Next questions: How many connections should be pooled:
  • Deployer guy openens readme.txt again, but can't find it. Scratches his head, and thinks 100 has a nice sound to it and enters that.
  • Eventually the data source is created and then the next message appears: Unresolved data source "statDS". Do you want to create it? [y/n].
  • Deployer guys says yes again, but this time it's not clear to which DB this DS should point. It's not in the readme! Eventually deployer guys just enters the same URL as for the mainDS to be done with it. Of course this is the wrong one and chaos ensues.

Now I may be greatly exaggerating, but in the core, is this the model that the Java EE expert group sees as the most pure and ideal one?

The way we do it is packaging the files that define the JMS queues, data sources etc inside the EAR. Then with an environment option (-D) on the commandline, we specify which stage we're deploying in. The application server that we use (JBoss AS 6), supports this by referencing those files from jboss-app.xml. E.g. conf/${our.staging}/database-ds.xml, where we startup JBoss with eg -Dour.staging=dev.

For small agile teams with a (separate or not) devops team, this greatly reduces complexity. Developers can directly update the resource files whenever their code requires something new, devops does sanity checking on this, and deployment is completely hassle free.

The Java EE deployment model seems to be tailored for large enterprises where developers and operations don't trust each other or maybe even blindly hate each other. It ensures that developers don't get to see what the live configuration is going to be that their code runs on, and makes it incredibly painful to have something as simple as an internal JMS queue added (since a JMS queue is an administered object and must be created by operations, who of course always initially refuse to do so just because they can).

Following this model, developers then use workarounds. E.g. instead of a JMS queue they use a LinkedBlockingQueue, or maybe do some hack to create the JMS queue programmatically somewhere. Thinking of it, it's really a bit silly that something as simple as the following is considered 'configuration'

<queue name="myQueue"><entryname="/queue/myQueue" /></queue>

Java EE allowed (simple) data sources to be defined in application.xml or via an annotation. The latter is mainly for prototype code, but the first could be a serious candidate for having these kind of things defined inside the EAR. If this could be expanded to JMS destinations, then it would be great!

Reza Rahman replied on Mon, 2011/06/13 - 10:36am in response to: Henk De Boer

Henk,

The real reason it has been historically difficult to standardize resource configuration is that they differ from vendor to vendor so much. That's why the standardized data source configuration in Java EE 6 is so sparse. Things are even worse for JMS. That being said, I hear your pain and we (I and Antonio) can see if at least some basic JMS configuration can be standardized in Java EE 7.

For now, I would say simply continue to provide deployers XML fragments of resource configuration. Most application servers like GlassFish, JBoss and Resin support that. In fact, in case of Resin you can package database configuration with the application.

Thanks for the input and keep it coming.  Also, I encourage you to join the Java EE 7 JSR user open aliases (you do not have to be a JCP member in order to do so).

Cheers,

Reza

Henk De Boer replied on Mon, 2011/06/13 - 12:08pm in response to: Reza Rahman

The real reason it has been historically difficult to standardize resource configuration is that they differ from vendor to vendor so much. That's why the standardized data source configuration in Java EE 6 is so sparse.

I understand. Yes, there are many differences. On the other hand, there are also much more similarities then the standardized data source configuration currently allows to be set. In the past we made extensive use of DBCP, then the newer Tomcat connection pooling, then the one from JBoss AS and in between for different jobs a handful of others.

Typically there's always a connection between defining a data source and defining pooling properties. As such, there's typically a min and max for the number of pooled connections, a timeout to wait for a connection and the ability to enter a query for checking whether a connection is valid.

An in-between option to support advanced vendor features in a semi-portable way might be to do the same thing that's being done in persistence.xml: cover the most common features with standardized tags and allow vendor specific features via a <properties> tag,

 

That being said, I hear your pain and we (I and Antonio) can see if at least some basic JMS configuration can be standardized in Java EE 7

That would be very nice. Thanks for looking into this! I found that for a great number of queues that we use (internally) in our applications, the configuration is nothing more than stating that the queue exists and what name it has. At least that should be relatively easy to standardize I think.

Reza Rahman replied on Mon, 2011/06/13 - 12:34pm in response to: Henk De Boer

Henk,

The issue is that connection pools are not standard -- so far. That being said, most Java EE application servers do implement them so we could see into that as well. Antonio's XML config idea would actually accomodate vendor extension meta-data quite nicely :-).

Cheers,

Reza

Craig Ringer replied on Wed, 2011/06/15 - 1:07am

I could not possibly agree with your sentiments more.

Java EE apps need a configuration mechanism that doesn't involve hacking the WAR and doesn't have to be re-implemented manually by each app using the underlying preferences api, config files on a custom path, or whatever.

@Alternative and beans.xml - deploy-time configuration and extension

There's more to configuration than just a bunch of parameters, though. In particular, I'm increasingly feeling the need for an overrides/extensions mechanism, allowing deploy-time addition of @Alternative bean implementations and control over @Alternative bean selection at deploy-time. It should not be necessary to hack the original war's beans.xml and insert additional classes into the war; this should be easily done using a deploy-time beans.xml override file that's merged in, and one or more JAR files containing the custom bean implementations that get added to the webapp's classpath at deploy time.

This would (finally) allow a user to deploy a pre-built WAR of a project, plugging in any site-specific extensions or configuration. Right now, users have to hack the sources of the project, rebuild the war with their changes, and maintain their customized branch of upstream as upstream changes. This is necessary whenever an app wants to support anything that individual sites might want to customise or that might be well suited to plugins, like new formats, support for different databases, different ways of storing files, or whatever.

Addition of user-supplied implementations of interfaces can currently be done using container environment resources via JNDI, but it's clumsy, painful to administrate, very container specific to set up, and generally requires a full container restart to change rather than a simple redeploy. More importantly, environment resources cannot reference interfaces or classes inside a war so it's even more clumsy for the user to plug in an @Alternative bean implementation; you need to provide a separate "myapp-api.jar" that goes in the container's lib directory for the user's bean implementations and your war to depend on. Ick!

roles vs users/groups, role mappings (Glassfish)

Another pain point for me at the moment is how, at least in Glassfish, mappings of webapp security principals to container users/roles must be configured in glassfish-web.xml inside the war file. That completely defeats the point of separating the concept of "principal" and "group/role", because the deployed sources have to be hacked to include those mappings!

The war should NOT need to be modified for site-specific, deployment-specific details. To fix this, it should be possible to specify a glassfish-web.xml overlay that's merged in at deployment time containing principal to user/group/role mappings, so the site can control these mappings rather than the application.

Even better, this mapping mechanism and a deployment-time override system for it could be standardized as part of Java EE7, so we wouldn't need container-specific crap for mapping principals to users/roles/groups anymore.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.