java - EJB Home 接口(interface)上的 WebLogic 类转换

标签 java jakarta-ee weblogic weblogic12c

我们正在将 J2EE 应用程序 (EJB 2.0) 从 WebLogic Service 8.1 升级到 12c(12.2.1.1.0)。我们正在将分解的 EAR 构建到域目录中的目录中。 Web 应用程序 (struts) 在 JNDI 中执行查找并获取对 EJB 的引用并返回一个主类。我们遇到的问题是它无法转换到接口(interface)。

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

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

我们已开始使用 WebLogic 类加载器分析工具,但它并未表明与此特定案例相关的任何类存在问题。

核心问题是我们必须进行哪些更改才能使转换像 WebLogic 8.1 一样工作,从而避免重构现有代码?

需要明确的是,该代码可以在 WebLogic Server 8.1 中运行,但不能在 WebLogic Server 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;
}

这里是调用上面的代码,进行转换,并在失败时打印出诊断信息:

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)”的类型和接口(interface):

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>

如有任何帮助,我们将不胜感激。

最佳答案

我们通过删除 <prefer-application-packages> 解决了这个问题来自weblogic.xml这导致了 weblogic.utils.classloaders.ChangeAwareClassLoader加载其自己的接口(interface)版本及其父接口(interface) weblogic.utils.classloaders.GenericClassLoader支持该应用程序。由于 Web 应用程序试图转换为与不同类加载器解析的 EJB 中的接口(interface)版本不匹配的接口(interface)版本,因此不允许转换。

关于java - EJB Home 接口(interface)上的 WebLogic 类转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39854571/

相关文章:

java - Spring 自定义格式化程序不工作

java - Hibernate Persistencebag 从列表中删除元素

jakarta-ee - 在 Websphere7 中启用基于角色的安全性

java - Weblogic 12c 与 Oracle 数据库 18c : setTransactionOnly() called on transaction error

java - 无法在 WebLogic Server 12c 中部署 EJB

java - 在 IntelliJ 中浏览自动完成选项时查看完整的 javadoc

java - 我需要从 Microsoft Exchange 服务器上托管的电子邮件发送电子邮件

Java 随机化并从函数返回一个数组

java - Struts <bean :write> tags

WebLogic 12c 获取真实路径