Is it possible to use Spring #Autowired in Liferay hook? - spring

I wonder if it is possible to have a bean form xml file injected by #Autowired somehow into Liferay hook. In this particular case I'm using UpgradeProcess hook. My project is already configured for using Spring with liferay, I can decode xml with ClassPathXmlApplicationContext's getBean("bean name") method, but it would be much nicer if this had happened automatically.
greetz!

It is possible denu.
Configure your application's web.xml listener class as org.springframework.web.context.ContextLoaderListener and place applicationContext.xml in the WEB-INF folder. It will pick the respective beans from your applicationContext.xml and you can autowire those objects in your beans.
Cheers

Related

Resteasy and Spring integration without Spring ContextLoadListener

I am using Resteasy and Spring for my project. As Resteasy document said: http://docs.jboss.org/resteasy/docs/3.0.1.Final/userguide/html_single/index.html#RESTEasy_Spring_Integration.
I need to add a listener in the web.xml file:
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
However, in my project we also used a cms called magnolia, and magnolia also has an implementation for SpringContextLoaderListener. If I put both context listener. The magnolia won't be started when I run the app.
So according to the Resteasy document said:
If you do not use a Spring ContextLoaderListener to create your bean factories, then you can manually register the RESTeasy BeanFactoryPostProcessor by allocating an instance of org.jboss.resteasy.plugins.spring.SpringBeanProcessor. You can obtain instances of a ResteasyProviderFactory and Registry from the ServletContext attributes org.jboss.resteasy.spi.ResteasyProviderFactory and org.jboss.resteasy.spi.Registry. (Really the string FQN of these classes). There is also a org.jboss.resteasy.plugins.spring.SpringBeanProcessorServletAware, that will automatically inject references to the Registry and ResteasyProviderFactory from the Servlet Context. (that is, if you have used RestasyBootstrap to bootstrap Resteasy).
Does anyone knows how can I achieve that without using Resteasy ContextLoaderListener? What do I need to put in my spring applicationContext xml file?
I've also had problem with RestEasy SpringContextListener (properties placeholders ${...} weren't processed - RESTEASY-787, Spring java config didn't work etc.).
So it's enough to drop RestEasy SpringContextListener and use default org.springframework.web.context.ContextLoaderListener or whatever listener you need to. You just have to define Spring bean in your Spring XML configuration like this:
<bean class="org.jboss.resteasy.plugins.spring.SpringBeanProcessorServletAware"/>
Than RestEasy should work even without their special SpringContextListener. It works for me.

Can't a Filter or Listener use spring beans?

I have a listener class in web.xml like this:
<listener>
<listener-class>com.datx.monitoring.model.MonitoringHttpSessionListener</listener-class>
</listener>
And for this class, I have defined a bean like this:
<bean id="monitoringHttpSessionListener"
class="com.datx.monitoring.model.MonitoringHttpSessionListener" autowire="byName"/>
But this bean is not able to use other beans. Every time this class is called, it has null properties.
This class is the exact same as the other which is working fine. The only difference is, this class is used as a listener and the other is not. Why is that?
There is a simple reason for this: There are two beans. One was created by your web container (which uses web.xml) and the other by Spring (which uses your bean definition). The web container and Spring know nothing about each other.
What you need to do is create a normal listener which gets the application context with
WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());
This will allow you to look up beans. Now you can define a bean which the filter can modify.
Note: You will want to give this bean the request scope or there will be chaos.

Inject Spring beans into EJB3

I'm trying to inject Spring beans into an EJB using #Interceptors(SpringBeanAutowiringInterceptor.class) but I cannot get it working with the beanRefContext.xml examples I've seen.
Here's my EJB:
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class AlertNotificationMethodServiceImpl implements
AlertNotificationMethodService {
#Autowired
private SomeBean bean;
}
I've provided a beanRefContext.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="...">
<!-- Have also tried with ClassPathXmlApplicationContext -->
<bean id="context"
class="org.springframework.web.context.support.XmlWebApplicationContext">
<property name="configLocations" value="/config/app-config.xml" />
</bean>
</beans>
But, it seems to be recreating the beans instead of obtaining the existing ApplicationContext. I end up with the following exception because one of my beans is ServletContextAware.
java.lang.IllegalArgumentException: Cannot resolve ServletContextResource
without ServletContext
When using the SpringBeanAutowiringInterceptor, shouldn't it obtain the ApplicationContext instead of create a new one?
I also tried changing my web.xml so the contextConfigLocation points to the beanRefContext.xml, hoping it'd load my Spring config but I end up with the same exception as above.
Does anyone know how to do this properly? The examples I've seen seem to use the same method I'm using which I assume means the beans are being recreated when the Interceptor is invoked (or is that how it's supposed to work and I've misunderstood).
When using the SpringBeanAutowiringInterceptor, shouldn't it obtain the ApplicationContext instead of create a new one?
Yes, and this is in fact what it does. It uses the ContextSingletonBeanFactoryLocator mechanism, which in turn manages a number of ApplicationContext instances as static singletons (yes, even Spring has to resort to static singletons sometimes). These contexts are defined in beanRefContext.xml.
Your confusion seems to stem from the expectation that these contexts have any relation to your webapp's ApplicationContext - they don't, they're entirely separate. So your webapp's ContextLoader is creating and managing a context based on the bean definitions in app-config.xml, and the ContextSingletonBeanFactoryLocator creates another one. They won't communicate unless you tell them to. The EJBs cannot get hold of the webapp's context, since EJBs sit outside of that scope.
What you need to do is to move the beans that need to be used by your EJBs out of app-config.xml and into another bean definition file. This extracted set of bean definitions will form the basis of a new ApplicationContext which will (a) be accessed by the EJBs, and (b) will act as the parent context of your webapp's context.
In order to activate the parent-child link between your webapp's context and the new context, you need to add an additional <context-param> to your web.xml called parentContextKey. The value of this parameter should be the name of the context defined in beanRefContext.xml (i.e. context, in your example).
The beans that stay behind in the webapp's context will be able to reference the beans in the parent context, as will the EJBs. However, the EJBs will not be able to reference anything in the webapp's context.
Also, you cannot use XmlWebApplicationContext in beanRefContext.xml, since that class requires awareness of the webapp, and ContextSingletonBeanFactoryLocator cannot supply that awareness. You should stick with ClassPathXmlApplicationContext there.

Using springs component-scan and injecting beans

Im using spring 2.5 and writing a DispatcherServlet. In the context file for the servlet im using component-scan and giving the location of the class where my controllers are. The classes use the #Controller("bean Name") annotation.
How can i inject properties into this bean?
Thanks
Also remember that you can inject beans defined in main application context to the beans defined in application context for servlet, but not vice-versa. These contexts aren't merged, but they form parent-child relationship.
Using #Autowired (docs) or #Resource (docs).

How to #autowire into jsf managed beans

In order to use the #Autowire annotation, the object where you use the annotation must come from the spring context.
JSF managed beans are created by JSF's IOC not Springs, therefor i cannot use #Autowire inside of them must must use faces-config.xml and managed properties.
I already setup an EL resolver that lets be have spring beans as managed properties, i want to take it one step further and get rid of the need to go into the faces-config.xml every time i need to autowire something. Is this possible?
Just annotate your managed beans with #Controller (or #Component), and #Scope("request") (or session) and add <context:component-scan> (if you haven't), and managed beans will automatically be detected as spring beans. And since you are already using the ELResolver, that should be it - you should be able to use #Autowired (or better - #Inject, if using spring 3.0).
You can use #ManagedProperty(#{'someBean'}) for autowire other beans in jsf bean

Resources