Fórumok

Liferay Spring integration

Nikolas Lahtinen, módosítva 15 év-val korábban

Liferay Spring integration

New Member Bejegyzések: 3 Csatlakozás dátuma: 2009.02.09. Legújabb bejegyzések
Hello,
I've been recently tasked with a job to take functionality from a custom web application and develop a proof of concept portlet. We are currently using Spring and iBatis in the custom application to communicate with our database server. Now, I'm to take the existing Spring beans and use them with Liferay. However I've ran into a little problem. A bit of Googling and wiki reading has let me to conclude that I should put my Spring configuration files to docroot\WEB-INF\src\META-INF and define the spring.configs in service.properties to point to said Spring configuration files. Now my problem exactly is this: How do I get access to the Application Context? Our current software uses something like this:
WebApplicationContext wctx = 
WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServlet().getServletContext());

Does anyone have any ideas on how to approach this issue? All help would be appreciated.
thumbnail
Rob Sonke, módosítva 15 év-val korábban

RE: Liferay Spring integration

Expert Bejegyzések: 275 Csatlakozás dátuma: 2007.08.26. Legújabb bejegyzések
Which version of Liferay do you use?
Nikolas Lahtinen, módosítva 15 év-val korábban

RE: Liferay Spring integration

New Member Bejegyzések: 3 Csatlakozás dátuma: 2009.02.09. Legújabb bejegyzések
Rob Sonke:
Which version of Liferay do you use?

5.2.1
Nikolas Lahtinen, módosítva 15 év-val korábban

RE: Liferay Spring integration

New Member Bejegyzések: 3 Csatlakozás dátuma: 2009.02.09. Legújabb bejegyzések
Found a code snippet in some Alfresco SSO integration in which they did the following to access the Spring context:
WebApplicationContext ctx = (WebApplicationContext) getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

So I tried the same in my own code and switched the WebApplicationContext to PortletApplicationContext (which is an extended version of WebApplicationContext). I needed to include the portal-impl.jar in my portal's lib folder (I reckon that this isn't the right way to do it though). My code looks like this now:
PortletApplicationContext ctx = (PortletApplicationContext) getPortletContext().getAttribute(PortletApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

However, this does not seem to work as it now throws a ClassCastException stating that com.liferay.portal.spring.context.PortletApplicationContext can't be casted to com.liferay.portal.spring.context.PortletApplicationContext. My colleagues think that this might be because PortletApplicationContext is loaded from two different ClassLoaders. But if I remove the portal-impl.jar from the deployed portal .war folder, I get an error stating that the class PortletApplicationContext cannot be found. Anyone have any ideas on this?
thumbnail
Niket Jaykumar Shah, módosítva 14 év-val korábban

RE: Liferay Spring integration

New Member Bejegyzések: 4 Csatlakozás dátuma: 2009.04.25. Legújabb bejegyzések
I am using Liferay 5.2.2 and I am also facing issue in integrating the existing spring beans with liferay 5.2.2 .

can any one show the pointers where exactly I can get good documentation/tutorial on this?

Thanks in advance.
Rice Owl, módosítva 14 év-val korábban

RE: Liferay Spring integration

Regular Member Bejegyzések: 177 Csatlakozás dátuma: 2009.04.24. Legújabb bejegyzések
I'll see if I can find some documentation, but here is how I've integrated Spring within my portlets. There are several different ways to do this, depending on what you want to do. I'll show how I do a Spring context per WAR file (ie, not shared outside of the WAR). If you are interested in have a shared Spring context among multiple WAR files, let me know and I'll dig that up (there are some slight differences).

First, update your web.xml file to load the context:

web.xml

<web-app>
  <description>Financial Quotes Portlet Application</description>
  
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/YourSpringContextFile.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  .....
</web-app>


Then as you can see from the web.xlm file, you are putting your spring context file in the WEB-INF directory of your WAR file.

Now, to get a bean, you do the following. I usually create a helper/utility class to help fetch beans, but here it is in a nutshell:

PortletContext context = getPortletContext();
WebApplicationContext springContext = (WebApplicationContext)   
                 context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
Object beanObject = springContext.getBean("yourBeanName");


the beanObject should be cast to your Spring bean interface/class. Then you can use it. If you are getting the bean from a servlet, its pretty much the same except you use a ServletContext instead of a PortletContext.

Hope that helps.

I also have a post here, I'll add a link to it. The post discussed how to use a Spring context that is shared across multiple WAR files. This is useful if you want true singletons across multiple wars. Sometimes it doesn't matter, sometimes it does. I try to architect my Spring beans as services, so they are pretty light weight and don't necessarily need to be "true" singletons across multiple wars. But you may have a case where you only want one Spring Bean for all your WAR files.


Niket Shah:
I am using Liferay 5.2.2 and I am also facing issue in integrating the existing spring beans with liferay 5.2.2 .

can any one show the pointers where exactly I can get good documentation/tutorial on this?

Thanks in advance.
thumbnail
Niket Shah, módosítva 14 év-val korábban

RE: Liferay Spring integration

New Member Bejegyzések: 4 Csatlakozás dátuma: 2009.04.25. Legújabb bejegyzések
Hi Rice Owl,

Thanks for reply and help.


I have moved further with the approach you have mention. and I have successfully deploy the portlet in Liferay.

Still I have make some changes to the approach as I have used existing ext-spring.xml for bean refrence rather then creating our own file and used below code is the code to get the reference object to the action class.


                   WebApplicationContext springContext =  (WebApplicationContext) config.getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

               ((ServiceNameObject)springContext.getBean("ServiceName")).method(variables);
     
      



Still I am not able to find out why it's giving classCastException if we use PortletApplicationContext rather then WebApplicationContext.

Hope you or Some one can tell us.
Rice Owl, módosítva 14 év-val korábban

RE: Liferay Spring integration

Regular Member Bejegyzések: 177 Csatlakozás dátuma: 2009.04.24. Legújabb bejegyzések
Glad I could be of some help. I'll try to answer the class cast exception you are getting. Spring provides various contexts depending on how you are using spring: an applicatoin context (for apps such as stand-alone apps, ie desktop applications that don't run in a web container), web applicatoin contexts and portlet contexts. The type of context will depend on how you are loading your context. The example I gave included updated the web.xml file, which is a web-level configuration file, not specific to portlets. You could cut and paste the configuration in the web.xml file I provided in any type of web app, say a Java Struts application (non-portal). Spring provides a dispatcher servlet that loads your configuration file (the configuration in the web.xml file specifies this servlet and a parameter for hte servlet to specifiy the spring config file). This is within the web context of your WAR file. its accessible to your portlets, but its loaded on the web context. Its not strictly in the portlet context, thus its class isn't PortletApplicationContext. Its a WebApplicationContext.

There is a PortletApplicationContext (I've never loaded spring this way). Spring has a Portlet MVC framework that you can use with your JSR-168 portlets. If you choose to load your spring beans this way, you can. However, instead of configuring the DispatcherServlet in the web.xml, you'd configure a DispatcherPortlet in your portlet.xml file. If you do it this way, you would then have a spring context of type PortletApplicationContext. So if you are using the Spring Portlet MVC framework you can do it this way. You might be able to use it w/o using the framework, I'm not sure and haven't done it myself.

Now there may be a potential other issue. You mention that you are actually using another spring file. Where is this Spring file located? If its in a different web application, this can be problematic. For instance, if this file is in lferay's ROOT web application, it will be in a different classloader than your web application (assuming you are deploying a different WAR file).

There are ways of sharing a Spring context amongst multiple WAR files. I have a post a few months ago that asked some questions around this. So I guess the question would be - where is this spring config file that you want to load located? Is it important that this context be shared amongst multiple WARs? And lastly, what are you trying to do? If you are accessing LifeRay specific things, liferay actually provides a client API that allows portlets to access liferay resources.

Hope that helped!

Niket Shah:
Hi Rice Owl,

Thanks for reply and help.


I have moved further with the approach you have mention. and I have successfully deploy the portlet in Liferay.

Still I have make some changes to the approach as I have used existing ext-spring.xml for bean refrence rather then creating our own file and used below code is the code to get the reference object to the action class.


                   WebApplicationContext springContext =  (WebApplicationContext) config.getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

               ((ServiceNameObject)springContext.getBean("ServiceName")).method(variables);
     
      



Still I am not able to find out why it's giving classCastException if we use PortletApplicationContext rather then WebApplicationContext.

Hope you or Some one can tell us.
Kerim suissi, módosítva 12 év-val korábban

RE: Liferay Spring integration

New Member Bejegyzés: 1 Csatlakozás dátuma: 2011.11.23. Legújabb bejegyzések
Hi Race ,

In witch part of my calss "Spring Application Servlet" may i make this code :


this my "Spring Application Servlet" :



@SuppressWarnings("serial")
public class SpringApplicationServlet extends AbstractApplicationServlet {

/** Default application bean name in Spring application context. */
private static final String DEFAULT_APP_BEAN_NAME = "application";

/** Application bean name in Spring application context. */
private String name;

/**
* Get and stores in the servlet the application bean's name in the Spring's
* context. It's expected to be configured as a the servlet
* &lt;code&gt;init-param&lt;/code&gt; named applicationBeanName. If no
* param is found, the default is "application".
*
* @see AbstractApplicationServlet#init(ServletConfig)
*/
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
String name = config.getInitParameter("applicationBeanName");
this.name = name == null ? DEFAULT_APP_BEAN_NAME : name;
System.out.println("----------------------------------s");
}

/**
* Get the application bean in Spring's context.
*
* @see AbstractApplicationServlet#getNewApplication(HttpServletRequest)
*/
@Override
protected Application getNewApplication(HttpServletRequest request)
throws ServletException {

WebApplicationContext wac = WebApplicationContextUtils
.getWebApplicationContext(getServletContext());

if (wac == null) {

throw new ServletException(
"Cannot get an handle on Spring's context. Is Spring running?"
+ "Check there's an org.springframework.web.context.ContextLoaderListener configured.");
}

Object bean = wac.getBean(name);

if (!(bean instanceof Application)) {

throw new ServletException("Bean " + name
+ " is not of expected class Application");
}
System.out.println("Done");
return (Application) bean;
}

/**
* Get the application class from the bean configured in Spring's context.
*
* @see AbstractApplicationServlet#getApplicationClass()
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected Class<? extends Application> getApplicationClass()
throws ClassNotFoundException {

WebApplicationContext wac = WebApplicationContextUtils
.getWebApplicationContext(getServletContext());

if (wac == null) {

throw new ClassNotFoundException(
"Cannot get an handle on Spring's context. Is Spring running? "
+ "Check there's an org.springframework.web.context.ContextLoaderListener configured.");
}

Object bean = wac.getBean(name);

if (bean == null) {

throw new ClassNotFoundException(
"No application bean found under name " + name);
}

return (Class) bean.getClass();
}

}
Surender Biyyala, módosítva 11 év-val korábban

RE: Liferay Spring integration

New Member Bejegyzés: 1 Csatlakozás dátuma: 2012.08.30. Legújabb bejegyzések
Hi
I`m Surender new bee to Liferay.
I`m interested in Spring Liferay Integration and I know little spring and how exactly it works.

I have a bunch of doubts related to how the spring is getting integrated to liferay.

--> what happens when the liferay server is up ,i mean will it instatiate the Portal Container and what other things the portlet server do here?
--> why to declare every Portlet as a servlet in liferay.
-->how the dispatcherPortlet map the request to the appropriate controller if we dont declare the MappingHandler?
--> how the portlet server communicates with servlet container?
--> what is the use of the below configuration


<servlet>
<servlet-name>MyPortlet</servlet-name>
<servlet-class>com.liferay.portal.kernel.servlet.PortletServlet</servlet-class>
<init-param>
<param-name>portlet-class</param-name>
<param-value>eu.ibacz.example.MyPortlet</param-value> <!--replace with your portlet class -->
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>

i mean why we need to pass our portlet (Spring controller ) as init-param to the PortletServlet


Could you please given me some start up of these internals im really confused of these configuration, who and when these xonfiguration files are processed..


Thanks
Surender
Xinsheng Robert Chen, módosítva 11 év-val korábban

RE: Liferay Spring integration

Junior Member Bejegyzések: 45 Csatlakozás dátuma: 2010.03.30. Legújabb bejegyzések
Hi,

This is a thread created long time back.
I came across it yesterday when I tried to get a custom bean defined in the META-INF/ext-spring.xml file for a custom portlet in Liferay portal 6.1. Liferay has actually provided code to do this in the auto-generated yyyLocalServiceUtil.java class. The code is like the following:

InvokableLocalService invokableLocalService = (InvokableLocalService)PortletBeanLocatorUtil.locate(ClpSerializer.getServletContextName(),
UserCustomLocalService.class.getName());

The value of UserCustomLocalService.class.getName() is the id of the bean in the ext-spring.xml file. You can use this code to get the custom bean you defined in the ext.spring.xml file from the portlet web application context.