Getting spring servlet application context - java

I need to get the servlet application context in the business layer of an spring mvc application.
I've tried implementing ApplicationContextAware interface, autowiring a WebApplicationContext field, and even implementing ServletContextAware and getting the application context with WebApplicationContextUtils, but none of this works.
Is there any other way to get it? I want to avoid having to pass an HttpServletRequest parameter from the controller to get the application context in the business object.
If it helps for something, I'm running on a WebSphere 6.1 server, and I think it has the servlet 2.4 api.

Implementing ApplicationContextAware and injecting ApplicationContext work. So that's the way to go. You must find what other problem stops it from working (how does it not work, actually?)
For example make sure the service class is not instantiated by you using the new operator.
By the way, you cannot and should not get the child application context (defined by dispatcher-servlet) in the service layer. This means that parent would know about child contexts - and it does not. You are thus breaking the layer boundaries. Think of another way of handling this task - for example have the context injected in a controller (it should work there), and then pass the desired arguments to a service.

Related

How to make legacy HttpServlet Spring web aware

We have a legacy HttpServlet class that is the backbone of our application. At this point, the app doesn't have any Spring libraries in it. We are looking to introduce Spring, in particular so we can use Spring-Data in conjunction with Hibernate.
I was wondering if there is a way to make this legacy Servlet web-aware so we can have Request and Session scopes injected. In particular, we would like to be able to inject the HttpServletRequest object into some beans.
One of the main reasons we need to do this, is for a weird multi-tenancy solution we have in place. Hibernate can handle Multi-Tenancy using a combination of a AbstractMultiTenantConnectionProvider and a CurrentTenantIdentifierResolver When using Spring-JPA's Repositories, you lose control of the session creation. One way to take care of this is to implement the CurrentTenantIdentifierResolver Since our tenant identifier is partially determined by something that comes in on the request, it is necessary to inject the request into our CurrentTenantIdentifierResolver implementation.
Also, it would be great to get Spring involved for all the other benefits it can provide in a legacy app.
Do you know how we can accomplish this?
You can define org.springframework.web.context.ContextLoaderListener within your web.xml, which will load your spring application context.
Then, within your servlet code, you access the context using WebApplicationContextUtils.getWebApplicationContext(servletContext) helper method.
Take a look at the Spring docs here:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#web-integration-common

React to NoSuchBeanDefinitionException inside Spring Application Context

We have an application context inside a web application. Whenever a typed-bean is requested which is not available in the context we have to create it and add it to the context.
The context will basically have to react to a NoSuchBeanDefinitionException by using a factory to create it.
For those wondering why we don't create them beforehand or use a FactoryBeans: Due to the highly dynamic nature of how the legacy middleware and the other layers interact we don't have a chance to know the service-types beforehand.
Any suggestions?
As mentioned in the comment below: Registering beans(prototype) at runtime in Spring

Load spring context in an EJB based application

The following is the situation :
I have a business layer, that is an EJB project. In fact, there is only one EJB that is created. This EJB is responsible to expose the service classes to other layers, that calls the EJB. I want to introduce spring (to use DI feature) in this layer.
My concern is, what is the best way to load the spring context in this business layer, so that the spring context does not get loaded again and again, whenever the EJB gets called ?
(In a Web project, there is an advantage rather to configure the spring context in contextLoaderListener, and it gets loaded once only when the application gets started)
I have thought of including spring in the same layer because :
Configure the dependencies of all DAO and service classes and inject them wherever necessary.
To use spring support for hibernate in the business layer.
Ease of Unit testing, by injecting the properties into classes and simulating the same. Don't need to run the other layers again and again, to test my business classes/methods.
To be able to use AOP (Aspect Oriented Programming) for Logging and method level auditing.
Kindly help me suggesting the best way, to load the spring context in an EJB project. I also want to know , if there are any alternatives if I can load the same in the app server (I am using Web sphere app server).
Thanks and Regards,
Jitendriya Dash
Spring should be configured as part of your application in the normal way that you always set it up. Then you need to access the Spring beans from the EJB layer. To access (adapted from this post), create a Spring bean as follows:
#Component
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(ApplicationContext context) throws BeansException {
CONTEXT = context;
}
public static Object getBean(String beanName) {
return CONTEXT.getBean(beanName);
}
}
Then, to call the bean in question from the legacy app:
SomeService someService = (SomeService)SpringApplicationContext.getBean("someServiceImpl");
The Spring context is initialized once, and your EJB layer can access at will.
For EJB3, Spring recommends using an EJB3 Injection Interceptor. Basically you specify your Spring context using a ContextSingletonBeanFactoryLocator which entails creating your Spring context in a beanContextRef.xml in your classpath. Probably as part of your EAR. The SpringBeanAutowiringInterceptor injects your bean into your EJB.
Marking the EJB been as a Singleton (#Singleton). And storing the spring context in a variable in this bean, after it is created once, so that you can return the same context again and again.

should a Service layer be a Spring bean?

Can or should a Service layer be a Spring bean?
If so, how should it be got from a calling application, a consumer of a service?
Because the consumer must be aware that such a bean exists, so it in any case must use Spring
to make use of Service methods.
Of course. The service layer is the part of your application that is visible to other users (e.g. a Web layer) so it needs to be configured and setup somewhere. Imho a Spring configuration is the best place to put this configuration in. The Service Layer user then has to take care of instantiating that context and getting the Service Objects he needs.
An alternative - if it needs to run standalone - would be for your service class(es) implementing the Service Layer interface(s) to instantiate the Spring application context themselves.
By making your consumers also spring beans, and inject the service bean with dependency injection.
Yes, It is always nice to configure service beans as spring beans. In the web layer you need to take care of instantiating the needed service objects. Another option is to make the web layer classes also as spring beans and inject the necessary service layer spring beans. From the testing point of view also, this type of design is very helpful when we use Spring testing framework.

Spring 2.5 managed servlets: howto?

Correct me if anything is wrong.
As I understand, all Spring functionality, namely DI works when beans are got thru
Spring Context, ie getBean() method.
Otherwise, none can work, even if my method is marked #Transactional and I will
create the owning class with a new operator, no transaction management will be provided.
I use Tomcat 6 as a servlet container.
So, my question is: how to make Servlet methods managed by Spring framework.
The issue here is that I use a framework, and its servlets extend the functionality of
basic java Servlets, so they have more methods. Still, web.xml is present in an app as usual.
The thing is that I do not control the servlets creation flow, I can only override a few methods
of each servlet, the flow is basically written down in some xml file, but I control this process
using a graphical gui.
So, basically, I only add some code to a few methods of each Servlet.
How to make those methods managed by Spring framework? The basic thing I need to do is
making these methods transactional (#Transactional).
comment to Bozho:
#Bozho Let's see. In these servlets' methods I work with framework capabilities, let's say special variables that are got and saved in the current session. And what is needed, is looping through those framework-based collections while saving some values in a database. What you suggest is introducing a new very complex object, so that it could be passed to a service layer. (Service layer will not know anything about framework, its classes and objects kept in current Session! First, we "wrap" framework based collections to such a object, so copy everything into it. Then, again, the Service layer method should either save changes in a database or, worse case, return a new complex object so that Servlet framework method could update framework variables depending on the result of Service layer method execution. It is a workaround but do you think it is a good idea?
You can also define your servlets directly in the Spring application context. You'll need a "proxy" servlet registered in web.xml and delegating to the servlet instance which is configured as bean in the applicationContext.xml. Proxy servlet is configured with the name of the target servlet bean, it discovers this bean via WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(...) and delegates all the processing to the target servlet. In this case an instance of your servlet is completely managed by Spring.
I'd suggest restructuring your code - making servlet methods transactional is not a good thing to do. Put the transactional logic in a separate, service class, and either
obtain these spring-managed classes by WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(..) or
in your servlet init() method obtain the ApplicationContext with the above method and call appCtx.getAutowireCapableBeanFactory().autowireBean(this). This way you can inject the transactional classes in your servlet as if it was spring-managed.
Now, you can do all this, but it is definitely not a beautiful way to go. I'd suggest using Spring MVC or any other MVC framework (which support spring integration of its components)
If this is all not possible, as a last resort I think you can use #Configurable (on your servlets) with a <context:load-time-weaver/>.
You should take a look how Spring proxy filters:
http://grepcode.com/file/repository.springsource.com/org.springframework/org.springframework.web/3.0.2/org/springframework/web/filter/DelegatingFilterProxy.java
In theory you could easily make the same sort of proxy for servlets and DispatcherServlet is sort of a proxy.

Categories

Resources