Monday, November 29, 2010

The Ghost EL of JSF and Liferay

Yes, this one is a nightmarish tale of woe, of pain, of suffering and of a desk with a vague dent in it shaped roughly like a forehead...

The scenario:

You're deploying a portlet into Liferay with Tomcat that's built with some flavor of JSF or another and when you watch the output during the deploy you see a message that says something like this:

java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/catalina/loader/WebappClassLoader) of the current class, com/sun/faces/config/ConfigureListener, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature

Now, in Googling this beast of an error you will see a lot of very helpful advice that usually revolves around "Take the el-api.jar file out of your WEB-INF/lib folder in your project."

See, the conflict arises when Tomcat already has an el-api.jar file in its lib folder so when you try to bring yours to the party it causes a collision.

"But wait!" You say. "I did that! I went into my pom.xml and made sure to exclude that dependency so now it doesn't show up in my .war file and still I get the error!!!!!!!111111111"

So you've verified that there's no sign of that el-api.jar file in your .war file's WEB-INF/lib folder? You sure?

Yes? ok then here's what you do next:

Go to your webapps folder in Tomcat. see your portlet folder in there? Open it. Now go into the WEB-INF/lib folder inside it.

Yeah. You see it, don't you?

See, back when you deployed your portlet the first time and put that el-api.jar file there, it caused the initial problem. Later, when you re-deployed your project without that .jar, it got deployed but it didn't completely blow away the old installation. That's why it's best to make sure it's gone when you re-deploy. How? Just delete the portlet's folder from webapps and wait a minute or two. Liferay will notice it's gone then unregister the portlet. You can now safely deploy your portlet again.

No comments:

Post a Comment