Using Class Loader Proxy classes to share plugins services

Etiquetas: development

Scenario: you have two plugins, each one in its war. One of them (from now on "CLP Portlet")has a service (let's call it "myObject") and its service layer (myObjectServiceUtil, myObjectLocalServiceUtil, etc) and the second portlet (from now on "CLP Consumer Portlet") needs to use those services. We are going to use Class Loader Proxy classes to achieve this: these classes serialize model entities across webapps so that they can be shared.

The steps to implement this are the following:

  1. After build-service in "CLP Portlet", it appears a CLP-portlet-service.jar file in WEB-INF/lib/
  2. Make the jar available for the other plugin. You can do this two ways:
    1. Copy the .jar file into the "CLP Consumer Portlet" WEB-INF/lib folder
    2. Copy CLP-portlet-service.jar into the global application server library folder. For Tomcat it would be tomcat_home/lib/ext
      1. Remove other copies from portlet/WEB-INF/lib (otherwise you will get strange exception like "ClassCastException Cannot cast MyObjectServiceUtil to MyObjectServiceUtil")
      2. In addition to all this, you MUST make sure that the copied service jar is NOT included in the original plugin.
  3. The last step is to call the remote service methods from "CLP Consumer Portlet".

This is as easy as a local call: com.liferay.clp.service.MyObjectServiceUtil.testMethod();

And that's all!

Note: some issues has been discovered using Tomcat 6.0 (see http://issues.liferay.com/browse/LPS-8353) but they have been fixed and are ready for the next release

Subpáginas

0 archivos adjuntos
29106 Accesos
Promedio (6 Votos)
La valoración media es de 4.333333333333333 estrellas de 5.
Comentarios
Respuestas anidadas Autor Fecha
The second and third step are unclear to me: ... Jakub Liska 6 de octubre de 2010 16:49
It's clear from the... Jakub Liska 8 de octubre de 2010 8:28
You're right Jakub, I updated the wiki the be... Amos Fong 12 de enero de 2011 18:03
I have troubles following this article. Here... Moisés Belda 19 de febrero de 2011 9:50
Sorry, here the link: <a... Moisés Belda 19 de febrero de 2011 9:51
Hi there, i've been trying to achieve this... Javier Vera 5 de diciembre de 2014 9:26

The second and third step are unclear to me:

we can copy the CLP jar either to CLP Consumer Portlet or to the app server context.

the third and fourth step say basically the same: to remove the jar from CLP context... which would work only if we copy CLP jar into app server context, but not if we copy it only to the CLP consumer context. Then it wouldn't be on the CLP classpath at all.

So either we copy it to app server context and delete it from CLP context, or copy it to the CLP consumer context and leave it in the CLP context... right ?
Publicado el día 6/10/10 16:49.
It's clear from the EntityLocalServiceUtil.getService() method that 2 situations arise:

1. we are not sharing services via CLP, so that we're using local EntityLocalServiceUtil
- _service field gets initialized by spring when portlet is deployed, the if (_service == null) condition is never true

2. sharing services - using "otherContext B" EntityLocalServiceUtil - then calls from "localContext A" to "otherContext B" EntityLocalServiceUtil.methods() are realized on freshly loaded class loaded by "localContext A" classloader without _service field initialized by spring.
Therefor if (_service == null) is true.

- First of all, I don't see any Serialization in here, just Reflection
the flow :
- locating "otherContext B" EntityLocalserviceImpl object whose methods we want to call and "otherContext B classloader"
- creating classLoaderProxy wrapping this EntityLocalserviceImpl object, invoking methodHandler that is supplied with method definition to be called on "otherContext B" serviceImpl object
- creating EntityLocalServiceClp that creates specific methodHandler instances for concrete method calls and with the help of ClpSerializer reloads "input parameter classes" / "return value classes" by "otherContext B" / "context A" classloader and manually copy over the state of the parameter and return value instances from those loaded by classloader B to those loaded by classloader A and the other way around.

Please, I'd appreciate any comments on this, to be sure that all the statements are correct.
Publicado el día 8/10/10 8:28.
You're right Jakub, I updated the wiki the be more a little more clear.
Publicado el día 12/01/11 18:03 en respuesta a Jakub Liska.
I have troubles following this article. Here the post with the problem:
http://www.liferay.com/es/community/forums/-/message_boards/message/7600­356
Publicado el día 19/02/11 9:50.
Sorry, here the link:
<a href="http://www.liferay.com/es/community/forums/-/message_boards/message/760035­6"> Post forum</a>
Publicado el día 19/02/11 9:51.
Hi there, i've been trying to achieve this "method sharing" however i've had no success. I see this Wiki is actually kind of old. I wonder if these same methods still apply for LR 6.2. And also, when attempting the following code i get strange errors:

ClassLoader classLoader = (ClassLoader) PortletBeanLocatorUtil.locate(pe.com.gmd.sistemas.service.service.ClpSerializer.­getServletContextName(),"portletClassLoader");

I wonder if we should use the string "portletClassLoader" instead of anything else.
Thank you for sharing!
Publicado el día 5/12/14 9:26.