2.5. Using Flex clients alongside Spring MVC Controllers

It could often be the case that your application needs to serve more than just Flex-based clients. For example, you may be constructing a RESTful architecture that is meant to serve multiple client-types. You could potentially even be consuming RESTful endpoints using the Flex HTTPService component. Spring MVC's controller model provides a simple, flexible means to create such RESTful endpoints. In these sorts of hybrid web application secenarios, you will need to consider an alternate mapping strategy.

The simplest approach is to use a hierarchical application context with multiple DispatcherServlets. In this approach, you configure your main application layer (services, security, supporting infrastructure, etc) in a parent context loaded via the ContextLoaderListener, and then configure all aspects of your Spring MVC controllers in one child DispatcherServlet context, and all aspects specific to your Flex client in a separate child DispatcherServlet context. This approach could look as follows in web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/*-context.xml
    </param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>flex</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

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

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>spring-mvc</servlet-name>
    <url-pattern>/spring/*</url-pattern>
</servlet-mapping> 		
		

Here the parent application context is being assembled from a group of files ending in -context.xml contained in the /WEB-INF/spring/ directory. The child context for the Flex-specific setup would be built (by convention) from /WEB-INF/flex-servlet.xml, and the context for the Spring MVC controllers would be built from /WEB-INF/spring-mvc-servlet.xml. This approach provides a nice separation of concerns and will allow Spring 2.5+ annotated controllers to work using their default configuration.

An alternate approach is to keep things consolidated under one DispatcherServlet context. The down-side to this approach is that it requires some additional manual configuration, and you have to modify your mapping approach accordingly, such as mapping /spring/* to the DispatcherServlet, mapping /messagebroker/* to the Spring-managed MessageBroker via the mapping XML namespace config tag, and modifying any BlazeDS channel definitions accordingly. You would override the default mapping strategy of the message-broker tag as follows:

<flex:message-broker>
    <flex:mapping pattern="/messagebroker/*" />
</flex:message-broker> 		
		

and you would have to account for the /spring/* mapping in your BlazeDS channel definitions. For example:

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
    <endpoint url="http://{server.name}:{server.port}/{context.root}/spring/messagebroker/amf" 
    	class="flex.messaging.endpoints.AMFEndpoint"/>
    <properties>
        <polling-enabled>false</polling-enabled>
    </properties>
</channel-definition> 		
		

In addition to setting up the consolidated mapping strategy, you will also have to manually enable the correct HandlerMapping and HandlerAdapter for your Spring MVC controllers as described in the Spring MVC documentation, due to the fact that alternate HandlerMapping and HandlerAdapter beans are configured automatically when using the message-broker tag.