应用程序的问题,其中EJB连接保持打开状态,后续连接打开和关闭

时间:2017-05-15 20:39:44

标签: jboss ejb

在打开和关闭其他ejb连接时保持和ejb连接打开是否常见或可接受,或者一旦客户端完成连接并为后续任务打开一个新连接就应关闭连接?

我目前正在使用一个使用EJB的Swing应用程序(JBoss AS 7.1.1.final)。应用程序打开一个ejb连接(即创建一个InitialContext实例),然后只要应用程序保持运行,就将该InitialContext用于常见任务。有许多长时间运行的操作,其中创建了额外的ejb连接(和InitialContext)。此连接用于单个长时间运行的进程,然后关闭。

在JBoss上,关于第40个连接打开和关闭后,我得到如下所示的异常。

2017 May 15, 16:29:03 INFO  - (JBossEJBClient.java:121) initialize - JNDI context initialized. 
java.lang.IllegalStateException: No EJB receiver available for handling [appName:dtsjboss,modulename:dtsserverejb,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@4e692639
    at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
    at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
    at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
    at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
    at com.sun.proxy.$Proxy4.getAuthorities(Unknown Source)
    at com.apelon.dts.examples.errors.ejb.EjbConnectionNotClosedErrorExample.doTest(EjbConnectionNotClosedErrorExample.java:53)
    at com.apelon.dts.examples.errors.ejb.EjbConnectionNotClosedErrorExample.bothCasesShouldSucceed(EjbConnectionNotClosedErrorExample.java:34)
    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:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

如果我运行下面的代码,使用和关闭ejb连接的情况有效,但是单个连接保持打开的情况会因上面的堆栈跟踪而失败。

package com.myCompany.myApp.examples.errors.ejb;

import java.util.List;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;

import org.apache.log4j.Logger;
import org.junit.Test;

import com.myCompany.myApp.client.jboss.JBossEJBClient;
import com.myCompany.myApp.dao.client.myAppServiceClient;
import com.myCompany.myApp.dao.client.myAppServiceClientParams;
import com.myCompany.myApp.testing.util.logging.LoggerForIntegrationTests;
import com.myCompany.myAppserver.dao.remote.AuthorityDao;
import com.myCompany.myAppserver.types.TAuthority;
import com.myCompany.install.util.ejb.ejbclient.myAppServiceClientFactory;

public class EjbConnectionNotClosedErrorExample {

    private static Logger logger = LoggerForIntegrationTests.get();

    private static final int COUNT = 100;

    @Test
    public void bothCasesShouldSucceed() {
        try {
            logger.debug("Doing case that works");
            doTest(true);
            logger.debug("Done with case that works.");
            logger.debug("\n\n\n");
            logger.debug("********************* DOING CASE THAT FAILS *********************");
            doTest(false);
            logger.debug("Done with use case that didn't work.");
        } catch (Exception exp) {
            exp.printStackTrace();
            throw new RuntimeException(exp);
        }
    }

    private void doTest(boolean closeConnection) {
        myAppServiceClientParams params = myAppServiceClientFactory.getDefaultClientParams();
        JBossEJBClient blocker = new JBossEJBClient();
        blocker.initialize(params);
        if (closeConnection == true) {
            blocker.close();
        }
        int max = COUNT;
        for (int i = 0; i < max; i++) {
            myAppServiceClient client = myAppServiceClientFactory.getDefaultClient();
            AuthorityDao dao = client.createAuthorityDao();
            List<TAuthority> list = dao.getAuthorities();
            logger.debug("CONNECTION " + (i + 1) + " ------------------------------------------------");
            logger.debug("Got " + list.size() + " authorities.");
            client.close();
        }
        System.out.println("");
    }

    public void initialize(myAppServiceClientParams params) {
        this.initialize(params.getHost(), params.getPort(), params.getInstance(), params.getUid(), params.getPwd());
    }

    public void initialize(String host, int port, String instance, String user, String password) {
        final Properties jndiProperties = new Properties();
        String providerURL = "remote://" + host + ":" + port;
        jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, org.jboss.naming.remote.client.InitialContextFactory.class.getName());
        jndiProperties.put(Context.PROVIDER_URL, providerURL);
        jndiProperties.put("jboss.naming.client.ejb.context", true);
        jndiProperties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
        // Explicitly specify STARTTLS = false for connecting to Wildfly v10
        jndiProperties.put("jboss.naming.client.connect.options.org.xnio.Options.SSL_STARTTLS", "false");
        jndiProperties.put(Context.SECURITY_PRINCIPAL, user);
        jndiProperties.put(Context.SECURITY_CREDENTIALS, password);
        try {
            InitialContext ctx = new InitialContext(jndiProperties);
            ctx.getEnvironment();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

这是一个特定于JBoss AS 7.1.1.final的错误吗?

1 个答案:

答案 0 :(得分:0)

这里的问题是单个连接被打开并被应用程序的主线程用作资源,并且(由于某种原因)导致JBoss不能完全取消分配其他连接。解决方案是在打开它时获取对此连接的引用,然后在创建任何其他新连接之前关闭此连接,然后在创建新连接后立即重新打开主线程使用的连接。