Saturday, December 26, 2009

Say hello to the Seam 3 Environment Configuration module

A funny thing happened after my last post -- I got an email from Dan Allen, from RedHat, with some interest in making my last JCDI Portable Extension -- EnvironmentBindingExtension -- into a Seam 3 Module... pretty cool for a fairly modest effort at finding a new way to solve a problem I've faced in the past... it will be my first official foray into open source (not counting that one line NetBeans patch I submitted in, like, 2000), so it will be interesting to see how this will actually work from the authoring side, as opposed to the user side, especially in a relatively well organized project like Seam...

What it's about

The idea behind the Environment Configuration module is to inject fairly static configuration information into any JEE 6 environment... it's typically done outside of your application, in a deployment that isn't regularly deployed or updated, so you can configure each of your environments separately, including Development, Testing, QA, Staging and Production -- once this is done, you can build your application once (or better yet -- have a Continuous Integration server build it!), and copy the same binary from server to server without having to reconfigure it, ensuring that the archive that you deploy to production is the same exact archive that you tested in QA... this allows you to streamline your deployment processes, removing any possible human error involved in building your code over, and over, and over again (and in some cases, it'll save a lot of time if you have a particularly slow build!)

How's it work? It takes advantage of JNDI -- one of the resources that all JEE servers provide... say, for example, that you have a system that needs to access a database, a filesystem, and has a batch process that runs at a specific frequency -- in development, you'll want to point to a personal Derby database, use a local folder on your Windows box for your filesystem, and run the batch process very frequently for testing... QA is similar, although it has different database, but say Staging and Production run on a cluster of Linux boxes that access a MySQL database, use a mounted shared drive for its' filesystem, and have its' batch processes run once an hour...

With the Seam 3 Environment Configuration module, you can create a simple .ear file for each of these environments that contains all of this data -- create them once, deploy them once, and you're good to go... take a look at the following example of a configuration that you could use in development:


/**
* An Environment Configuration for Development
* @author Matt
*/
@EnvironmentBinding
@DataSourceDefinition (
className="org.apache.derby.jdbc.ClientDriver",
name="java:global/jdbc/AppDB",
serverName="localhost",
portNumber=1527,
user="user",
password="password",
properties={"create=true"},
databaseName="dev-db"
)
public class Config {
@Bind ("myApp/fs-root")
String rootFolder = "C:\fs-root";

@Bind ("myApp/batch-frequency")
long batchFrequencyInMs = 60 * 1000;
}


Pretty simple -- toss this class into its' own .war file, and it will define three global JNDI entries, one for each of the items mentioned above... your other applications are now free to read these resources in whatever way they need to, even using the standard @Resource(lookup="java:global/myApp/fs-root") notation... a similar configuration file would be created for QA, but perhaps the @DataSourceDefinition annotation will use a MySQL datasource, and likewise for Staging and Production...

What next?

Well, there are a few things on my list of features here, including, but not limited to:
  • Test, Test, Test!
  • Using the @Bind attribute on methods, including @Produces methods
  • Support 'unbinding', if needed
  • Create a Maven Archetype that could be used to quickly and easily setup an Environment Configuration deployment
  • Create an interface of some kind to be able to review the available findings -- either web app or simply JAX-RS based
I am, of course, interested in any ideas or feedback anyone would have, but one goal I would have here is to keep it simple and portable -- what this module is intended to do isn't exactly brain surgery, so I don't think it's necessary to throw in too many 'extras'...

M