0

我有一个 EJB 服务器在一台 Liberty 服务器上运行,而客户端在另一台服务器上运行。

如果我使用下面的代码手动查找远程 EJB,我可以访问 EJB。

Context ctx = new InitialContext();
Object homeObject = ctx.lookup("corbaname::localhost:22809#ejb/global/TempEAR-0.0.1/com.ibm.temp-TempEJB-0.0.1/ConverterBean!com.ibm.temp.ejb.ConverterRemote")
ConverterRemote myRemoteEJB = (ConverterRemote) PortableRemoteObject.narrow(homeObject, ConverterRemote.class);
System.out.println("RESULT " + myRemoteEJB.celsiusToFar(1));

上述工作按预期工作,它能够调用在其他服务器实例上运行的远程 EJB 并按预期工作。

我正在尝试在我的@Controller类中使用 Spring,并通过注释@EJB或引用 EJB@Autowired

@EJB(name="testRemoteEJB")
ConverterRemote testRemoteEJB;

mvc-调度程序-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/jee        
        http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

    <context:component-scan
        base-package="com.ibm.common.controller" />

    <mvc:annotation-driven />

    <jee:remote-slsb id="testRemoteEJB"
        jndi-name="jndi/testRemoteEJB"
        business-interface="com.ibm.temp.ejb.ConverterRemote">
    </jee:remote-slsb>  
</beans>

自由服务器.xml

  <jndiEntry id="testRemoteEJB" jndiName="jndi/testRemoteEJB" value="corbaname::localhost:22809#ejb/global/TempEAR-0.0.1/com.ibm.temp-TempEJB-0.0.1/ConverterBean!com.ibm.temp.ejb.ConverterRemote"/>

当我打印出 testRemoteEJB 对象时,它返回一个com.sun.proxy.$Proxy41对象,当我尝试调用方法函数时,我得到以下异常

[err] org.springframework.remoting.RemoteProxyFailureException: No matching RMI stub method found for: public abstract double com.ibm.temp.ejb.Converter.celsiusToFar(double) throws java.rmi.RemoteException; nested exception is java.lang.NoSuchMethodException: java.lang.String.celsiusToFar(double)
[err]   at org.springframework.remoting.rmi.RmiClientInterceptorUtils.invokeRemoteMethod(RmiClientInterceptorUtils.java:83)
[err]   at org.springframework.ejb.access.SimpleRemoteSlsbInvokerInterceptor.doInvoke(SimpleRemoteSlsbInvokerInterceptor.java:98)
[err]   at org.springframework.ejb.access.AbstractRemoteSlsbInvokerInterceptor.invokeInContext(AbstractRemoteSlsbInvokerInterceptor.java:140)
[err]   at org.springframework.ejb.access.AbstractSlsbInvokerInterceptor.invoke(AbstractSlsbInvokerInterceptor.java:189)
[err]   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[err]   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
[err]   at com.sun.proxy.$Proxy41.celsiusToFar(Unknown Source)
[err]   at com.ibm.common.controller.JSONController.lookupEJB(JSONController.java:89)
[err]   at com.ibm.common.controller.JSONController.getTempCtoF(JSONController.java:157)
[err]   at sun.reflect.GeneratedMethodAccessor663.invoke(Unknown Source)
[err]   at java.lang.reflect.Method.invoke(Method.java:498)
[err]   at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
[err]   at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
[err]   at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
[err]   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
[err]   at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
[err]   at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
[err]   at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
[err]   at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
[err]   at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
[err]   at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
[err]   at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
[err]   at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
[err]   at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
[err]   at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1258)
[err]   at [internal classes]
[err]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[err]   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[err]   at java.lang.Thread.run(Thread.java:748)
[err] Caused by: java.lang.NoSuchMethodException: java.lang.String.celsiusToFar(double)
[err]   at java.lang.Class.getMethod(Class.java:1786)
[err]   at org.springframework.remoting.rmi.RmiClientInterceptorUtils.invokeRemoteMethod(RmiClientInterceptorUtils.java:75)
[err]   ... 48 more

所以很明显远程查找没有解决,但我很困惑,因为我知道我可以手动访问它,所以连接字符串应该是有效的。

如果有什么我可能会丢失?

这最初与传统的 WAS 一起使用,但不适用于 Liberty

4

1 回答 1

0

@EJB注释旨在提供与工作手册示例的前 3 行等效的内容,然后在应用注释的字段上设置结果。因此,它应该执行以下操作:

Context ctx = new InitialContext();
Object homeObject = ctx.lookup("corbaname::localhost:22809#ejb/global/TempEAR-0.0.1/com.ibm.temp-TempEJB-0.0.1/ConverterBean!com.ibm.temp.ejb.ConverterRemote")
ConverterRemote myRemoteEJB = (ConverterRemote) PortableRemoteObject.narrow(homeObject, ConverterRemote.class);

如果带有注释的字段位于 Java EE 容器托管对象上,例如 servlet、servlet 过滤器、EJB、拦截器等,那么 Liberty 将执行该行为并且@EJB注释将按预期工作。

但是,在这种情况下,@EJB注释位于 springframework 托管对象上,因此执行@EJB注释处理的是 springframework,并且似乎 springframework 省略了“PortableRemoteObject.narrow()”的使用。

CORBA 远程对象的 COS 命名查找不能保证返回远程接口的特定 _Stub 实现。很可能,它是通用存根类的一个实例,例如org.omg.stub.java.rmi._Remote_Stub. 当 springframework 然后尝试在这样的存根上调用方法时,它将失败并返回 NoSuchMethodException,因为存根没有实现远程接口。执行narrow()将通用 Stub 实例转换为实现远程接口的特定 Stub 实例。如果可以更新 springframework 以执行narrow(),那么该场景将起作用。

这个场景的行为在传统的 WebSphere 和 Liberty 之间会有所不同,因为它们都使用非常不同的 CORBA ORB 实现。

传统的 WebSphere 使用 IBM ORB,它预计应用程序将需要一个特定的 Stub 类,并尝试在查找时提供一个缩小的 stub;随后的 narrow() 调用将是无操作的。IBM ORB 积极主动地尝试改进性能。但是,应该注意的是,即使使用 IBM ORB,查找时返回的 Stub 并不总是特定的 Stub;anarrow()应始终执行。

Liberty 使用 Yoko ORB,它不会尝试在 JNDI 查找上返回特定的 Stubs 实例,因为这不是规范所要求的。返回的 Stub 几乎总是一个通用的 Stub,并且查找应该总是跟在一个narrow().

要么需要更新应用程序以@EJB在 Java EE 托管对象上使用,要么需要更改 springframework 使用的机制以获取 EJB 引用,以便narrow()执行 a。

于 2022-03-04T23:29:16.940 回答