Previous Next

Technical Blog

January 25, 2010

Before the settings framework was introduced in EP, many environment specific settings were hard coded in config files contained within the WAR. Every time we performed a deployment, we needed to post-process the WAR artifacts to match the environment it was going to be deployed to. Although we had an automated way of doing this, it was not ideal for several reasons:

 

  • Each environment had a subtlely different WAR artifact
  • Additional steps during deployment increased risk without adding much value
  • It required us to build extra configuration artifacts.

 

When the settings framework was added, most of these environment specific settings were immediately migrated to the database. This was very beneficial, and almost allowed us ditch our WAR post-processing scripts altogether, but there were still a few configuration options that varied across our environments.

 

Two particular configuration options that were still defined in the WARs were the Acegi portMapper port values. Here is what the original portMapper definition looked like in acegi.xml:

<bean id="portMapper" class="org.acegisecurity.util.PortMapperImpl">
     <property name="portMappings">
          <map>
               <entry key="8080"><value>8443</value></entry>
          </map>
     </property>
</bean>

 

For some of our environments the port numbers were 8080 and 8443, but on others, they were 80 and 443, or 7080 and 7443. We wanted to be able to set this value once for a given environment and not have to reconfigure it again. We also wanted to leverage the settings framework to do this. We created a new setting and used Spring's factory-bean and factory-method attributes to dynamically inject the setting value into the portMapper bean

 

First we needed to get our setting into Spring as a bean:

<bean id="httpPortSettingValue" factory-bean="settingsService"
          factory-method="getSettingValue">
     <constructor-arg value="CUSTOM/STORE/storefrontHttpPort"/>
</bean>

 

The following bean definition instructs Spring to call the getSettingValue method on the settingsService bean with "CUSTOM/STORE/storefrontHttpPort" as a parameter, and make the result available as a bean. The return value of this call is an instance of com.elasticpath.settings.domain.impl.SettingValueImpl, which can now be referenced as a bean with id httpPortSettingValue. By itself, this can't be injected into the Acegi portMapper bean, but with the following XML, we can retrieve the string value of the setting:

<bean id="httpPort" factory-bean="httpPortSettingValue"
          factory-method="getValue" />


... and then inject it into our Acegi portMapper:

<bean id="portMapper" class="org.acegisecurity.util.PortMapperImpl">
     <property name="portMappings">
          <map>
               <entry key-ref="httpPort" value-ref="httpsPort"/>
          </map>
     </property>
</bean>

 

Our final code looks like this:

<bean id="portMapper" class="org.acegisecurity.util.PortMapperImpl">
     <property name="portMappings">
          <map>
               <entry key-ref="httpPort" value-ref="httpsPort"/>
          </map>
     </property>
</bean>

<bean id="httpPort" factory-bean="httpPortSettingValue"
          factory-method="getValue" />

<bean id="httpPortSettingValue" factory-bean="settingsService"
          factory-method="getSettingValue">
     <constructor-arg value="CUSTOM/STORE/storefrontHttpPort"/>
</bean>

<bean id="httpsPort" factory-bean="httpsPortSettingValue"
          factory-method="getValue" />

<bean id="httpsPortSettingValue" factory-bean="settingsService"
          factory-method="getSettingValue">
     <constructor-arg value="CUSTOM/STORE/storefrontHttpsPort"/>
</bean>

 

It is a little more verbose than the original, but you can shrink the XML by nesting the beans, or creating a helper method that retrieves the String equivalent of a setting value in one method call. In our case, this was as far as we needed to go.

 

If you're trying to find a way to pull some of these hard coded setting values out of the WAR, you may want to give this technique a try.

0 Comments Permalink