留言板

Liferay 6.1 Action Hook Spring Context

Mark Moon,修改在12 年前。

Liferay 6.1 Action Hook Spring Context

New Member 帖子: 5 加入日期: 12-1-19 最近的帖子
Has anyone been able to successfully obtain a Spring application context within a Liferay action hook? I've tried a number of approaches within web.xml to correctly configure the Spring context including:
  • org.springframework.web.context.ContextLoaderListener
  • com.liferay.portal.kernel.spring.context.PortletContextLoaderListener
  • com.liferay.portal.kernel.servlet.HookContextListener

The only combination which yields any sort of result is:

<!--?xml version="1.0"?-->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  ...
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/spring/applicationContext.xml</param-value>
  </context-param>
  <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.liferay.portal.kernel.servlet.HookContextListener</listener-class>
  </listener>
</web-app>


With the above in place, I can see the Spring context being created, however when I go to obtain the application context from within an Action via:
(ApplicationContext) portletConfig.getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)

I get:
com.liferay.portal.spring.context.PortalApplicationContext cannot be cast to org.springframework.context.ApplicationContext

PortalApplicationContext resides in portal-impl and I've see where people are including that in their hook classpaths, but it is my understanding that it is a good practice to refrain from having this dependency in place.

Alternatively, if I try:
PortletApplicationContextUtils.getWebApplicationContext(portletConfig.getPortletContext());

I get:
Root context attribute is not of type WebApplicationContext: Root WebApplicationContext: startup date [xx]; root of context hierarch


Environment:
  • Liferay 6.1
  • Tomcat 7.0.23
  • Spring 3.0.5
  • Java 1.6.0_27
  • MySQL 5.5
thumbnail
David H Nebinger,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

Liferay Legend 帖子: 14915 加入日期: 06-9-2 最近的帖子
The attribute in the portlet context is Liferay's Spring context, not yours. You will not be able to access it because it is outside the scope of your portlet, and it's not the one you'd want anyway.

You should be using the PortletApplicationContextUtils.getRequiredWebApplicationContext() method to access your own spring context.
Mark Moon,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

New Member 帖子: 5 加入日期: 12-1-19 最近的帖子
Switching to PortletApplicationContextUtils.getRequiredWebApplicationContext() yields the same result:
Root context attribute is not of type WebApplicationContext: Root WebApplicationContext: startup date [Thu Jan19 11:16:55 CST 2012]; root of context hierarchy
java.lang.IllegalStateException: Root context attribute is not of type WebApplicationContext: Root WebApplicationContext: startup date [Thu Jan 19 11:16:55 CST 2012]; root of context hierarchy
        at org.springframework.web.portlet.context.PortletApplicationContextUtils.getWebApplicationContext(PortletApplicationContextUtils.java:80)
        at org.springframework.web.portlet.context.PortletApplicationContextUtils.getRequiredWebApplicationContext(PortletApplicationContextUtils.java:100)


Am I missing something in web.xml?
thumbnail
David H Nebinger,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

Liferay Legend 帖子: 14915 加入日期: 06-9-2 最近的帖子
You still need the spring context listener...
Mark Moon,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

New Member 帖子: 5 加入日期: 12-1-19 最近的帖子
My web.xml is:
<!--?xml version="1.0"?-->
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
 ...
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/spring/applicationContext.xml</param-value>
  </context-param>
  <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.liferay.portal.kernel.servlet.HookContextListener</listener-class>
  </listener>
</web-app>
thumbnail
David H Nebinger,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

Liferay Legend 帖子: 14915 加入日期: 06-9-2 最近的帖子
Mark Moon:
Root context attribute is not of type WebApplicationContext: Root WebApplicationContext: startup date [Thu Jan19 11:16:55 CST 2012]; root of context hierarchy


After actually looking at the code for PortletApplicationContextUtils, here's what's going on:

1. Grab the attribute from the portlet context named "WebApplicationContext.ROOT".
2. If the object is null, null is returned.
3. If the object is a RuntimeException or an Error instance, throw it as an exception.
4. If the object is not an instance of ApplicationContext, it throws the IllegalStateException with "Root context attribute is not of type WebApplicationContext: " + the string value of the object.

So the string value of the object you have stored here is "Root WebApplicationContext: startup date [Thu Jan19 11:16:55 CST 2012]; root of context hierarchy".

Now the weird thing is that this is actually a string generated by the web application context, so it would appear that the object actually is an instance of ApplicationContext.

So at this point I would guess that you're looking at a classpath issue here, that the object is right but the "instanceof ApplicationContext" fails because it is in a different class.
Mark Moon,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

New Member 帖子: 5 加入日期: 12-1-19 最近的帖子
I was able to solve this by moving all of the dependencies in ROOT/WEB-INF/lib into Tomcat's lib/ext directory. After doing that, I was able to cast to ApplicationContext instead of PortalApplicationContext. I'm not crazy about this approach, as now all my custom plugins will have to use the same dependencies as Liferay.
thumbnail
David H Nebinger,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

Liferay Legend 帖子: 14915 加入日期: 06-9-2 最近的帖子
Eek, this is definitely a bad thing...

You should figure out how to resolve the class loader issue instead of pursuing this path...
Mark Moon,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

New Member 帖子: 5 加入日期: 12-1-19 最近的帖子
Any thoughts as to how? Seeing that PortalApplicationContext resides in portal-impl.jar which is in ROOT/WEB-INF/lib I don't see how to do this other than moving portal-impl.jar to TOMCAT_HOME/lib/ext. Moving portal-impl.jar, resulted in a number of additional class loader issues until ultimately, moving the remaining dependencies to Tomcat's lib/ext solved the issue.
thumbnail
David H Nebinger,修改在12 年前。

RE: Liferay 6.1 Action Hook Spring Context

Liferay Legend 帖子: 14915 加入日期: 06-9-2 最近的帖子
Well if you can't get access to it within the hook, I think you're going to have to move it into an Ext plugin. That's going to be the only approved way of finding yourself within the portal class loader...