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:
<configuration> <stage name=“development”> <jms-destination-factory> . . . <jms-destination-factory> <data-source> . . . <data-source> . . . </stage> <stage name=“test”> . . . </stage> <stage name=“production”> . . . </stage> </configuration>
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:
META-INF/ META-INF/MANIFEST.MF EnterpriseApplication1-ejb.jar org/javaee8/ org/javaee8/samples/ org/javaee8/samples/wildfly/ org/javaee8/samples/wildfly/MyTestBean.class EnterpriseApplication1-war.war WEB-INF/ WEB-INF/classes/ WEB-INF/classes/org/ WEB-INF/classes/org/javaee8/ WEB-INF/classes/org/javaee8/samples/ WEB-INF/classes/org/javaee8/samples/wildfly/ WEB-INF/classes/org/javaee8/samples/wildfly/MyTestServlet.class WEB-INF/lib WEB-INF/lib/myLibrary.jar META-INF/ org/ org/javaee8/ org/javaee8/samples/ org/javaee8/samples/wildfly/ org/javaee8/samples/wildfly/MyLibrary.class index.html
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.
Here my thoughts:
1. application.xml is for ear so configuration.xml maybe. If it needs a graphical tool it is surely it is not simple enough (would like to avoid too complicated and unusable descriptor, you comment just scared me a bit even if we all know graphical tools will exist).
2 and 5, 7, and surely 9. It is also important to get configuration path configurable from the environment (hardcoded, system property) to be able to deploy same war in several environments with different config. Both: all environments in a single place and configuration outside the app are mandatory. Having a configuration loader SPI (to read from enterprise specific configuration source like a database) would be great.
3. maybe something to wait for next iteration, would need a lot of spec before IMHO but nice goal ;).
4. Stages and resources (or sub stage items). This way pre-prod stage will inherit from prod stage but preprod datasource can inherit test datasource.
6. Not sure configuration is the place to do so. I’d rather link configuration stage to other spec which already define at the right place the defaults (default datasource, etc…)
8. Hmm, other specs already allow some indirection so once again if configuration spec is well done enough others can be based on it to read their needed data. Doing the opposite sounds not that safe to me
10. One configuration by application sounds the way to go first. Allowing subconfiguration will be more generic but surely harder to understand and manage in the everyday of an app. That said for a subset of features it is a great idea, so maybe a configuration-fragment.xml (but I really think it is not mandatory for the 1.0).
11. defining resources in a generic way would be awesome (based on properties?). It would also allow custom resources like in TomEE which is quite nice.
12. Think it should be another spec based on configuration one. Configuration and Versioning are both harder than it looks and mixing both is not a good idea and wouldn’t solve some issues since versioning needs more than only configuration. Can also be added later adding a VersionedConfiguration in 1.1 version for instance.
13. Awesome idea. Once thing to provide could be a fluent API to add resources etc on configuration events (CDI is too late but that’s the same idea).
14. I’d just allow as the BeanManager injection in CDI beans and extension, the injection of the stage. Simple and enough.
15. Exactly and a fully programmatic configuration would be awesome.
16. Not convinced for the first step (1.0). Then the question is: does the app/container takes it into account. All containers have a bunch of caches preventing it. Once this is tackled (hot reloading spec maybe) this will be a nice feature.
17. Exported by default? Can create security issues then. Sounds nice but maybe dangerous.
1. Agree with CDI approach.
2. Agree with environment specific settings.
3. Agree that DB override would be nice for config, defaulting to bundled XML, with dynamic change ability.
4. Not sure if JCache / JMS topic will feature. (propagating config change to rest of cluster)
5. Standard area for App Server to define environment name. Allow also for global settings. (not environment specific)
6. Console exposure for reading and updating config value to DB & cache. (maybe not API responsibility, but vendors)
7. Inheritance of configs good. All datasources use some standard properties.