Thursday, April 3, 2014

My Liferay Startup Action Killed My Hot Deploys

or... where have all my custom portlets gone?

Liferay 6.1.1
CentOS

So I have an ever-evolving Extension plugin I use for the portals I'm responsible for.  Among other things, it provides custom authentication and applies a custom new user form for users accessing the site for the first time.  Since this form requires custom fields I implemented a startup action class to create the new fields for the user in Liferay's expando table the first time the portal starts up after having the extension applied.

It installed fine, I restarted the portal with no problems,  the new authenticator worked fine, the new user form worked fine.  All was well.

Except that no custom portlets appeared on my pages anymore.

Huh?

The portlet app folders were still right there under webapps, and on startup Liferay had no errors of any kind.  I tried re-installing a portlet just to see what would happen and...

...nothing.  The hot deploy listener wasn't responding to the .war file in the deploy folder.

Eventually I narrowed it down to my custom startup action.  My portlet-ext.properties file had the following line:

global.startup.events=edu.jhu.cvrg.utilities.setup.CVRGStartupAction

When I commented out this line and deployed my extension again (in a fresh copy of the portal) the hot deploy listener worked fine.

Interesting...

So I commented out all the code in the startup action class and re-enabled it.  Once again, deployments ceased to work.

Now, Liferay tells us that this global startup event runs once during the portal startup.  Well, that's exactly what I wanted.  There is however, another property...

application.startup.events

Which runs for each site on the portal.  In the case of a portal running only one site, this is functionally equivalent.  At least, it's supposed to be...

But when I changed the line in portal-ext.properties so it read

application.startup.events=edu.jhu.cvrg.utilities.setup.CVRGStartupAction

The extension worked perfectly, and so do hot deploys.

I'd really like to hear from a Liferay dev on this.  Is this a bug, or was I applying something incorrectly?

Tuesday, January 28, 2014

Resolving java.lang.ArrayIndexOutOfBoundsException: 0 on startup action in Liferay

So Liferay has a great system for creating global startup actions.  You configure the portal-ext.properties to run a class derived from AppStartupAction and Liferay runs it during startup.

I found a problem however...

20:27:35,500 ERROR [pool-2-thread-1][MainServlet:325] java.lang.ArrayIndexOutOfBoundsException: 0
java.lang.ArrayIndexOutOfBoundsException: 0
    at com.liferay.portal.util.PortalInstances._getDefaultCompanyId(PortalInstances.java:318)
    at com.liferay.portal.util.PortalInstances.getDefaultCompanyId(PortalInstances.java:82)
 ...

Strange, isn't it?  The companyId is provided by the PortalInstances class which should have been initialized, right?

The problem is that Liferay's MainServlet runs the global startup events BEFORE it initializes the PortalInstances object.  Since PortalInstances supplies the default companyId, it isn't available yet if you need it in your custom startup action.

The solution I used was to modify the MainServlet.java class to place the global startup actions right after company initialization.