I haven't been able to find a complete best practices approach to using Spring with your web framework. I am currently using Spring and Struts together. As you know the ApplicationContextAware interface has the method setApplicationContext() which the app context calls, allows the use of app contexts (resources, events etc) – but it ties you to spring. I have read numerous articles and books that clearly state that you shouldn't tie yourself to spring and that having your objects implement ApplicatoinContextAware would do just that. However, these articles don't go on to demonstrate how this to prevent tight coupling to the framework and preserve context information across various tiers (inside and outside the container). I am utilizing Spring's IOC services by using a ContextLoaderListener and making calls in the action code within the container. All of this works fine. However, when I have to leave the container and make a call to my business tier, I need to preserve the context. The problem that I am finding, where there is little documentation is how preserve the contextual information from the webtier to the app tier with out having to:
1.)decorate the interfaces with a helper object that would otherwise wrap information normally kept in the context
2.)have every object implement applicationContextAware interface - which would tightly couple me to Spring.
3.)have a common service object (that all spring-i-fied objects would extend) - another form of tight coupling.
4.)code directly against the XMLBeanFactory (programatic approach to integrating with spring)
Your help is appreciated.
we are doing the same thing, using Spring in conjunction with Struts.
First up, let me ask you why exactly you need to pass the spring context through your business tier? Could you give an example?
Anyway, our approach is the following:
All our business logic services are collected in a single facade object that provides nothing but getters and setters for the service interfaces. This facade has all its dependencies (the service implementations) injected by Spring.
All the service implementations and their dependencies are also assembled by Spring (provided with other services, DAOs, etc.). This removes the need to access the ApplicationContext from within a service implementation.
All our actions extend a common superclass (which itself extends ActionSupport) that provides a getFacade() method which will extract the facade from the application context. The action superclass then delegates execution to an abstract doExecute() method.
This way, all our action code looks like getFacade().getSomeService().callSomeMethod(foo, bar);
Inside the service implementations, neither the context nor the facade is ever referenced. If a new dependency is added to a service implementation, the context is configured to inject that dependency.
This approach reduces the spring coupling to a single point: the action superclass, which could easily be replaced with a different implementation which for example constructs the facade and services in code.
Hope that helps...
Thanks for the help.
It looks like you draw a line in the sand as to how far back your framework will depend on spring. The facade is where all spring dependencies stop.
In my case, I need to go further back. I have business objects who's various methods need to utilize spring's services. I am looking for a way to do this without using a dependency injection. My only other alternative is to implement ApplicationContextAware. This is discouraged by the springframework team, because it tighly couples your code to spring.
I also have a services layer that uses Spring's IOC features. Across these various tiers, I am passing contextual information that is required so that various services dispatch to the appropriate service.
So to sum it up in a sentence, I am looking for a way to use spring through out my code base without relying on a dependency injection, or tighly coupling my code to the spring framework.
Anyone willing to offer some help be greatly appreciated.
If you really need Spring wihtout dependecy injection, then do you really need Spring for business tier? You can take advantage of MVC (on web tier), but when it comes to business tier have you considered J2EE? I definitely agree that ApplicationContextAware ties you up with Spring (I opened a discusion thread on a similar topic on "General J2EE forum - J2EE 1.5 or Spring") pointing to the exact problem that you're facing. I thing that would also worth to try AOP (through AspetJ not Spring AOP). AOP can really help you decouple your code from such dependencies and reuse it in other contexts. Collaboration between beans can be thinked as separate concerns handled by different aspects, if you just don't want Spring dependecy injection.
I think, I am also facing a similar problem as you, but with a little deviation. I have beans globally defined in an application-context(bean-factory) and are to be re-used across different tiers of the application. My objective is, I want to use the same context across different tiers, without re-instantiating the context. In this context, I have some beans which I never want to have the bean-defenitions refreshed, and another group of beans(dynamic beans) which I want to refresh frequently. Dynamic beans, I kept in a classpath location, so that, I can modify the properties, and I can add/remove beans.
So, what I am doing is, I created my own singleton application-context (MyCustomApplicationContext) extending ClassPathXmlApplicationContext, with an additional private element, dynamicContext. In effect, I have a static context as well as dynamic context. I overrided the methods of ClassPathXmlApplicationContext to manage both the static as well as dynamic beans. for eg., getBean() method will check for beans inside static context first and if not found, dynamic context. More over, the refresh method will refresh just the dynamic factories.
Since the MyCustomApplicationContext is a singleton, I think I can use this across different tiers, calling the methdos just like - MyCustomApplicationContext.getBean("mybean").
Here I wish sombody point out the design flows of this approach, or, is there any correction or an alternate way ?
Or, is there another way to use the same instance of BeanFactory across different tiers ?
Also, I wish to know, how people do, re-create beanfactory for each client(class), or whenever need some bean ?
thanks in advance
If i understand well your problem (i hope so ...), you want to be able to construct a shared context that is a parent of your private contexts, and this feature (context hierarchy) is already provided in ApplicationContext (in opposite to bean factories).
Here is an example for Sharing a spring context across multiple Webapps
that can be very similar to what you are expecting.