留言板

Share code between ext and plugin portlets

thumbnail
Mathieu Hicauber,修改在11 年前。

Share code between ext and plugin portlets

Junior Member 帖子: 79 加入日期: 10-12-22 最近的帖子
Hello all,


Is there a recommended way to share a Utility class between ext plugin and portlet plugin ?
I have a XXXHelper class, which I use both in an overrided implementation of ThemeDisplay sitting in ext plugin, and also in a portlet plugin.

I'd prefer not to have to duplicate the class...

Thank you,

Mathieu.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
If it's wrapped into a jar, it is still usable by EXT.

In plugin projects, add the jar as a dependency and it will get pulled in at deployment time so you don't have duplicated code issues.
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Hi David,

How do you add the portlet-service.jar as a dependency in an ext plugin?

Regards,

Flor.
thumbnail
Mathieu Hicauber,修改在11 年前。

RE: Share code between ext and plugin portlets

Junior Member 帖子: 79 加入日期: 10-12-22 最近的帖子
I think what David sais is :

- put a jar in ext-lib folder in ext plugin
- then you can add it as dependency in any portlet through liferay-plugin-package.properties (after a first deployement of the ext plugin, so the jar is copied to ROOT/WEB-INF/lib)

HTH


Mathieu.
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
So may be my problem is different. Not sure if I should start a new thread or keep writing in this one.

I've tried to use a portlet plugin in an ext plugin, these is what I've tried:

Option 1:

I included the portlet-service.jar generated from the portlet in the ext-lib/portal of the ext plugin. When I compile the ext plugin, the classes from the portlet are not being seen by the ext plugin. So I can't even compile.

Option 2:

I included the portlet-service.jar generated from the portlet in the ext-lib/global of the ext plugin. It compiles perfectly. But when I deploy the ext plugin in the server (after deploying the portlet), I get exceptions like:

java.lang.ClassCastException: com.rcs.service.service.persistence.MessageSourcePK cannot be cast to com.rcs.service.service.persistence.MessageSourcePK


So this looks like a class loader issue, like there are duplicated classes.

I've read that putting the portlet-service.jar in tomcat/lib/ext is not a good practice, so I won't do it.

Are there any other suggestions?

Thanks,

Flor.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Florencia Gadea:
I included the portlet-service.jar generated from the portlet in the ext-lib/global of the ext plugin. It compiles perfectly. But when I deploy the ext plugin in the server (after deploying the portlet), I get exceptions like:

java.lang.ClassCastException: com.rcs.service.service.persistence.MessageSourcePK cannot be cast to com.rcs.service.service.persistence.MessageSourcePK


So this looks like a class loader issue, like there are duplicated classes.


Yep, you're missing the step of removing the service jar from the deployed plugin that has the service. There should only be one service jar in this scenario, the one in the global lib directory. Any other copies anywhere in the webapps folder will cause you similar headaches.
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Hi David,

Thank you a lot for your help.

In your opinion, what do you think is the best option in order to make it easier for a non-technical user to deploy this?

Regards,

Flor.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Florencia Gadea:
In your opinion, what do you think is the best option in order to make it easier for a non-technical user to deploy this?


The easiest route is the global lib usage scenario. The caveat here is that you have the app container deployment to contend with (shutdown, service jar move, restart).
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Ok, here is what I did and it looks that it's working:

1) Deploy portlet plugin.
2) Stop liferay.
3) Move portlet-services.jar from portlet plugin WEB-INF/lib to tomcat/lib/ext.
4) Deploy ext plugin.
5) Restart liferay.

Is it ok?

Thanks,

Flor.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Florencia Gadea:
Ok, here is what I did and it looks that it's working:

1) Deploy portlet plugin.
2) Stop liferay.
3) Move portlet-services.jar from portlet plugin WEB-INF/lib to tomcat/lib/ext.
4) Deploy ext plugin.
5) Restart liferay.


Yep, that's it, although you may want to adjust the order. If the service jar is not in lib/ext, the IDE will complain about the code in the EXT plugin since the jar is not available yet. If you trust your development skills, though, it's okay to order in this way.

For redeployments, you have two paths:

a) If you needed to build services as part of the deployment (i.e. you added/modified an entity, you added a method to XxxLocalServiceImpl or changed a method signature to an existing method in XxxLocalServiceImpl), you must repeat the process you did above.

b) If you did not need to build services but had a deployment (i.e. you changed the logic within a method in XxxLocalServiceImpl but did not change a method signature), your deployment process is slightly smaller:

1. deploy portlet plugin.
2. stop liferay.
3. delete service jar from portlet plugin (move is not necessary because jar did not change).
4. start liferay.
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Ok, thanks for sharing you time and knowledge!

Best regards,

Flor.
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Hi David,

Me again. After I move the portlet-service.jar to tomcat/lib/ext I get this exception:


...
SEVERE: Servlet.service() for servlet resourceEditor Servlet threw exception
java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
	at org.springframework.web.servlet.support.JstlUtils.exposeLocalizationContext(JstlUtils.java:97)
...


In my plugin portlet I need to use some JSPs. Does it mess with the lib/ext solution?

Regards,

Flor.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Does it happen if you restart tomcat?
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
David H Nebinger:
Does it happen if you restart tomcat?


Yes.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Florencia Gadea:

...
SEVERE: Servlet.service() for servlet resourceEditor Servlet threw exception
java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1711)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
	at org.springframework.web.servlet.support.JstlUtils.exposeLocalizationContext(JstlUtils.java:97)
...



The JSP stuff comes from the jstl.jar, which it looks like your portlet might not have. Add jstl-api.jar as a dependent jar in liferay-plugin-package.properties.
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
David H Nebinger:

The JSP stuff comes from the jstl.jar, which it looks like your portlet might not have. Add jstl-api.jar as a dependent jar in liferay-plugin-package.properties.



It is already added there:

portal.dependency.jars=\		
	jstl-api.jar,\
	jstl-impl.jar,\
        util-java.jar,\
        slf4j-api.jar,\
        slf4j-log4j12.jar,\        
        commons-collections.jar,\
        commons-fileupload.jar,\
        commons-httpclient.jar,\
        commons-io.jar
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Is there a 'caused by' exception that you didn't show?
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
David H Nebinger:
Is there a 'caused by' exception that you didn't show?


Yes:

Caused by: java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
This is typically an artifact of another class loader problem...

Does your service code reference any other classes (something other than one of your entity classes or primitives)?
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Apart from my entity classes, these are all the classes that my code references:


import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
import com.liferay.portal.kernel.deploy.hot.HotDeployException;
import com.liferay.portal.kernel.deploy.hot.HotDeployListener;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.DocumentException;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.util.Portal;
import com.liferay.portal.kernel.util.PortalClassInvoker;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.events.SimpleAction;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.language.LanguageUtil;
thumbnail
Florencia Gadea,修改在11 年前。

RE: Share code between ext and plugin portlets

Regular Member 帖子: 146 加入日期: 12-3-27 最近的帖子
Well, I fixed this error. I deleted the jstl-api.jar from the portal dependency jars and I added it in WEB-INF/lib.

Thanks everyone for the help.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Florencia Gadea:
How do you add the portlet-service.jar as a dependency in an ext plugin?


Well, this is a special case. The service jar must either be promoted to the global lib directory (lib/ext in tomcat) or copied to the ext-lib of the EXT plugin and deployed. There is additional work that you must do in either case.

For the global lib route, you must deploy the service plugin, stop the app container, move the jar to global lib, then start the container.

For ext-lib, you should move the jar prior to deployment (involves building a special deployment artifact for the plugin that had the service jar), bundle and deploy the EXT and the service plugin will need to have the service jar listed as a dependency jar before deployment, ...

Although the global lib route requires a restart of the app container, it is often the easier route than trying to figure out how to get the pieces working in the EXT plugin...
thumbnail
Mathieu Hicauber,修改在11 年前。

RE: Share code between ext and plugin portlets

Junior Member 帖子: 79 加入日期: 10-12-22 最近的帖子
edit : refering to David message (cross message posting ^^)

I've done that in the past, but I like to use maven for versioning third party jars like this one and I experienced problem :

Put jar-v0.1 in ext-lib folder,
Refer to it as a dependency in portlet plugin
OK.

Put jar-v0.2 in ext-lib folder, delet v0.1
==> when ext is deployed, v0.1 is still present in ROOT/WEB-INF/lib, and is being picked up by LR classs loader.



So I was think of putting a utility class (like PortalUtil or so) in the ext plugin so it can be viewed by any portlet... but I don't see how.

According to you, no other solution apart putting the class in a jar, and the jar in ext plugin ?
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Mathieu Hicauber:
I've done that in the past, but I like to use maven for versioning third party jars like this one and I experienced problem...


Yeah, versioning doesn't work out to well. EXT plugins rarely undeploy cleanly (at least in my experience) so you do get left with both versions (old and new) sitting out there.

I typically don't do the versioning on the 3rd party jars, mostly because I don't want to have to clean this stuff up afterwards and deal with class versioning conflicts if I don't get to it in time.

According to you, no other solution apart putting the class in a jar, and the jar in ext plugin ?


The only other option for sharing code is to use the global lib directory...
thumbnail
Mathieu Hicauber,修改在11 年前。

RE: Share code between ext and plugin portlets

Junior Member 帖子: 79 加入日期: 10-12-22 最近的帖子
Hi,

I'm back ! (not network at home emoticon )

The only other option for sharing code is to use the global lib directory...


Can you explain this other solution ?

Also, I've herad of a "client" directory at the root of the plugin sdk (newly rebaptized "shared" it seems). I didn't find any specific documentation about this, but from what I understood it could be a kind of "shared functionnalities" plugin. Am I right ? Isn't this the kind of plugin Ii'm looking for ?

Thank you,

Mathieu.
thumbnail
David H Nebinger,修改在11 年前。

RE: Share code between ext and plugin portlets

Liferay Legend 帖子: 14918 加入日期: 06-9-2 最近的帖子
Mathieu Hicauber:
The only other option for sharing code is to use the global lib directory...


Can you explain this other solution ?


Put the jar in the global lib directory (tomcat's lib/ext directory, for example). This path has issues as you will not be able to do updates when the application container is running, but makes the code globally available.

Also, I've herad of a "client" directory at the root of the plugin sdk (newly rebaptized "shared" it seems). I didn't find any specific documentation about this, but from what I understood it could be a kind of "shared functionnalities" plugin. Am I right ? Isn't this the kind of plugin Ii'm looking for ?


Well the client directory used to be for creating web service clients for your SB web service entities, but I don't know if it still has the same meaning...
thumbnail
Mathieu Hicauber,修改在11 年前。

RE: Share code between ext and plugin portlets

Junior Member 帖子: 79 加入日期: 10-12-22 最近的帖子
I guessed the "share functionnalities" info from there :
http://issues.liferay.com/browse/LPS-30551

Thank you for your advices, I'll go with the jar in the ext/lib dir so I can reference it from other plugin.

Thanks again,

Mathieu.