Multi environment artifacts

Too many times I’ve seen this anti-pattern applied. So many that I’m here writing about it with the hope some of those applying it will read this post and stop doing it.

The anti-pattern I’m referring to is the one I christened Environment Aware Artifact, also known as The Production Build. If you don’t understand what I mean it is very possible you are either working in a single environment project (very unlikely) or you are actually applying this anti-pattern. In both cases, please keep reading!

The principle is simple: ensure your deployables/builds are environment agnostic. What that means truly depends on your specific application, but usually it can be condensed into this simple statement: externalize your environment configuration so that it is NOT bundled within your deployable but deployed separately.

Let me try to explain the previous sentence by using a Java example, but please consider this anti-pattern does not apply to Java environments only.

Say that you are developing a web application (what about an eCommerce web site?) which needs to invoke some sort of external service (let’s say it is the ePayment system). Probably you have to use different URIs for the external system depending if you are in a test environment (you don’t want to use the real ePayment service for your tests, do you?) or in a production environment (you want to collect real money from your customers, right?).

If you are a supporter of this anti-pattern you will create a configuration file (if it’s a Java properties or an XML it doesn’t matter) which will end up within your WAR: by doing this you will tie your deployable (the WAR file) to a specific environment (the one the configuration file refers to).

If you are asking yourself “What’s wrong with that?” then you are one hundred percent contributing to this anti-pattern: you are the reason for this article! The problem is you will have to rebuild the deployable every time you move from one environment to another which introduces errors and issues you would never expect (you can either trust me or experience them on your own skin, your choice). On top of that you are exposing environment related, potentially security related, information (what if instead of a URI we were talking about a password?), to everybody who is involved into the build chain!

If you are asking yourself “How can I achieve that?” you are starting to understand it is indeed an anti-pattern and I’m glad you are! As you can imagine different tools, systems, platforms and languages have separate ways of achieving such goal, some being simpler others being more complex. In other words you have to investigate your own selection, but in case you are using one of the platforms I use here are some advises.

Please consider it is generally more important to have an environment agnostic deployable rather than a container agnostic one: more than often the type of environment surrounding your final artifact is either pre-determined (corporate or project decision) or highly definable (installation instructions). If you have to decide between adding a step to your installation procedure and building multiple artifacts the former is 99.99% preferable!

JBoss AS

Starting from version 4 of this wonderful application server you can provide system environment properties through the properties service: just put your environment specific configuration in a properties file and add that file to deploy/properties-service.xml to have them exposed to your deployables. Starting with version 7 the file name changed to standalone.xml or domain.xml, depending on the application server startup mode. Properties set as such will be readable as system ones.


I believe this feature has always been there, for sure starting from version 5.5 of the web container. It is part of the context definition and documented as, guess what, environment entries. Please note these configuration mode is readable through JNDI.

Other JavaEE containers

Most of the containers out there provide the ability to specify environment properties using their management interfaces, being them JNDI bound or available as system properties. Please refer to your container documentation.

Any JVM language in general

This is applicable to every language based on the JVM and any environment: deploy into the system JRE a library containing a configuration class which provides your configuration parameters. While this solution might be sub optimal in certain environments it’s definitely applicable to a broader set of cases, including desktop applications. With the proper adjustments it is applicable to many other platforms/languages as well, including C#, .NET and so on.


4 thoughts on “Multi environment artifacts

  1. It’s definitely a good idea, but as you say, very much dependant on the environment. This is particularly tricky to get right on mobile devices.

    Since you are “deploying” to an user device you can’t count on them having any environment variable, config file or similar.



    • Oh sure you can, it’s just going to be a little longer path, but there’s always a way to externalize a resource from your archetype: what about retrieving such information from a fixed URI to which you post your device ID and, based on that, an environment configuration is returned? I know, there are easier methods, some that might work on iOS, some might work on Android, but I believe this should be available to any platform which has some sort of network connectivity.
      If the device ID is not recognized then the production environment configuration is returned, so you don’t have to list all you mobile application users.

      If your app should be available offline or doesn’t require connectivity you can bundle the production configuration and use the URI as an overriding config: if the URI is unreachable or no mobile ID matches than use the bundled config.

      What do you think about it?


      • Ummm, not sure I’m convinced! It’s not so much a device ID (as in testing devices) since we need to constantly change the environment to which a device is pointing to in different stages of testing: sometimes you need to check something on production, sometimes a fix on the staging environment…

        You’d need to be able to *quickly* change in the backend the environment to which a particular device is pointing to. I can see this being problematic, since when building client side applications chances are you do not have access to the backend CMS / team at all.

        We have used the default-to-some-environment-but-change-to-another-one-if-you-find-this approach, but we only do that on debug/test builds : )

        Production builds are hardcoded to the production servers, no questions asked.

        You could also compile the app to ask the backend for a particular environment (, which would be production by default, but again, you would be compiling differently for different environments, so not much of a difference.

        I don’t see an easy way out for client side apps, even if I totally agree with the idea of your post.


      • I’m not sure you got my suggestion… I’m talking about a configuration HTTP service to which you send a GET request containing your mobile device ID as Authentication HTTP header, the service returns a configuration for your device containing every parameter environment related (service endpoints, log level, etc…). By changing the id to environment configuration association within your configuration service you change the environment your device points to.
        Bind the config service request to the application boot and all you need to do to change the environment your device points to is reboot your app: this, in combination to the production default should be a viable compromise, add a cache HTTP header to your response and you can get a configuration system capable of working in production so to get a production benefit from a test solution ;-D


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s