【问题标题】:Glassfish EJB Remote Interface Multithreaded ApplicationGlassfish EJB 远程接口多线程应用程序
【发布时间】:2012-01-18 16:15:23
【问题描述】:

我有一个多线程 Java SWT 应用程序,它连接到远程无状态 bean 以进行一些数据处理。我在 jdk 1.7.0_02 下的 Windows 7 32 位操作系统上运行 Glassfish 3.1.1(内部版本 12)。

对于每个访问 EJB 的线程,我都会创建一个新的远程接口对象,例如我有 2 个并行执行的线程,

Thread-1
LoginBeanRemote ejbClient = (LoginBeanRemote) new InitialContext().lookup("LoginBean");
ejbClient.doSomething();

Thread-2
LoginBeanRemote ejbClient = (LoginBeanRemote) new InitialContext().lookup("LoginBean");
ejbClient.doSomethingDifferent();

现在它一半时间运行良好,其余时间在第二行给出“NullPointerException”。

SEVERE: java.lang.NullPointerException
    at com.mypackage.myclass.getListofOperators(LoginBean.java:270)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
    at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
    at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5366)
    at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
    at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
    at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
    at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
    at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5338)
    at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5326)
    at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:206)
    at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:79)
    at $Proxy180.getListofOperators(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie.dispatchToMethod(ReflectiveTie.java:144)
    at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:174)
    at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:528)
    at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:199)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1624)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1486)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:990)
    at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:214)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:742)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:539)
    at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2324)
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)

SEVERE:     at com.mypackage.myclass.getListofOperators(LoginBean.java:270)
SEVERE:     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
SEVERE:     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
SEVERE:     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
SEVERE:     at java.lang.reflect.Method.invoke(Method.java:601)
SEVERE:     at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
SEVERE:     at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
SEVERE:     at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:5366)
SEVERE:     at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:619)
SEVERE:     at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
SEVERE:     at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:571)
SEVERE:     at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doAround(SystemInterceptorProxy.java:162)
SEVERE:     at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:144)
SEVERE:     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
SEVERE:     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
SEVERE:     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
SEVERE:     at java.lang.reflect.Method.invoke(Method.java:601)
SEVERE:     at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:861)
SEVERE:     at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:800)
SEVERE:     at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:370)
SEVERE:     at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5338)
SEVERE:     at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5326)
SEVERE:     at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:206)
SEVERE:     at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:79)
SEVERE:     at $Proxy180.getListofOperators(Unknown Source)
SEVERE:     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
SEVERE:     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
SEVERE:     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
SEVERE:     at java.lang.reflect.Method.invoke(Method.java:601)
SEVERE:     at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie.dispatchToMethod(ReflectiveTie.java:144)

SEVERE:     at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:174)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:528)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:199)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1624)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1486)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:990)
SEVERE:     at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:214)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:742)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:539)
SEVERE:     at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2324)
SEVERE:     at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
SEVERE:     at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)

此外,异常并不总是来自同一个线程,它可以是 ejbClient.doSomething() 或 ejbClient.doSomethingDifferent()

我没有为 entitymanager 使用注入,因为我需要为不同的会话提供不同的用户名和密码,并按照

properties.put("javax.persistence.jdbc.user", loginName);
properties.put("javax.persistence.jdbc.password", password);
properties.put("javax.persistence.jdbc.url", "jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
properties.put("javax.persistence.jdbc.driver", "oracle.jdbc.driver.OracleDriver");

EntityManagerFactory emf = Persistence.createEntityManagerFactory("xadp", properties);
EntityManager em = emf.createEntityManager(properties); 

有什么想法吗?

【问题讨论】:

    标签: glassfish ejb


    【解决方案1】:

    没有看到更多代码,我只能猜测,但很可能您在会话 bean 中使用了实例变量。

    关于会话 bean 的问题在于,即使使用无状态会话 bean,容器(在本例中为 Glassfish)也可以汇集 bean。这意味着它有许多会话 bean 实例来服务请求并在客户端之间共享它们。

    关键是会话bean可以随时交给另一个客户端,所以如果你将bean中的状态保存在实例或静态字段中,你可能会让客户端A调用然后中途中断,所以客户端 B 可以看到客户端 A 的数据。

    【讨论】:

    • 嗨 Jim,感谢您的回复,您可能是对的,因为我没有注入 entitymanager,而是使用属性从 EntityManagerFactory 构建它,因此该对象可能在 bean 之间共享。现在我必须这样做,因为对于不同的用户,bean 为底层数据库连接接收不同的用户名和密码。我认为我不能为数据源提供不同的用户名/密码并同时使用注入?对?那么在这种情况下,如果我不能使用注射,我该怎么办?
    • 什么变量在第 270 行给出 NullPointerException?另外,我不在贵公司的脑海中,但是不同用户在数据库中具有不同用户名的用例似乎很可疑。通常,您将通过其他方式(例如 LDAP)进行身份验证,然后让所有用户使用服务器上的单个用户名/密码连接到数据库。通过该设置,您可以使用 @RolesAllowed 注释作为开始来控制 access
    • 另一个想法,因为你没有注入 EntityManager,你可能需要做一些工作来确保它加入正确的事务。类似this
    • 再次感谢 Jim 抽出宝贵时间。该应用程序是多用户和多线程的,因此用户可以拥有多个线程,但每个用户将只有一个 u/p,最初的问题是应用程序在单线程中运行良好,但是一旦同时发生两个线程,其中一个就给出了 NPE .异常完全从服务器日志粘贴到上面,它发生在我尝试在远程接口上调用方法的那一行。基于用户名/密码创建 entitymanager 的原因是基于用户的访问管理是由底层 Oracle DB 完成的。
    • 我可以使用@RolesAllowed 注释,但我认为我必须自己进行用户管理。我将探索您提出的选项并提供反馈。再次感谢所有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 2018-02-03
    • 2012-04-10
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 2020-09-16
    相关资源
    最近更新 更多