掲示板

Wrong order of portlet unloading during hot-redeploy

12年前 に Pavel Horal によって更新されました。

Wrong order of portlet unloading during hot-redeploy

New Member 投稿: 14 参加年月日: 11/06/16 最新の投稿
Hello,

I've been having troubles with redeploying my portlet in Liferay 6.1 CE (bundled with Tomcat).

Most of the time I was getting NoClassDefFound in my Portlet.destroy() method. The probable cause was Tomcat's webapp class-loader memory leak prevention, when they don't allow using the class loader after the application was undeployed. This exception caused Liferay's HotRedeploy component fail to reload the portlet. I was getting all sorts of strange error, which were signalizing that the application is using old portlet (from undeployed application loaded by "removed" classloader).

Then I checked the order of component initialization and destruction on hot-redeploy (from Liferay IDE btw.):

  • First, the web application's ContextLoaderListener.contextDestroyed() was called.
  • Then after redeploy the ContextLoaderListener.contextInitialized() was called.
  • And after this, Liferay's HotDeployUtil.fireDeployEvent() was called. During this method it is when the Portlet.destroy() method was called (on a Portlet from undeployed web application!).


The problematic piece of code com.liferay.portal.service.impl.PortletLocalServiceImpl.initWAR(), which contains the invalid call to the the destroy method. In my opinion portlet's destroy method should be called during web application contextDestroyed() event.

Stack trace from the initialization event (this is after the application has been redeployed, however the breakpoint was in destroy method):

... my portlet stuff ...
	at org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher.destroy(Jsr168Dispatcher.java:632)
	at com.liferay.portlet.InvokerPortletImpl.destroy(InvokerPortletImpl.java:195)
	at com.liferay.portlet.PortletInstanceFactoryImpl.clear(PortletInstanceFactoryImpl.java:63)
	at com.liferay.portlet.PortletInstanceFactoryImpl.clear(PortletInstanceFactoryImpl.java:45)
	at com.liferay.portlet.PortletInstanceFactoryUtil.clear(PortletInstanceFactoryUtil.java:29)
	at com.liferay.portal.service.impl.PortletLocalServiceImpl.initWAR(PortletLocalServiceImpl.java:745)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.liferay.portal.spring.aop.ServiceBeanMethodInvocation.proceed(ServiceBeanMethodInvocation.java:112)
	at com.liferay.portal.spring.aop.ServiceBeanAopProxy.invoke(ServiceBeanAopProxy.java:211)
	at $Proxy65.initWAR(Unknown Source)
	at com.liferay.portal.service.PortletLocalServiceUtil.initWAR(PortletLocalServiceUtil.java:403)
	at com.liferay.portal.deploy.hot.PortletHotDeployListener.doInvokeDeploy(PortletHotDeployListener.java:271)
	at com.liferay.portal.deploy.hot.PortletHotDeployListener.invokeDeploy(PortletHotDeployListener.java:115)
	at com.liferay.portal.kernel.deploy.hot.HotDeployUtil._doFireDeployEvent(HotDeployUtil.java:111)
	at com.liferay.portal.kernel.deploy.hot.HotDeployUtil._fireDeployEvent(HotDeployUtil.java:188)
	at com.liferay.portal.kernel.deploy.hot.HotDeployUtil.fireDeployEvent(HotDeployUtil.java:40)
	at com.liferay.portal.kernel.servlet.PortletContextListener.doPortalInit(PortletContextListener.java:101)
	at com.liferay.portal.kernel.util.BasePortalLifecycle.portalInit(BasePortalLifecycle.java:42)
	at com.liferay.portal.kernel.util.PortalLifecycleUtil.register(PortalLifecycleUtil.java:61)
	at com.liferay.portal.kernel.util.PortalLifecycleUtil.register(PortalLifecycleUtil.java:53)
	at com.liferay.portal.kernel.util.BasePortalLifecycle.registerPortalLifecycle(BasePortalLifecycle.java:52)
	at com.liferay.portal.kernel.servlet.PortletContextListener.contextInitialized(PortletContextListener.java:55)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4765)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5260)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:866)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:842)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:615)
	at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:649)
	at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1581)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)


You should be able to reproduce the problem by adding throw new RuntimeException() in the Portlet.destroy() method.