7 Replies Latest reply on May 19, 2017 4:34 AM by scattie

    Remote EJB calls from another WildFly Instance

    stevehayesxx

      Hi,

       

      I'm currently involved in porting our application from JBoss 4.3.0 to WildFly 10.1.0.Final.

      Part of that port involves accessing EJBs remotely from both a standalone client and from another WildFly instance.

      I have the standalone client working, but I cannot get remote EJB calls to work from WildFly. I've tried every

      combination I can find in forums / documentation etc, hence the post here now. For reasons that I won't go into here,

      I would like to use the programmatic client approach as opposed to setting up the connections in standalone-full.xml.

       

       

      For the working client I have the following:

       

           1. JBoss client jar from WildFly bin/client dir on the class path

           2. The following jboss-ejb-client.properties file on the class path:

       

      remote.connections=conn1
      remote.connection.conn1.host=hostname
      remote.connection.conn1.port=8080
      remote.connection.conn1.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
      remote.connection.conn1.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false
      remote.connection.conn1.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=${host.auth:JBOSS-LOCAL-USER}
      remote.connection.conn1.username=PARSservice
      remote.connection.conn1.password=ff705b9eef086335df8592078de921bc

       

           3. The following code to create the InitialContext and do the lookup (lookup names are in the form 'ejb:APP/Module/Bean!Interface'):

       

           public static <T> T getFromRemoteContext( final String hostName, final String name ) throws NamingException {

                  InitialContext ctx = getServerContext( hostName );

                  return (T) ctx.lookup( name );

           }

       

           private static InitialContext getServerContext( final String hostName ) throws NamingException {

                  return new InitialContext( getEnv(hostName) );

           }

       

           private static Properties getEnv( final String server ) {

       

                   Properties env = new Properties();

       

                   env.put( Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory" );

                   env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

                   env.put("jboss.naming.client.ejb.context", true);

                   env.put( "jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false" );

                   env.put( "jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false" );

       

                   String port = System.getProperty("interica.ejbremoting.port");

       

                   if ( port == null ) {

                       log.warn( "No port specified for remoting. Defaulting to 8080." );

                       port = "8080";

                   }

       

                   env.put(Context.PROVIDER_URL, "http-remoting://" + server + ":"+port);

       

                   try {

                       ServiceUser serviceUser = ServiceUserFactory.getServiceUser();

                       env.put( Context.SECURITY_PRINCIPAL, serviceUser.getUsername() );

                       env.put( Context.SECURITY_CREDENTIALS, serviceUser.getPasswordAsString() );

                   } catch ( IOException e ) {

                       log.error( e.getMessage(), e );

                   }

       

                   return env;

           }

       

           4. The following in standalone-full.xml:

       

           <security-realm name="IntericaRealm">

                <authentication>

                     <jaas name="Interica"/>

                </authentication>

           </security-realm>

       

           <http-connector name="http-remoting-connector" connector-ref="default" security-realm="IntericaRealm"/>

       

       

      For calls from another WildFly instance I have tried the above with both the JBoss client jar from WildFly bin/client dir on the class path of my APP ear and

      also with the following dependencies in the jboss-deployment-structure.xml in the APP ear acting as the client:

       

           <module name="org.jboss.remote-naming" export="true"/>

           <module name="org.jboss.xnio" export="true"/>

       

       

      With each of these I get the following error:

       

       

        2017-01-24 12:18:56,186 ERROR [ServerRegistrationThread] EJBCLIENT000025: No EJB receiver available for handling [appName:PARSAPP, moduleName:ejb-jar, distinctName:] combination for      invocation context org.jboss.ejb.client.EJBClientInvocationContext@1b12a1a4

             java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:PARSAPP, moduleName:ejb-jar, distinctName:] combination for invocation context      org.jboss.ejb.client.EJBClientInvocationContext@1b12a1a4

             at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798)

             at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128)

             at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)

             at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)

             at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)

             at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)

             at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)

             at com.sun.proxy.$Proxy89.registerNode(Unknown Source)

             at com.enigmadata.core.registration.node.service.ServerRegistrationThread.run(ServerRegistrationThread.java:68)

             at org.jboss.as.ee.concurrent.ControlPointUtils$ControlledRunnable.run(ControlPointUtils.java:105)

             at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

             at java.util.concurrent.FutureTask.run(FutureTask.java:266)

             at org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.run(ManagedFutureTask.java:141)

             at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.access$101(ManagedScheduledThreadPoolExecutor.java:383)

             at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.run(ManagedScheduledThreadPoolExecutor.java:532)

             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

             at java.lang.Thread.run(Thread.java:745)

             at org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:250)

       

       

      After seeing some other posts, I've now removed the jboss-ejb-client.properties file from the class path and am using the following code for

      creating the InitialContext and doing the lookups from WildFly:

       

       

             public static <T> T getFromRemoteContext( final String hostName, final String name ) throws NamingException {

                  InitialContext ctx = getServerContext( hostName );

                  return (T) ctx.lookup( name );

             }

       

             private static InitialContext getServerContext( final String hostName ) throws NamingException {

                  return new InitialContext( getEnv(hostName) );

             }

       

             private static Properties getEnv( final String server ) {

       

                  String port = System.getProperty("interica.ejbremoting.port");

       

                  if ( port == null ) {

                       log.warn( "No port specified for remoting. Defaulting to 8080." );

                       port = "8080";

                  }

       

                  String username = "unknown";

                  String password = "unknown";

       

                  try {

                       ServiceUser serviceUser = ServiceUserFactory.getServiceUser();

                       username = serviceUser.getUsername();

                       password = serviceUser.getPasswordAsString();

                  } catch ( IOException e ) {

                       log.error( e.getMessage(), e );

                  }

       

                  Properties env = getWildFlyClientConnectionProperties( username, password, server, port );

       

                  env.put( Context.PROVIDER_URL, "http-remoting://" + server + ":" + port );

                  env.put( Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory" );

                  env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

                  env.put("jboss.naming.client.ejb.context", false);

                  env.put("org.jboss.ejb.client.scoped.context", true);

                  env.put( "jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false" );

                  env.put( "jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false" );

       

                  env.put( Context.SECURITY_PRINCIPAL, username );

                  env.put( Context.SECURITY_CREDENTIALS, password );

       

                  return env;

             }

       

             private static Properties getWildFlyClientConnectionProperties(  final String username,

                                                                              final String password,

                                                                              final String host,

                                                                              final String port ) {

       

                  Properties p = new Properties();

       

                  p.put( "endpoint.name", "client-endpoint");

                  p.put( "remote.connections", "conn1");

                  p.put( "remote.connection.conn1.username", username );

                  p.put( "remote.connection.conn1.password", password );

                  p.put( "remote.connection.conn1.host", host );

                  p.put( "remote.connection.conn1.port", port );

                  p.put( "remote.connection.conn1.create.options.org.xnio.Options.SSL_ENABLED", false);

                  p.put( "remote.connection.conn1.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", false );

                  p.put( "remote.connection.conn1.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", false );

                  p.put( "remote.connection.conn1.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER" );

                  p.put( "remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", false );

       

                  return p;

             }

       

       

      The above code gives me the following error (not sure whether this is a step forwards or backwards):

       

       

        17:55:12,877 WARN  [org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector] (EE-ManagedScheduledExecutorService-default-Thread-1) Could not register a EJB receiver for connection to anl0343:8080: javax.security.sasl.SaslException: Authentication failed: all available authentication mechanisms failed:

             at org.jboss.remoting3.remote.ClientConnectionOpenListener.allMechanismsFailed(ClientConnectionOpenListener.java:114)

             at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.handleEvent(ClientConnectionOpenListener.java:449)

             at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.handleEvent(ClientConnectionOpenListener.java:241)

             at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)

             at org.xnio.channels.TranslatingSuspendableChannel.handleReadable(TranslatingSuspendableChannel.java:198)

             at org.xnio.channels.TranslatingSuspendableChannel$1.handleEvent(TranslatingSuspendableChannel.java:112)

             at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)

             at org.xnio.ChannelListeners$DelegatingChannelListener.handleEvent(ChannelListeners.java:1092)

             at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)

             at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)

             at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)

             at org.xnio.nio.WorkerThread.run(WorkerThread.java:567)

             at ...asynchronous invocation...(Unknown Source)

             at org.jboss.remoting3.EndpointImpl.doConnect(EndpointImpl.java:294)

             at org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:430)

             at org.jboss.ejb.client.remoting.EndpointPool$PooledEndpoint.connect(EndpointPool.java:192)

             at org.jboss.ejb.client.remoting.NetworkUtil.connect(NetworkUtil.java:153)

             at org.jboss.ejb.client.remoting.NetworkUtil.connect(NetworkUtil.java:133)

             at org.jboss.ejb.client.remoting.ConnectionPool.getConnection(ConnectionPool.java:78)

             at org.jboss.ejb.client.remoting.RemotingConnectionManager.getConnection(RemotingConnectionManager.java:51)

             at org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector.setupEJBReceivers(ConfigBasedEJBClientContextSelector.java:161)

             at org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector.getCurrent(ConfigBasedEJBClientContextSelector.java:118)

             at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createIdentifiableEjbClientContext(EjbNamingContext.java:269)

             at org.jboss.ejb.client.naming.ejb.EjbNamingContext.setupScopedEjbClientContextIfNeeded(EjbNamingContext.java:134)

             at org.jboss.ejb.client.naming.ejb.EjbNamingContext.<init>(EjbNamingContext.java:101)

             at org.jboss.ejb.client.naming.ejb.ejbURLContextFactory.getObjectInstance(ejbURLContextFactory.java:38)

             at org.jboss.as.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:133)

             at javax.naming.InitialContext.lookup(InitialContext.java:417)

             at javax.naming.InitialContext.lookup(InitialContext.java:417)

             at com.enigmadata.core.common.locator.ServiceLocator.getFromRemoteContext(ServiceLocator.java:39)

             at com.enigmadata.core.registration.node.service.ServerRegistrationThread.getRegistrationFacade(ServerRegistrationThread.java:101)

             at com.enigmadata.core.registration.node.service.ServerRegistrationThread.run(ServerRegistrationThread.java:54)

             at org.jboss.as.ee.concurrent.ControlPointUtils$ControlledRunnable.run(ControlPointUtils.java:105)

             at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

             at java.util.concurrent.FutureTask.run(FutureTask.java:266)

             at org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.run(ManagedFutureTask.java:141)

             at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.access$101(ManagedScheduledThreadPoolExecutor.java:383)

             at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.run(ManagedScheduledThreadPoolExecutor.java:532)

             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

             at java.lang.Thread.run(Thread.java:745)

             at org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:250)

       

       

      Any help would be gratefully received!

        • 1. Re: Remote EJB calls from another WildFly Instance
          mayerw01

          It looks like there are several issues with your code:

          1. If you were using the core EJB client API, then you would have configured all these properties via the jboss-ejb-client.properties or via programatic API usage as explained here EJB invocations from a remote client using JNDI.
          2. If you use the remote-naming project approach you should set "jboss.naming.client.ejb.context" to true to allow the the remote-naming project creation of a EJBClientContext containing a EJBReceiver (Remote EJB invocations via JNDI - EJB client API or remote-naming project - JBoss AS 7.1 - Project Documentation Editor )

          Regarding the message "EJBCLIENT000025: No EJB receiver available" you should verify that your lookup string is correct ("lookup: " + appName + "/" + moduleName + "/" + beanName + "!" + remoteView)

          • 2. Re: Remote EJB calls from another WildFly Instance
            stevehayesxx

            Hi Wolfgang,

             

            Thanks for the quick response.

             

            After looking at the remote naming project in more detail, I don't think it's what we require, so would like to go with the core EJB client API.

             

            The code in the first part of my post (above) uses the jboss ejb client jar and the properties file and has "jboss.naming.client.ejb.context" set to true. This works fine for a remote standalone client.

            My problem is trying to do the same thing but from an ear deployed within WildFly.

             

            If I use the same code as the remote standalone client then the following scenarios are true:

             

            If the ear that is acting as the client calls a remote ejb on the ear acting as the 'server' and both are running within the same WildFly instance then it all works fine.

            If the ear that is acting as the client is running in a different WildFly instance then I get the following stack trace when it tries to invoke a method on the remote ejb that has been looked up:

             

            2017-01-25 17:31:47,672 ERROR [ServerRegistrationThread] EJBCLIENT000025: No EJB receiver available for handling [appName:PARSAPP, moduleName:ejb-jar, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@5e581216

            java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:PARSAPP, moduleName:ejb-jar, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@5e581216

              at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798)

              at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128)

              at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)

              at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)

              at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)

              at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)

              at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)

              at com.sun.proxy.$Proxy91.registerNode(Unknown Source)

              at com.enigmadata.core.registration.node.service.ServerRegistrationThread.run(ServerRegistrationThread.java:68)

              at org.jboss.as.ee.concurrent.ControlPointUtils$ControlledRunnable.run(ControlPointUtils.java:105)

              at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

              at java.util.concurrent.FutureTask.run(FutureTask.java:266)

              at org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.run(ManagedFutureTask.java:141)

              at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.access$101(ManagedScheduledThreadPoolExecutor.java:383)

              at org.glassfish.enterprise.concurrent.internal.ManagedScheduledThreadPoolExecutor$ManagedScheduledFutureTask.run(ManagedScheduledThreadPoolExecutor.java:532)

              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

              at java.lang.Thread.run(Thread.java:745)

              at org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:250)

             

            Interestingly, if I take the properties file off of the class path for the remote standalone client then I get a similar stack trace to that above.

             

            EJBCLIENT000025: No EJB receiver available for handling [appName:PARSAPP, moduleName:ejb-jar, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@3e694b3f

            java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:PARSAPP, moduleName:ejb-jar, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@3e694b3f

                    at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798)

                    at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128)

                    at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)

                    at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)

                    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)

                    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)

                    at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)

                    at com.sun.proxy.$Proxy2.isCallerServerAdmin(Unknown Source)

                    at com.enigmadata.core.shell.util.XMLImport.initialise(XMLImport.java:86)

                    at com.enigmadata.core.shell.util.Shell.initialiseExtensionModule(Shell.java:617)

                    at com.enigmadata.core.shell.util.Shell.loadExtensionModule(Shell.java:579)

                    at com.enigmadata.core.shell.util.Shell.cmdloadModule(Shell.java:799)

                    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

                    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

                    at java.lang.reflect.Method.invoke(Method.java:497)

                    at com.enigmadata.core.shell.util.Shell.invokeCommand(Shell.java:522)

                    at com.enigmadata.core.shell.util.Shell.interpret(Shell.java:368)

                    at com.enigmadata.core.shell.util.Shell.main(Shell.java:105)

             

            Its almost as if the properties file isn't on the class path for the ear, however I've set the option on start up, and also set it programmaticaly just before creating the initial context and still get the same error.

            • 3. Re: Remote EJB calls from another WildFly Instance
              mayerw01

              Did you also check this thread Remote EJB Look up in Wildfly 8.2.Final?

              • 4. Re: Remote EJB calls from another WildFly Instance
                stevehayesxx

                Hi Wolfgang,

                 

                Thanks for the references. Looks like I've finally got it going.

                I wanted to avoid configuring the connections in standalone-full.xml as it would mean our support people having to do essentially the same configuration in 2 places
                (one for the standalone client and one for the client within WildFly).

                 

                Essentially what got it working for me from within WildFly is:

                 

                1) Ensuring the "jboss.ejb.client.properties.file.path" property is set to the path of the properties file with the connections in.

                2) Ensuring both "jboss.naming.client.ejb.context" and "org.jboss.ejb.client.scoped.context" are set to true.

                3) Adding the connection properties (like the one set up in the properties file) for the host I wish to connect to to the properties passed to the initial context.

                 

                I still have some experimenting and tidying up to do, but once I've done that I'll post what I've done here in case anyone is interested (at which point I'll mark this as answered).

                 

                Thanks for your help

                 

                Steve

                • 5. Re: Remote EJB calls from another WildFly Instance
                  wdfink

                  You should keep in mind that using "scoped context" add more resources (connections) for each context.

                  This is different to the configuration with remote-outbound because here the connections are shared.

                  It might blow up your resources if you create multiple context opjects with this approach.

                  • 6. Re: Remote EJB calls from another WildFly Instance
                    stevehayesxx

                    Thanks, yes I noticed the resources getting used up!!!

                    For now I create one InitialContext per server I wish to contact and provide synchronized access to them when looking up remote EJBs.

                    I'm not sure if this is a good approach but it seems to work, seems pretty robust and doesn't use up a load of resources.

                    • 7. Re: Remote EJB calls from another WildFly Instance
                      scattie

                      Hey Steve,

                       

                      I'm running into the same issue, trying to invoke a remote bean from on Wildfly instance on another, preferably with the least amount of fiddling in the config files.

                      Do you mind sharing your final solution to this issue? Not having to experiment with all the different properties and such would save me a tremendous amount of time.

                       

                      Many thanks in advance.