Change Apache Struts2 Configuration Programmatically

One of the myth of Apache Struts2 configuration is to programmatically changing the Struts constants (Struts’ name of settings) in our application. This article shows how to do this.

Like the rest of the posts, I would state my problem first:

  • I am building a Java web application.
  • Many 3rd party libraries are used e.g. Struts2, Hibernate, Spring DI.
  • Changing configuration of the system requires me to memorize the correct library’s way of configuration.
  • Different libraries has different configuration files and methods.
  • One of my problem is to configure the maximum file upload size, which involve Struts’s configuration.

My goal:

  • Centralize all configuration into one .ini file, by changing that one and the only one file, the settings will be applied to all sub-systems.
  • Primary goal is to allow the system to apply the settings in the .ini file at application startup, changing configuration during runtime is not essential.

Some of the key configuration values are:

You can read the list of struts properties in Strut’s documentation (2.3.x).

Findings

As a result, I need to find a way to programmatically change the Struts’s configuration at startup.

Most of the tutorials found on the web just tell you to edit the Struts2 configuration files e.g. struts.xml, struts.properties. When you google for the words “struts change configuration programmatically“, some clever results show up like:

However, they are all related to changing the struts.devMode parameter only via code.

In Struts’ Core Developer Guide, under the section Architect’s Guide there is a page Configuration Provider & Configuration which describe framework configuration. However the page does not provide any further details nor sample code.

After further digging into the Dispatcher class, I found that the com.opensymphony.xwork2.config.ConfigurationProvider is the key to the answer.

Solutions

This involve two parts:

  1. Implement the interace com.opensymphony.xwork2.config.ConfigurationProvider.
  2. Configure the StrutsPrepareAndExecuteFilter in the web.xml to use the ConfigurationProvider subclass.

Code

First create a class which implements ConfigurationProvider.

package helloworld;

public class MyConfigurationProvider implements ConfigurationProvider {
  public void destroy() {
  }
  public void init(Configuration configuration) throws ConfigurationException {
  }

  public boolean needsReload() {
    return false;
  }

  /**
   * Place your logic on read external configuration here.
   */
  public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {

    // read external configuration. MyConfiguration is our own written class which 
    // provides access to configuration file. You should write your own way to do this.
    String fileMaxUploadSize = MyConfiguration.getConfig("max_file_size");

    // save the external configuration to the LocatableProperties which will be 
    // used by Struts.
    props.setProperty("struts.multipart.maxSize", Long.toString(fileMaxUploadSize));

  }
}

This class is the key component which is responsible for reading external configuration source and alter Strut’s configuration.

Next step is to add this provider to Struts.

After a long time web searching, I found that it is StrutsPrepareAndExecuteFilter which allows configuration – documentation is so hard to find! Also, in the class Dispatcher‘s method init_CustomConfigurationProviders, it reads a configuration value configProviders which accepts a list of comma-separated ConfigurationProvider classes!

Now edit the file web.xml and configure the Struts filter:

<filter>
  <filter-name>action2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  <init-param>
    <param-name>configProviders</param-name>
    <param-value>helloworld.MyConfigurationProvider</param-value>
  </init-param>
 </filter>

Restart the application and it is done!

Advertisements

3 thoughts on “Change Apache Struts2 Configuration Programmatically

  1. Hi. Thanks for this post. It helps understand better, but it still fails ((((

    I use `struts.multipart.saveDir`, and I do set this property to the value I need, but after file upload it still uploads into the old path. Seems like `set` is doing it’s job, but it’s late.

  2. Very good post, it helped me a lot to understand how struts2 configurations ar loaded.
    I figured out that my configuration provider needed access to the servlet context, so I hacked the code of Dispatcher class to achieve this

    private void init_CustomConfigurationProviders() {
    String configProvs = initParams.get(“configProviders”);
    if (configProvs != null) {
    String[] classes = configProvs.split(“\\s*[,]\\s*”);
    for (String cname : classes) {
    try {
    Class cls = ClassLoaderUtil.loadClass(cname, this.getClass());

    ConfigurationProvider prov;
    try {
    Constructor constructor = cls.getConstructor(ServletContext.class);
    prov = (ConfigurationProvider)constructor.newInstance(servletContext);
    } catch (Exception e) {
    prov = (ConfigurationProvider)cls.newInstance();
    }
    configurationManager.addContainerProvider(prov);
    } catch (InstantiationException e) {
    throw new ConfigurationException(“Unable to instantiate provider: “+cname, e);
    } catch (IllegalAccessException e) {
    throw new ConfigurationException(“Unable to access provider: “+cname, e);
    } catch (ClassNotFoundException e) {
    throw new ConfigurationException(“Unable to locate provider class: “+cname, e);
    }
    }
    }
    }

    it worked.

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s