0
votes

I started to update a wep application from Tomcat 6 to the current version of Tomcat (7-27). The problem arises when I start-up the server with the following error message:

ERROR LifeCycle - Cannot start object org.gatein.pc.portlet.container.PortletInitializationException: Cannot create filter with class com.qnamic.railopt.web.security.portlet.PortletSecurityFilter because it does not implement the expected interface javax.portlet.filter.PortletFilter at org.gatein.pc.portlet.impl.jsr168.ClassInstanceLifeCycle.create(ClassInstanceLifeCycle.java:85) at org.gatein.pc.portlet.impl.jsr168.PortletFilterImpl.start(PortletFilterImpl.java:144) at org.gatein.pc.portlet.impl.container.PortletFilterLifeCycle.invokeStart(PortletFilterLifeCycle.java:66) at org.gatein.pc.portlet.impl.container.LifeCycle.managedStart(LifeCycle.java:93) at org.gatein.pc.portlet.impl.container.PortletApplicationLifeCycle.startDependents(PortletApplicationLifeCycle.java:339) at org.gatein.pc.portlet.impl.container.LifeCycle.managedStart(LifeCycle.java:129) at org.gatein.pc.mc.PortletApplicationDeployment.install(PortletApplicationDeployment.java:153) at org.gatein.pc.mc.PortletApplicationDeployer.add(PortletApplicationDeployer.java:216) at org.gatein.pc.mc.PortletApplicationDeployer.onEvent(PortletApplicationDeployer.java:185) at org.gatein.wci.impl.DefaultServletContainer.safeFireEvent(DefaultServletContainer.java:200) at org.gatein.wci.impl.DefaultServletContainer.fireEvent(DefaultServletContainer.java:219) at org.gatein.wci.impl.DefaultServletContainer.access$400(DefaultServletContainer.java:60) at org.gatein.wci.impl.DefaultServletContainer$RegistrationImpl.registerWebApp(DefaultServletContainer.java:338) at org.gatein.wci.tomcat.TC7ServletContainerContext.start(TC7ServletContainerContext.java:380) at org.gatein.wci.tomcat.TC7ServletContainerContext.lifecycleEvent(TC7ServletContainerContext.java:234) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:168) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556) 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) A: S: R: U: ERROR LifeCycle - Cannot start object org.gatein.pc.portlet.container.PortletInitializationException: Cannot create filter with class com.qnamic.railopt.web.core.portal.ContextFilter because it does not implement the expected interface javax.portlet.filter.PortletFilter at org.gatein.pc.portlet.impl.jsr168.ClassInstanceLifeCycle.create(ClassInstanceLifeCycle.java:85) at org.gatein.pc.portlet.impl.jsr168.PortletFilterImpl.start(PortletFilterImpl.java:144) at org.gatein.pc.portlet.impl.container.PortletFilterLifeCycle.invokeStart(PortletFilterLifeCycle.java:66) at org.gatein.pc.portlet.impl.container.LifeCycle.managedStart(LifeCycle.java:93) at org.gatein.pc.portlet.impl.container.PortletApplicationLifeCycle.startDependents(PortletApplicationLifeCycle.java:339) at org.gatein.pc.portlet.impl.container.LifeCycle.managedStart(LifeCycle.java:129) at org.gatein.pc.mc.PortletApplicationDeployment.install(PortletApplicationDeployment.java:153) at org.gatein.pc.mc.PortletApplicationDeployer.add(PortletApplicationDeployer.java:216) at org.gatein.pc.mc.PortletApplicationDeployer.onEvent(PortletApplicationDeployer.java:185) at org.gatein.wci.impl.DefaultServletContainer.safeFireEvent(DefaultServletContainer.java:200) at org.gatein.wci.impl.DefaultServletContainer.fireEvent(DefaultServletContainer.java:219) at org.gatein.wci.impl.DefaultServletContainer.access$400(DefaultServletContainer.java:60) at org.gatein.wci.impl.DefaultServletContainer$RegistrationImpl.registerWebApp(DefaultServletContainer.java:338) at org.gatein.wci.tomcat.TC7ServletContainerContext.start(TC7ServletContainerContext.java:380) at org.gatein.wci.tomcat.TC7ServletContainerContext.lifecycleEvent(TC7ServletContainerContext.java:234) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:401) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:168) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1566) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1556) 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)

The class com.qnamic.railopt.web.security.portlet.PortletSecurityFilter does implement the interface javax.portlet.filter.PortletFilter:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Principal;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.filter.ActionFilter;
import javax.portlet.filter.EventFilter;
import javax.portlet.filter.FilterChain;
import javax.portlet.filter.FilterConfig;
import javax.portlet.filter.RenderFilter;
import javax.portlet.filter.ResourceFilter;

import org.apache.log4j.Logger;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

public class PortletSecurityFilter implements ActionFilter, EventFilter, RenderFilter, ResourceFilter {

ActionFilter does implement javax.portlet.filter.PortletFilter

The dependent jars are:

  • primefaces-3.2.jar
  • spring-core-3.0.5.RELEASE.jar
  • spring-asm-3.0.5.RELEASE.jar
  • spring-context-3.0.5.RELEASE.jar
  • spring-aop-3.0.5.RELEASE.jar
  • spring-expression-3.0.5.RELEASE.jar
  • spring-webmvc-portlet-3.0.5.RELEASE.jar
  • spring-webmvc-3.0.5.RELEASE.jar
  • spring-context-support-3.0.5.RELEASE.jar
  • portlet-api-2.0.jar
  • Platform-3.8.0.jar
  • jdo-2.0.jar
  • kodo-runtime.jar
  • openjpa-1.0-fast.jar
  • PlanOpt-3.8.0.jar
  • RailOptBase-3.8.0.jar
  • portletfaces-bridge-api-2.0.0-RC1.jar
  • portletfaces-bridge-impl-2.0.0-RC1.jar
  • portletfaces-logging-1.1.0.jar
  • commons-collections-3.2.1.jar
  • spring-web-3.0.5.RELEASE.jar
  • aopalliance-1.0.jar
  • spring-beans-3.0.5.RELEASE.jar
  • spring-security-web-3.0.5.RELEASE.jar
  • spring-security-core-3.0.5.RELEASE.jar
  • spring-tx-3.0.3.RELEASE.jar
  • aspectjrt-1.6.8.jar
  • aspectjweaver-1.6.8.jar
  • spring-security-config-3.0.5.RELEASE.jar
  • log4j-1.2.15.jar
  • el-api-1.0.jar
  • slf4j-api-1.5.8.jar
  • servlet-api-2.5.jar
  • jstl-1.2.jar
  • commons-lang-2.5.jar
  • RailOptIntegration-3.8.0.jar
  • google-collections-1.0.jar
  • junit-4.8.2.jar
  • commons-io-2.0.1.jar
  • el-impl-2.2.jar
  • javax.faces-2.1.7.jar

Some dependencies have the scope "provided" and are not included in the war (as long tomcat doesn't use them)!

Part of my portlet.xml

<filter>
<filter-name>PortletSecurityFilter</filter-name>
        <filter-class>com.qnamic.railopt.web.security.portlet.PortletSecurityFilter</filter- class>
    <lifecycle>ACTION_PHASE</lifecycle>
    <lifecycle>EVENT_PHASE</lifecycle>
    <lifecycle>RENDER_PHASE</lifecycle>
    <lifecycle>RESOURCE_PHASE</lifecycle>
    <init-param>
        <name>message</name>
        <value>Security Filter</value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>PortletSecurityFilter</filter-name>
    <portlet-name>*</portlet-name>
</filter-mapping>

The other dependencies are found in a parent project:

  • pc-api-2.2.0-GA.jar
  • pc-controller-2.2.0-GA.jar
  • pc-portlet-2.2.0-GA.jar
  • pc-mc-2.2.0-GA.jar
  • wci-wci-2.1.1-GA.jar
  • wci-tomcat7-2.1.1-GA.jar

When I debug the code in org.gatein.pc.portlet.impl.jsr168.ClassInstanceLifeCycle.create(...) it stops on the second line

Class clazz = classLoader.loadClass(className);
if (expectedClass.isAssignableFrom(clazz)) {
    Class<? extends T> castedClass = clazz.asSubclass(expectedClass);
    Constructor<? extends T> ctor = castedClass.getConstructor();
    instance = ctor.newInstance();
}
else  {
    String msg = "Cannot create " + type + " with class " + className + " because it does not   implement the expected interface " + expectedClass.getName();
    throw new PortletInitializationException(msg);
}

My suggestion was first that there is a problem with the class loader but it shouldn't be, because the first line correctly loads the class PortletSecurityFilter. The expected class is javax.portlet.filter.PortletFilter as expected. Why the class is not assignable from?

I thank for any help!

1

1 Answers

1
votes

I must admit that I have no idea what is the exact version of GateIn you used to meet this issue but anyway I could reproduce this issue with GateIn-3.2.0.Final-tomcat7 by simply keeping (on purpose) portlet-api-2.0.jar in the WEB-INF/lib directory of my war file. I could then get something like:

28 janv. 2013 15:48:09 org.gatein.common.logging.Logger log
GRAVE: Cannot start object
org.gatein.pc.portlet.container.PortletInitializationException: Cannot create filter with class org.exoplatform.tutorial.portlet.MyPortletFilter because it does not implement the expected interface javax.portlet.filter.PortletFilter
    at org.gatein.pc.portlet.impl.jsr168.ClassInstanceLifeCycle.create(ClassInstanceLifeCycle.java:85)
    at org.gatein.pc.portlet.impl.jsr168.PortletFilterImpl.start(PortletFilterImpl.java:144)
    at org.gatein.pc.portlet.impl.container.PortletFilterLifeCycle.invokeStart(PortletFilterLifeCycle.java:66)
    at org.gatein.pc.portlet.impl.container.LifeCycle.managedStart(LifeCycle.java:93)
    at org.gatein.pc.portlet.impl.container.PortletApplicationLifeCycle.startDependents(PortletApplicationLifeCycle.java:339)
    at org.gatein.pc.portlet.impl.container.LifeCycle.managedStart(LifeCycle.java:129)
    at org.gatein.pc.portlet.impl.deployment.PortletApplicationDeployment.install(PortletApplicationDeployment.java:153)
    at org.gatein.pc.portlet.impl.deployment.PortletApplicationDeployer.add(PortletApplicationDeployer.java:199)
    at org.gatein.pc.portlet.impl.deployment.PortletApplicationDeployer.onEvent(PortletApplicationDeployer.java:168)
    at org.gatein.wci.impl.DefaultServletContainer.safeFireEvent(DefaultServletContainer.java:200)
    at org.gatein.wci.impl.DefaultServletContainer.addWebAppListener(DefaultServletContainer.java:166)
    at org.gatein.pc.portlet.impl.deployment.PortletApplicationDeployer.start(PortletApplicationDeployer.java:241)
    at org.exoplatform.portal.pc.ExoKernelIntegration.start(ExoKernelIntegration.java:178)
    at sun.reflect.GeneratedMethodAccessor53.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.exoplatform.container.LifecycleVisitor.traverse(LifecycleVisitor.java:100)
    at org.exoplatform.container.LifecycleVisitor.start(LifecycleVisitor.java:170)
    at org.exoplatform.container.ConcurrentPicoContainer.start(ConcurrentPicoContainer.java:554)
    at org.exoplatform.container.ExoContainer.start(ExoContainer.java:266)
    at org.exoplatform.container.PortalContainer.start(PortalContainer.java:667)
    at org.exoplatform.container.ExoContainer.start(ExoContainer.java:254)
    at org.exoplatform.container.RootContainer.createPortalContainer(RootContainer.java:399)
    at org.exoplatform.container.RootContainer.registerPortalContainer(RootContainer.java:266)
    at org.exoplatform.portal.application.PortalController.afterInit(PortalController.java:114)
    at org.exoplatform.container.web.AbstractHttpServlet.init(AbstractHttpServlet.java:79)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1201)

I could fix it by simply removing portlet-api-2.0.jar from WEB-INF/lib of my webapp (or defining this dependency in maven as provided). This happens simply because the jar file is already in tomcat/lib so the Portlet Container refers to the class javax.portlet.filter.PortletFilter that has been loaded from the common ClassLoader of Tomcat and your Filter implements the class javax.portlet.filter.PortletFilter that has been loaded from the ClassLoader of your webapp (from WEB-INF/lib), even if the FQN of these 2 classes are equal, they are not considered as the same classes that is the reason why expectedClass.isAssignableFrom(clazz) returns false.