Fórum

Tomcat 6.x classloader issue

thumbnail
Guido Kaltwasser, modificado 15 Anos atrás.

Tomcat 6.x classloader issue

New Member Postagens: 18 Data de Entrada: 15/09/08 Postagens Recentes
Dear all,

Presumably, we discovered a classloader issue with Tomcat 6.0.x and apparently also with Tomcat 5.5.x

Within the portal core we customised class com.liferay.portal.service.OrganizationServiceUtil so that users can choose thier location during the registration process. As recommended we overwrite this class in the ext environment and deploy it to tomcat. This class is packaged to two jar files.

1) {catalina.home} /lib/ext/ext-services.jar (customised class) and
2) {catalina.home} /lib/ext/portal-service.jar (original class)

According to the classloader specification of tomcat, ext-service.jar should be read first and therefore the customised class as well. But when I invoke the create_account.jsp the original class is called and we get an java.lang.NoSuchMethodError exception, because the method we call with that jsp sits within the customised class.

We found a workaround for this issue by copying the class files into the {catalina.home} /lib/ folder to force tomcat to load this class first. That worked!

From our point of view, that does not seam to be the right way. Is there any one who can tell us what we are doing wrong...

Cheers Guido

Environment:
-ubuntu
-java 6
-ant 1.7
-liferay 5.1.2
-Tomcat 6 Bundle
-HSQL (for development)
thumbnail
Alex Wallace, modificado 15 Anos atrás.

RE: Tomcat 6.x classloader issue

Liferay Master Postagens: 640 Data de Entrada: 05/11/07 Postagens Recentes
Because of classloading differences and sometimes unexpected behavior, the recommendation is that your overrides use their own package name or class name (different from originals) and that you also change the process that used the class you overrode, such as a struts action, or perhaps you will need to create a custom service to use your override as well.

I hope this makes sens... And helps...
thumbnail
Guido Kaltwasser, modificado 15 Anos atrás.

RE: Tomcat 6.x classloader issue

New Member Postagens: 18 Data de Entrada: 15/09/08 Postagens Recentes
Hi Alex,

thanks, we will discuss this approach in tomorrows meeting.

What I forgot to mention is, that we have a couple of development PC and with one PC does it work and with the other PC not. Up till now we were not able to find out why.. That drives me mad.

Cheers Guido
thumbnail
Mika Koivisto, modificado 15 Anos atrás.

RE: Tomcat 6.x classloader issue

Liferay Legend Postagens: 1519 Data de Entrada: 07/08/06 Postagens Recentes
You should never have two classes with the same name in the same classloader. It is unpredictable which one gets loaded. Within a webapp you can put the overriding class in WEB-INF/classes because the spec states that it is loaded before WEB-INF/lib but the same doesn't apply to tomcat's common classloader. What you should do is give it a different name and use that class in your jsp.

If you want to change the implementation of a service then you should extend the class you are overriding and configure spring to use your class.
thumbnail
Guido Kaltwasser, modificado 15 Anos atrás.

RE: Tomcat 6.x classloader issue

New Member Postagens: 18 Data de Entrada: 15/09/08 Postagens Recentes
Hi Mika,

thanks for your reply, since we don't tend to customise to many classes for the core application, we dicided to customise the original class, so that it fits our needs. We do that for convenience. The drawback is obviously that we have to put a bit more effort into merging the customised classes when upgrading to the next version.

Cheers Guido
Karl Mozurkewich, modificado 13 Anos atrás.

RE: Tomcat 6.x classloader issue

New Member Postagens: 10 Data de Entrada: 02/02/09 Postagens Recentes
Mika Koivisto:
You should never have two classes with the same name in the same classloader.



This is not practical, and not even followed in the LR core. There are multiple instances in the LR trunk where there are disparate classes with the same name. (BooleanQuery.java is an example - both in LR and lucene.jar)
Karl Mozurkewich, modificado 13 Anos atrás.

RE: Tomcat 6.x classloader issue

New Member Postagens: 10 Data de Entrada: 02/02/09 Postagens Recentes
I ran into this same problem - odd thing was my code worked on a 32bit machine but not a 64bit one.(different jvm obviously) My issue is that I thought the whole idea of the ext-plugin architecture was to allow us to override the LR classes by laying our code on-top of the vanilla LR build during the EXT deployment and registration.

The classes I overrode were core LR interfaces related to search, and as they are used all over the place it would be tedious to go through and update all the existing portlets with new references and prototypes.(men use vi, not IDEs.. emoticon )
Joel Peterson, modificado 13 Anos atrás.

RE: Tomcat 6.x classloader issue

New Member Postagens: 22 Data de Entrada: 18/02/10 Postagens Recentes
Karl,
I ran into this classloading issue awhile back. I found either a forum or blog post that explained that while the PortalClassLoader loads alphabetically, allowing you to load ext-impl.jar before portal-impl.jar, the app server's class loader was not guaranteed to load the same way. Since portal-service.jar and ext-service.jar deploy to the app server's library folder and not the portal web app's library folder this would explain why it will not always overwrite portal-service.jar.

I would suggest looking at Liferay's spring files to see if you can overwrite Liferay's search beans with your own. All of the Liferay APIs that I have looked at call a spring bean to actually execute the service, so if you were to replace the underlying spring bean definition with your own then you would not necessarily need to update all of their portlets. You can find a bunch of their spring files inside of portal-impl.jar in the META-INF folder.
Karl Mozurkewich, modificado 13 Anos atrás.

RE: Tomcat 6.x classloader issue

New Member Postagens: 10 Data de Entrada: 02/02/09 Postagens Recentes
Joel Peterson:
Karl,
I ran into this classloading issue awhile back. I found either a forum or blog post that explained that while the PortalClassLoader loads alphabetically, allowing you to load ext-impl.jar before portal-impl.jar, the app server's class loader was not guaranteed to load the same way. Since portal-service.jar and ext-service.jar deploy to the app server's library folder and not the portal web app's library folder this would explain why it will not always overwrite portal-service.jar.

I would suggest looking at Liferay's spring files to see if you can overwrite Liferay's search beans with your own. All of the Liferay APIs that I have looked at call a spring bean to actually execute the service, so if you were to replace the underlying spring bean definition with your own then you would not necessarily need to update all of their portlets. You can find a bunch of their spring files inside of portal-impl.jar in the META-INF folder.



Thanks Joel - I've spent a good deal of time going through the core. The problem is spring validation checking on the object types which translates to exceptions when you try to totally re-write the classes without any inheritance, plus all the issues that it causes with the existing portlets that use those types.

There should be a custom global classloader that doesn't break current contracts, but at least guarantees basic consistency. Overriding trunk classes in Ext is basically broken until you can guarantee which class gets used, the main problem being with the interfaces in the service layer. Since version 1.0 the jcp specs have always stressed the fact of never relying on classloading order, but if LR wants to leverage the ext pattern of the specs and architect things the way they are, the project needs to provide either working classloader proxies or a custom global classloader.
thumbnail
Mathieu Hicauber, modificado 11 Anos atrás.

RE: Tomcat 6.x classloader issue

Junior Member Postagens: 79 Data de Entrada: 22/12/10 Postagens Recentes
Hi,

I had the problem recently :
- overriding a class from the "Service" part (ThemeDisplay.java)
- a classloader behavior different on my local machine and on the integration machine.

Found a workaround : http://mathieuhicauber-java.blogspot.fr/2012/11/classloader-issue-when-overriding.html

Hope this help.

Mathieu.