tags:

views:

63

answers:

3

I have two Spring contexts declared in my application - one for Spring-MVC requests, and another for Flex/BlazeDS messagebroker requests, mapped to different url-patterns:

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

There's a common context configuration declared, (/WEB-INF/applicationContext.xml) and then each of the two contexts have their own configurations declared in spring-mvc-servlet.xml and flex-servlet.xml respectively.

Inside flex-servlet.xml I have beans declared which are specific to the flex context. However, when a call comes in to http://localhost/messagebroker/* I'm getting errors that those beans aren't available.

The code in question is inside a custom Spring component, so directly references the WebApplicationContext in order to access the declared beans:

public ISerializer getSerializer(Object source,boolean useAggressiveSerialization)
{
    ServletContext ctx = FlexContext.getServletContext();
    WebApplicationContext springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(ctx);
    String serializerBeanName = springContext.getBeanNamesForType(ISerializer.class);
}

This approach works when I'm running with a single context. However it needs to also support where there are multiple contexts running.

Setting a breakpoint, I see that the value of springContext is the root context, with a single configLocation - /WEB-INF/applicationContext.xml

I'm asssuming that this is the problem - as the ISerializer that the above code requires is declared in flex-servlet.xml.

How do I modify the above code to support both scenarios? (Single context, and multiple contexts)?

EDIT: The code shown above sits inside a ManageableComponentFactoryBean, which appears to operate as a custom bean factory. It seems that the ApplicationContextAware interface is not honoured on generated classes. Eg:

<bean id="dpHibernateRemotingAdapterComponentFactory"
    class="org.springframework.flex.core.ManageableComponentFactoryBean">
    <constructor-arg
        value="org.dphibernate.adapters.RemotingAdapter" />
    <property name="properties">
        <value>
            {"dpHibernate" :
                {
                    "serializerFactory" : "org.dphibernate.serialization.SpringContextSerializerFactory"
                }
            }
        </value>
    </property>
</bean>

The code quoted above sits inside the org.dphibernate.serialization.SpringContextSerializerFactory. Making this SpringContextSerializerFactory implement ApplicationContextAware has no impact.

+1  A: 

Declare your custom componente as Spring Context aware:

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public MyCustomBean  implements ApplicationContextAware {

  private ApplicationContext springContext;

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    springContext = applicationContext;
  }

  public ISerializer getSerializer(Object source,boolean useAggressiveSerialization)
{
    String serializerBeanName = springContext.getBeanNamesForType(ISerializer.class);
  }
}

At the bean initialization, Spring will access the setApplicationContext method of your bean, passing as an argument the context in wich it's being created. There, you can keep it an use it whenever you need.

Tomas Narros
good point, +1.
Bozho
Good suggestion - thanks. Unforutnately, it doesn't appear to work. I've updated the original question with the relevant config related to this problem.
Marty Pitt
+3  A: 

If flex is a DispatcherServlet, and for some reason you can't follow Tomás Narros's suggestion, you can obtain a context associated with the current DispatcherServlet using RequestContextUtils.getWebApplicationContext(request).

There is also a convenience method RequestContextUtils.getWebApplicationContext(request, ctx), which returns the root context if DispatcherServlet's one is not available.

axtavt
a nice util to know, +1
Bozho
This did the trick! Thanks very much
Marty Pitt
+1. Quite useful in some environments. @Marty: if this did solve your question, accept axtavt answer.
Tomas Narros
A: 

Hrmmmm.....I have nearly that exact sort of declaration in my Spring/Flex app, using Spring/Flex integration and there is only one application context. Could that be the problem? You have beans declared in the Flex context file that aren't in the MVC context file, and they aren't really getting loaded?

mezmo
Hi. The critical aspect here is that there are two dispatchers - for good reason. One routes Spring-MVC requests, the other Flex messagebroker requests. The two are seperated so the routing doesn't interefere with each other.
Marty Pitt
With Spring BlazeDS you can use the Spring MVC DispatcherServlet to handle the AMF / Flex requests as well so I'm not sure why you need two different contexts.
James Ward