Packaging For Different Environments

It is often necessary to create application configuration that varies by runtime environment. For example, service endpoint URLs, JMS connection information, and JDBC data source URLs may differ for testing and production environments.

To satisfy these requirments, Fabric3 provides named environments for composite activation and the ability to define configuration templates for use in a composite file.

Named Environments

Named environments such as "production", "testing", and "development" can be configured in the runtime systemConfig.xml using the <environment> tag as shown below:

<config xmlns="urn:fabric3.org">
   <runtime environment="testing"/>
</config>

In the above example, the runtime will be booted in the "testing" environment. If no value is specified, the runtime will be booted in the default "production" environment.

It is possible to control which environments a deployable composite is deployed in via the @environments attribute in sca-contribution.xml:

<contribution xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:f3-tests="org.codehaus.fabric3.tests">
    <deployable composite="f3-tests:ProductionComposite" environments="production"/>
    <deployable composite="f3-tests:TestComposite" environments="development test"/>
</contribution> 

In the above example, ProductionComposite is configured to deploy only when the runtime is booted in the production environment. TestComposite, in contrast, specifies a space-delimited list of environments. Specifically, it will be activated when the runtime is booted in the development or test environment. If no value is specified, the default production value will be used. This means that if an environment is not specified for a runtime in systemConfig.xml and a deployable composite entry does not contain an @environments attribute, the composite will be activated as both values will default to production.

Creating Environment-Specific Configuration

Using named environments, an application can specify datasource, JNDI, and other resource configuration that is specific to an environment. It is also possible to activate a set of components for a specific environment. To do this, place the resource definitions in a composite or set of composites that are configured to activate in production, testing or some other environment. These composites can then be contained in a single contribution or in an external contribution.

Configuration Templates

Binding configuration such as endpoint addresses may often change from testing to production. Fabric3 provides a simple templating mechanism whereby this binding information may be substituted at deployment time. The following demonstrates how to use <binding.template> to substitute web service configuration:

<component name="TestClient">
   <implementation.java class="..."/>
      <reference name="service">
         <binding.template name="TestServiceBinding"/>
      </reference>
</component>

The <binding.template> element instructs the runtime to substitute the specified template when the contribution is installed. The template is defined using the <template> element in a composite:

<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
           xmlns:f3="urn:fabric3.org"...>

    <f3:template name="TestServiceBinding">
        <binding.ws uri="http://localhost:8900/TestService"/>
    </f3:template>

 </composite>

The template composite can be contained in the same contribution or placed in a different contribution. If it is in the same contribution, the named environments feature described above can be used to activate different template definitions depending on the environment. For example, production and testing template composites can be provided.

As previously mentioned, it is also possible to place composites containing template definitions in a different contribution. In this case, the contribution containing the template must be installed prior to any contributions containing references to it (Note that the Fabric3 capabilities ordering feature can be used to have the runtime automatically order template and referring contributions).

By creating a separate contribution containing templates, it is possible to reuse template definitions across applications. For example, multiple applications may reference the same web service or REST endpoints. A standardized contribution containing templates for the endpoints can be reused across those applications. Within that contribution, it is also possible to configure specific templates for production and testing.

Specifying Template Definitions in the System Configuration

In addition to including template definitions in a contribution, it is also possible to specify them in the controller systemConfig.xml. Note participant runtimes do not need to have template definitions as the information is only used by the controller. The following shows how to specify a template in systemConfig.xml:

<config xmlns="urn:fabric3.org" xmlns:f3="urn:fabric3.org" xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912">
    <web.server>
        <http port="8900"/>
    </web.server>
    <templates>
       <template name="SystemConfigTestServiceBinding">
          <sca:binding.ws uri="http://localhost:8900/TestService"/>
       </template>
    </templates>
</config>

Note that namespaces must be used for template configuration

Stubbing Binding Templates in Testing

Sometimes it is necessary to stub out a binding template for testing. For example, a component may take an optional reference that must be explicitly bound to an external service. The composite containing the component contains a binding template configuration. For testing, the external service is not needed. The binding template can be defined using a blank binding.sca, which will result in no binding being applied to the reference:

<config xmlns="urn:fabric3.org" xmlns:f3="urn:fabric3.org" xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912">
    <web.server>
        <http port="8900"/>
    </web.server>
    <templates>
       <template name="SystemConfigTestServiceBinding">
          <sca:binding.sca/>
       </template>
    </templates>
</config>

JPA/Hibernate Overrides

Persistence context configuration can also be specified in an environment-dependent fashion similar to the way templates are. For more details, see Hibernate and JPA.