Configuration JSR in Java EE 8 - What should be covered ?
GeeCON 2014 was very inspiring! A really greet feeling from the Polish Java community, awesome bunch of organizers (Andrej (@ags313), Adam (@maneo), Konrad (ktosopl), Adrian (@adrno), rest of the gang is just super nice), great technical content, courteous and helpful volunteers, lots of socializing space/opportunities, and most importantly fun! This was my second GeeCON and would love to go back there next year.
During speakers’ dinner, Anatole (@atsticks) and I were talking about the Configuration JSR (scheduled to be part of Java EE 8) and he shared the proposal. Instead of reading the proposal, I decided to put my thoughts down first so as not to be tainted by it. So this blog describe the use cases that I think this JSR should address. This by no means is a comprehensive list, or in any particular priority order. It is solely intended as input to the JSR and Expert Group based upon Anatole’s request, Laird Nelson (@chuggid) is the other spec lead on this.
Here goes the list ...
- Application-wide configuration may be provided using XML-based configuration (application.xml ?), Annotations, and a programmatic Java API. A graphical web-based tool may simplify generation of these artifacts as well.
- One of the primary concerns during devops is the ability to take the same WAR file from development, to testing, and finally to production. Unzipping the archive and bundling a different deployment descriptor to point to different databases/servers is used as a workaround, but not recommended. If configuration is specified using a XML configuration file, then there should be the ability to specify configuration for all of these stages. Each stage could point to a different JMS destination, JNDI reference for data source, port numbers, etc.For example:
. . .
. . .
. . .
. . .
. . .
In addition, a mechanism to trigger a particular stage would need to be defined. An external configuration tool that can trigger a particular environment may be one way to achieve this. Relying upon environment variables does is not a good idea.
Custom stages should be permitted as this would allow to target different environments for stress, performance, regression, integration, and different sorts of testing.
All of this, of course, would work for Java EE components only.
- Configuration may not be restricted to only Java EE components. It may include the max amount of memory that the application could use on the server, whether high availability is enabled or not, min/max number of servers in a cluster, etc. This would require to specify the configuration outside of Java EE context.
- Stages may inherit from other stages. This would allow a production environment to point to the test database rather easily. In this case, inheritance rules would need to be defined.
- Application configuration may be specified exclusively outside the application. This could be done using the graphical tool, and stored in a persistent store. This would allow a system administrator to easily pick a particular configuration.
- Reasonable defaults should be defined for the entire application, such as more logging/debugging during development stage. This will allow containers to spit out more detailed and useful information during different stages. For example, JSF displays an error message on XHTML page, even if there is no place holder for it, during development phase but hides it during the production stage.
- A mechanism to store all the configuration information in a variety of persistent stores would be useful. One of the common ways could be “application.xml” as a file, typically bundled in the archive itself. Storing this information in a relational database could be useful as well. This would allow developers to focus on application configuration during development, possibly using annotations or "application.xml". And then retrieve a testing/production configuration from a database when targeting those stages.
- An archive would typically have a "persistence.xml" and a "web.xml". Explicit rules on how the values defined in those individual files are overridden by application-wide configuration needs to be defined. These rules would need to be defined amongst the different ways configuration is enabled, for example "application.xml" overriding the values set by annotations.
- Going a step further, it may be relevant to even provide a standard schema on how this information is persisted. Vendors may provide their extensions to it, but at least a basic schema would ensure some level of portability.A development database bundled with the application server would work during development stage. But typically a more enterprise and reliable database would be used during production. So one more step further, a standard way to connect to these databases would be useful.
- A typical EAR file may look like:
The scope of how/where an annotation is defined needs to be clearly specified. Whether "application.xml" can be defined in a JAR file bundled in WEB-INF/lib in an EAR file ?
If so, what are the overriding rules ?
Can it only be specified on the top-level archive ?
What happens if there is a conflict ?
- JSR 236 did not specify how different managed objects can be configured, and this is a gap in the existing specification. If JSR 236.next is not being planned or not planning to address it during Java EE 8 timeframe, then this JSR should attempt to address that.
- Different application servers have their own means to deploy multiple versions of an application. This allows multiple versions to be deployed but only one version to be enabled at a given time. It would be nice if application versioning can be addressed by this JSR.
- Pre/post hooks for deployment, and other stages, should be made available. These can be used by sysadmins to provision resources required during deployment/runtime.
- CDI events for different stages may be generated. This would allow different parties to listen, and react to them.
- A Java EE 8 application may not need any deployment descriptors of the past. Bundling either just this "application.xml", or specifying the configuration information externally should be enough.
- Reload of configuration information should be possible, without deploying the archive.
- A REST schema of all the configuration information handled by the JSR will really simplify how vendors can easily build custom tools on it.
- Other frameworks like Ruby-on-Rails and Grails allow application-wide configuration and we should learn from them, and adopt their best practices.
Now that my own thoughts are listed here, here are some additional ones after reading the proposal …
- There is no mention in the JSR for an XML-based deployment descriptor. Even though non-Java EE components will be specified outside the scope of Java EE, but I think having a descriptor to specify the configuration for Java EE components is useful.
- +1 on not defining a new archive format and Anatole has explained it well in the blog.
- I strongly prefer the second approach integrate this new functionality with all existing JSRs as that keeps the approach simple, and scalable to any future specs as well. This JSR should define an overall framework, and how other JSRs would specify the configuration. Individual component JSRs then should leverage that and define the exact configuration points. Ideally, each component specification should have an explicit chapter dedicated for configuration.
- KISSing is good and I like the proposed simplistic approach of using a Map to store all this information.
What do do you think should be the scope of this JSR ?
Added a calendar reminder to revisit this blog in a year, and another one in +1 year, and see how many of these points actually make it in the spec.