tags:

views:

55

answers:

3

I have two spring config files and I'm specifying them in my web.xml as in below.

web.xml snippet 

..
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/classes/domain-context.xml WEB-INF/classes/client-ws.xml</param-value>
</context-param>
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
..

From my domain object I have to invoke a Web Service Client and in order to get a reference to the Web Service client I do this:

ApplicationContext context = new ClassPathXmlApplicationContext("client-ws.xml"); //b'cos I don't want to use WebApplicationContextUtils
ProductServiceClient client = (ProductServiceClient) context.getBean("productClient");
..

client.find(prodID); //calls a Web Service 
..

However, I have concerns that looking up the client-ws.xml file and getting a reference to the ProductServiceClient bean is not efficient. I thought of getting it using WebApplicationContextUtils. However, I don't want my domain objects to have a dependency on the ServletContext (a web/control layer object) because WebApplicationContextUtils depends on ServletContext. What is the best way to get a reference to a spring bean in the backend layers?

Thanks!

A: 

This code:

new ClassPathXmlApplicationContext("client-ws.xml"); 

will create an entirely new and separate application context to the one defined in your web.xml. Efficiency is one thing but a bigger issue here is correctness.

A bigger issue is that directly calling a bean by name is not really what dependency injection and Spring are all about.

What exactly do you mean by "domain object"? If possible, this object should be made "Spring-aware" and the WS client should be injected by:

  • explicitly injecting it from the application context (probably not applicable to a domain object but mentioned for completeness);

  • using @Autowired; or

  • using @Configurable.

cletus
+1  A: 

Why would you not inject the client into the back end bean? "Don't call us, we'll call you" - objects should be given their dependencies. That's what Spring and DI are all about.

duffymo
+3  A: 

I prefer to inject the Spring container into an applicationContext variable. Spring supports this with the ApplicationContextAware interface. Then it's easy to ask for a new bean from the code.

An example:

public class ContextAwareFactory implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public String getConfigValue() {
        return (String)applicationContext.getBean("config-value");
    }
}
Espen
Thanks, I like this idea. But if I make the getConfigValue method and applicationContext static - is that a bad idea/design?
java_pill
If you have a reference to the factory from all the object's that needs it, then you should just inject the factory with Spring. Else, a static method is a good alternative.
Espen