Integrating Adobe Flex with Struts 2 and JBOSS Using BlazeDS

The first step of this process will be to able to run BlazeDS on JBOSS without struts 2. If that is not working yet for you please do that first.
The main reason that Struts 2 and BlazeDS out of the box fail to work together is because most configurations of Struts 2 intercept all HTTP requests to a web application. This is because of this piece of configuration in web.xml:

<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
 <filter-name>struts2</filter-name>
 <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
 </filter>

This is a java filter that intercepts all requests and responses. This is a problem because most instructions on how to setup BlazeDS ask you declare the following servlet in your web.xml:

<!-- MessageBroker Servlet -->
<servlet>
<servlet-name>MessageBrokerServlet</servlet-name>
<display-name>MessageBrokerServlet</display-name>
<servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>MessageBrokerServlet</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

However this will never work with Struts 2 unless you restrict the url pattern to something less than /*. Filters seem to be executed always before any servlet declared in web.xml.

To solve this problem, instead of declaring the MessageBrokerServlet as a servlet lets declare it as filter in the filter chain. Filters declared in a filter chain are always executed in the order that they are declared in web.xml. For that reason make sure that this filter is always called before the Struts 2 filter(FilterDispatcher). If our filter determines that there is an incoming request that needs to be handled by BlazeDS, we call the MessageBrokerServlet, and we prevent any more filters in the chain to be called. If the request is not for BlazeDS the filter will not be called.

package uk.co.spltech.web.filter;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.mock.web.MockServletConfig;

import flex.messaging.MessageBrokerServlet;

/**
* The MessageBrokerServlet has a lower priority than Filters, regardless of the url-pattern
* we use. For that reason I created a filter that directly extends the MessageBrokerServlet but
* behaves as a filter. This might be quite dodgy but that's the only way I found to integrate struts
* 2 and Adobe Flex/BlazeDS. Anyone who knows a simpler way please email me at info at spltech.co.uk
*
* @author Armindo Cachada
*
*/
public class FlexFilter  extends MessageBrokerServlet implements Filter{

public void destroy() {
super.destroy();
}

/**
* If this method is called the parent service method of the MessageBrokerServlet is called,
* which does whatever BlazeDS needs to do to communicate with the flex client. Note Here
* that any subsequent filter will not be called because I am not invoking filterChain.doFilter/
* That is on purpose, because if it does, the normal struts 2 action mapping mechanism will be called.
*
*/
public void doFilter(ServletRequest servletrequest,
ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException {
this.service((HttpServletRequest)servletrequest, (HttpServletResponse)servletresponse);
}

/** Note the use here of MockServletConfig. This utility class is available in the spring framework. It is  meant
to be used for testing but I am actually giving it a real purpose :)
*/
public void init(FilterConfig filterconfig) throws ServletException {
System.out.println("filter called");
MockServletConfig servletConfig = new MockServletConfig(filterconfig.getServletContext());
Enumeration filterParameters = filterconfig.getInitParameterNames();

while (filterParameters.hasMoreElements()){
String filterParameter = (String)filterParameters.nextElement();
System.out.println("Found parameter: " + filterParameter);
String value =filterconfig.getInitParameter(filterParameter);
servletConfig.addInitParameter(filterParameter, value);

}
super.init(servletConfig);
}

}




Add the following to your filter chain in web.xml:

<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>

<filter>
<filter-name>flex</filter-name>
<filter-class>uk.co.spltech.web.filter.FlexFilter</filter-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
</filter>

This solution did the job for me. Please let me know if it also works for you!