Managing Environment Specific Configuration with Seam
June 17, 2008
Swapping configuration between development and production (and often other environments) is usually a custom solution but often follows a general pattern. Personally, I usually leave this up to properties files. For instance, let’s say we have a specific URL for an adding service and let’s say the URL changes between the development and production environments. Obviously we would want to automate this.It is quite simple to define a component to invoke the service using Seam:
package com.solutionsfit.example.service;
@Scope(ScopeType.STATELESS)
public class AddingServiceFacade {
private location;
private port;
public int add(int num1, int num2) {
// invoke service at location and port
// ... ...
}
// getters and setters
// ... ...
}
Once defined, we can simply create a namespace for this component (as shown in this previous posting) and our configuration in components.xml becomes simple:
<components xmlns="http://jboss.com/products/seam/components"
xmlns:service="http://solutionsfit.com/example/service"
... ...
<service:adding-service-facade name="addingService"
location="@addingServiceIpAddress@" port="@addingServicePort@" />
... ...
The wildcard attributes above are replaced by our components.properties definition:
addingServiceIpAddress=192.168.0.1 addingServicePort=9999
The properties are set into our component at create time and invocation is now as simple as injecting the component:
@Name("addingAction")
public class AddingAction {
@In
private AddingServiceFacade addingService;
// ... ...
public void addNumbers() {
result = addingService.addNumbers(num1, num2);
}
}
Since this definition changes between development and production we simply maintain properties files specific to each environment aptly named: components-dev.properties and components-prod.properties. A simple ant target (or Maven profile) resolves the appropriate properties file based on environment when creating the archive that is being deployed.
This becomes even more useful when creating integration tests. An additional properties file can be defined that specifically defines the integration testing properties for your automated tests (e.g. components-test.properties). The integration test target can then use this properties file for running automated tests, avoiding any additional setup in the tests, and allowing a full integration test to be run.
So my question, how are you managing your environment-specific configuration with Seam?
UPDATE: This approach will be supported in Seam 2.1 as a feature of seam-gen’d projects as part the profiling functionality. See JBSEAM-3157 to patch your existing seam-gen’d project.








Posted in
content rss
June 19th, 2008 at 6:06 am
Jacob,
Good and very well-written article indeed. I would suggest an alternative technique to adding the (test, prod etc) prefix to name of each file and then putting all such files into a single folder. You could \instead create a separate folder for each inside some root directory and then, put the specific files inside the respective folders. For example, if test, prod are 2 environments, create 2 folders: test and prod. Copy test env version of components.properties to test folder and prod version of components.properties to prod folder and do the same for all other env specific files. That is it. This approach makes the env-specific files very easy to navigate and browse. With this, you can also associate permissions with files in a specific by simply configuring the permissions on the respective folder.
Thanks
June 19th, 2008 at 6:07 am
By the way, I do like the captcha ):=. Is this the custom Seam captcha you were talking about a few days ago?
June 19th, 2008 at 7:02 am
No, the captcha being used on my blog site is reCAPTCHA. I am a big fan of reCAPTCHA, very easy to use, and looks good. Perhaps I’ll post a blog entry on integrating reCAPCHA into a Seam application if there is interest. The Java plugin can be found here.
July 22nd, 2008 at 7:18 pm
I manage it by letting you do it.
August 5th, 2008 at 5:01 am
Well, I have a Seam service that reads the property file and parses the parameters, setting them in the context. If I only knew this was possible through components.xml…
On a side note, would the component be required to be a seam component, or would this work for @Service:s, MDB:s and EJB:s too?
August 6th, 2008 at 9:17 pm
For this approach it would be required to be a Seam component, but as I’m sure you are well aware it is quite easy to make EJBs Seam components
Simply annotate them with @Name!