2 Replies Latest reply on Oct 28, 2015 5:31 PM by David Lloyd

    Wildfly 8.2.1.Final - EJB000025 - Life cycle management

    Theunis de Jongh Newbie

      Hi,

       

      I need some assistance with remote EJB calls, and the error "java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling".

      To be clear - I have a solution to the error, but what I am after is a deeper/clearer understanding of the

      EJBClientContext life cycle, and where it should be managed.

       

      Let's distinguish between the two invocation styles:

      1. JNDI invocation - with ("jboss.naming.client.ejb.context", true).

      2. EJB Client Properties invocation.

       

      Style #1: JNDI

      I find that rapid EJB invocation gives the EJBCLIENT000025 error after about 20 EJB method invocations.

       

      Referring to documentation on scoped EJB contexts,

        https://docs.jboss.org/author/display/WFLY8/Scoped+EJB+client+contexts

      if I close the ejbRootNamingContext explicitly, I can perform thousands of EJB method invocations

      without the EJBCLIENT000025 error.

       

                      try {

                          // close the EJB naming JNDI context

                          ejbRootNamingContext.close();

                      } catch (Throwable t) {

                          t.printStackTrace();

                      }

                      try {

                          // also close our other JNDI context since we are done with it too

                          jndiCtx.close();

                      } catch (Throwable t) {l

                          t.printStackTrace();

                      }

       

      I debugged the EJBClientContext code, and found that the error originates here:

       

      EJBReceiver requireEJBReceiver(final EJBClientInvocationContext clientInvocationContext, final String appName, final String moduleName, final String distinctName)

                  throws IllegalStateException {

              // try and find a receiver which can handle this combination

              final EJBReceiver ejbReceiver = this.getEJBReceiver(clientInvocationContext, appName, moduleName, distinctName);

              if (ejbReceiver == null) {

      ====>      throw Logs.MAIN.noEJBReceiverAvailableForDeploymentDuringInvocation(appName, moduleName, distinctName, clientInvocationContext);

              }

              return ejbReceiver;

          }

       

      ==> The reason for EJB Receiver being null, is that the EJBClientContext.close() method is invoked, which then leads to the EJB

          Receiver not being found.

      Questions:

      1. Which component invokes the close() method? Even if I re-create the context on every call, it gets closed after a certain

         amount of calls. This leads me to believe that some sort of server-side state is involved. Am I correct?

      2. Must I absolutely close the ejbRootNamingContext after every EJB method invocation? Can I not increase the timeout before

         the context gets closed?


      Style #2: EJB Client Properties

      Does the use of this style - which I have not experimented with extensively - make client-side lifecycle management unnecessary?

        • 1. Re: Wildfly 8.2.1.Final - EJB000025 - Life cycle management
          Theunis de Jongh Newbie

          So ... I tried with the Style #2 (ejb:) protocol as well - utilizing the programmatic approach:

           

               try {

                      EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(ejbProperties);

                      final ContextSelector<EJBClientContext> ejbClientContextSelector = new ConfigBasedEJBClientContextSelector(cc);

                      for (int i=0;i<10000;i++) {

                          final ContextSelector<EJBClientContext> previousSelector = EJBClientContext.setSelector(ejbClientContextSelector);

                          StatelessEJBLocator<ExampleRemote> locator = new StatelessEJBLocator(ExampleRemote.class, "EAR", "EJB", "ExampleBean", "");

                          System.out.println("[" + i + "]" + org.jboss.ejb.client.EJBClient.createProxy(locator).exampleMethod());

                      }

                  }catch (Exception e ) {

                      e.printStackTrace();

                  }

           

          Observations:

          1. They key line is the ejbClientContextSelector one.

          2. If I keep it outside of the loop - I can create 10000 proxies, and invoke the method successfully.

          3. If I move it into the loop - I can perform 40 invocations before EJBCLIENT000025 surfaces.

           

          Which resource is being exhausted? I have Undertow configured for 15000 concurrent connections.

           

          A snippet from ConfigBasedEJBClientContextSelector:

           

          public ConfigBasedEJBClientContextSelector(final EJBClientConfiguration ejbClientConfiguration, final ClassLoader classLoader) {

                  this.ejbClientConfiguration = ejbClientConfiguration;

                  // create a empty context

                  if (classLoader == null) {

                      this.ejbClientContext = EJBClientContext.create(this.ejbClientConfiguration);

                  } else {

                      this.ejbClientContext = EJBClientContext.create(this.ejbClientConfiguration, classLoader);

                  }

                  // register a EJB client context listener which we will use to close endpoints/connections that we created,

                  // when the EJB client context closes

                  this.ejbClientContext.registerEJBClientContextListener(new ContextCloseListener());

          }

           

              }

          • 2. Re: Wildfly 8.2.1.Final - EJB000025 - Life cycle management
            David Lloyd Master

            The simple answer is, EJBClientContexts (at least in the version of jboss-ejb-client that you're using) must be closed when you're done with them.  Given that the number is 40, I expect you're hitting the channel limit, because the 1.x and 2.x versions of jboss-ejb-client don't combine channels on shared connections.  If you close the client context when you're done with it, you probably will be OK.