代码之家  ›  专栏  ›  技术社区  ›  SCote

EJB主接口上的WebLogic类强制转换

  •  1
  • SCote  · 技术社区  · 9 年前

    使用反射,我们可以看到返回的类确实实现了预期的接口,但当我们尝试强制转换时,它总是抛出java.lang.ClassCastException。

    工作原理是,一个类加载器用于支持容器中的EJB,另一个不相关的类加载者为servlet提供服务,因此返回的类不能从另一个类加载程序转换到接口类中。我们无法确认这一点,但我们怀疑类加载器层次结构在WLS 8.1和12c之间发生了变化。如果是这样的话,我们就找不到解决办法。

    我们已经开始使用WebLogic类加载器分析工具,但它并没有指出与此特定情况有关的任何类的问题。

    要明确的是,该代码在WebLogic Server 8.1中工作,但在WebLogicServer 12c中不工作。EJB部署描述符已使用weblogic进行了更新。DDConverter,但我们在转换之前也遇到了这个问题。

    这是我们在JndiHelper类中查找EJB的方式(这适用于WLS8):

    public static EJBHome getHome( String ejbHomeName ) throws NamingException {
      EJBHome home = null;
      String sENCHome = JNDI_ENC_EJB_CONTEXT + "/" + ejbHomeName;
      Object objRef = new InitialContext().lookup( sENCHome );
      home = (EJBHome)PortableRemoteObject.narrow( objRef, EJBHome.class );
      return home;
    }
    

    下面是调用上述代码、进行cast并在失败时打印诊断信息的代码:

    EJBHome home = null;
    try {
      home = JndiHelper.getHome( JndiConstants.USER_HANDLER_EJB );
      UserHandlerHome userHandlerHome = (UserHandlerHome)home; // throws class cast exception here
      UserHandler userHandler = userHandlerHome.create();
      adminInd = userHandler.isAdmin( userId );
    } catch ( ClassCastException e ) {
      StringBuffer b = new StringBuffer( "ClassCastException: " );
      b.append( e.getMessage() );
      b.append( "\r\nThe JNDI lookup for '" );
      b.append( JndiConstants.USER_HANDLER_EJB );
      b.append( "' returned a bean of unexpected type.\r\nValue:" );
      b.append( home );
      b.append( "\r\nReturned bean's inheritance:\r\n" );
      b.append( Reflector.getInheritanceDump( home ) );
      b.append( "\r\n" );
      b.append( UserHandlerHome.class.getName() );
      b.append( " expected.\r\nFull Stack Trace:\r\n" );
      b.append( ExceptionUtil.stackTrace( e ) );
      Logger.error( this, b.toString() );
      errors.add( ActionErrors.GLOBAL_ERROR, new WebActionError( MessageConstants.NON_DESCRIPT_ERROR, WebActionError.makePopUp( b.toString() ) ) );
    }
    

    以下是显示的诊断信息示例。注意继承列表包含后缀为“(I)”的类型和接口:

    ERROR com.myapp.admin.controller.UserHelper - ClassCastException: com.myapp.admin.model.UserHandler_8cwrmw_HomeImpl cannot be cast to com.myapp.admin.model.UserHandlerHome
    The JNDI lookup for 'UserHandler' returned a bean of unexpected type.
    Value:com.myapp.admin.model.UserHandler_8cwrmw_HomeImpl@5f938f12
    Returned bean's inheritance:
    com.myapp.admin.model.UserHandler_8cwrmw_HomeImpl
    weblogic.ejb.container.internal.StatelessEJBHome
    weblogic.ejb.container.internal.BaseEJBHome
    java.lang.Object
    weblogic.ejb.container.interfaces.BaseEJBRemoteHomeIntf(I)
    weblogic.ejb.container.interfaces.BaseEJBHomeIntf(I)
    weblogic.ejb.spi.BaseEJBHomeIntf(I)
    weblogic.ejb20.interfaces.RemoteHome(I)
    javax.ejb.EJBHome(I)
    java.rmi.Remote(I)
    weblogic.ejb.spi.RemoteHome(I)
    weblogic.rmi.SupportsInterfaceBasedCallByReference(I)
    com.myapp.admin.model.UserHandlerHome(I)
    com.myapp.admin.model.UserHandlerHome expected.
    Full Stack Trace:
    java.lang.ClassCastException: com.myapp.admin.model.UserHandler_8cwrmw_HomeImpl cannot be cast to com.myapp.admin.model.UserHandlerHome
            at com.myapp.admin.controller.UserHelper.isAdmin(UserHelper.java:82)
            at com.myapp.framework.controller.login.LoginAction.doAction(LoginAction.java:278)
            at com.myapp.framework.controller.AfgAction.perform(AfgAction.java:268)
            at org.apache.struts.action.ActionServlet.processActionPerform(ActionServlet.java:1888)
            at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1654)
            at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:526)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
            at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)
            at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)
            at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)
            at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)
            at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:247)
            at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3679)
            at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3649)
            at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:326)
            at weblogic.security.service.SecurityManager.runAsForUserCode(SecurityManager.java:197)
            at weblogic.servlet.provider.WlsSecurityProvider.runAsForUserCode(WlsSecurityProvider.java:203)
            at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:71)
            at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2433)
            at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2281)
            at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2259)
            at weblogic.servlet.internal.ServletRequestImpl.runInternal(ServletRequestImpl.java:1686)
            at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1646)
            at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:270)
            at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:348)
            at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:333)
            at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:54)
            at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41)
            at weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:640)
            at weblogic.work.ExecuteThread.execute(ExecuteThread.java:406)
            at weblogic.work.ExecuteThread.run(ExecuteThread.java:346)
    

    在WEB-INF\weblogic中。xml我们有以下内容:

    <?xml version="1.0" encoding="UTF-8"?>
    <weblogic-web-app>
    
        <jsp-descriptor>
            <keepgenerated>true</keepgenerated>
            <backward-compatible>true</backward-compatible>
        </jsp-descriptor>
    
        <container-descriptor>
            <prefer-application-packages>
                <!-- Resolves finding Log4J classes (Issue T9) -->
                <package-name>org.apache.log4j.*</package-name>
                <package-name>org.apache.log4j.pattern.*</package-name>
                <package-name>org.apache.log4j.net.*</package-name>
                <package-name>org.apache.log4j.jmx.*</package-name>
                <package-name>org.apache.log4j.jdbc.*</package-name>
                <package-name>org.apache.log4j.helpers.*</package-name>
                <package-name>org.apache.log4j.config.*</package-name>
                <!-- Recommended by the Classloader Analysis Tool to resolve reported conflicts -->
                <package-name>com.myapp.admin.*</package-name>
                <package-name>com.myapp.framework.*</package-name>
                <package-name>com.myapp.om.*</package-name>
                <package-name>com.sun.mail.*</package-name>
                <package-name>javax.mail.*</package-name>
                <package-name>javax.mail.event.*</package-name>
                <package-name>javax.mail.internet.*</package-name>
                <package-name>javax.mail.search.*</package-name>
                <package-name>javax.wsdl.*</package-name>
                <package-name>javax.wsdl.extensions.*</package-name>
                <package-name>javax.wsdl.factory.*</package-name>
                <package-name>javax.wsdl.xml.*</package-name>
                <package-name>javax.xml.rpc.*</package-name>
                <package-name>org.apache.commons.*</package-name>
            </prefer-application-packages>
        </container-descriptor>
    
    </weblogic-web-app>
    

    任何帮助都将不胜感激。

    1 回复  |  直到 9 年前
        1
  •  0
  •   SCote    9 年前

    我们通过删除解决了此问题 <prefer-application-packages> 从…起 weblogic.xml weblogic.utils.classloaders.ChangeAwareClassLoader 要加载其自己版本的接口及其父接口,请 weblogic.utils.classloaders.GenericClassLoader 其支持该应用。由于web应用程序试图强制转换到与由不同类加载器解析的EJB中的接口版本不匹配的接口版本,因此不允许强制转换。

    推荐文章