3 Replies Latest reply on Jun 26, 2019 7:59 AM by valsaraj007

    Programmatic remote ejb call issue with WildFly Naming Client?

    valsaraj007

      Is wildfly-config.xml is mandatory for WildFly Naming Client?

      I have removed it and used the Programmatic Approach because of this:

      wildfly-config.xml contains user creds which will be available as principal in EJB. We have multiple users using same client. Also using a custom security realm. So user creds will change each time.

       

      But the lookup fails with Programmatic Approach but works with wildfly-config.xml approach.

      Here is wildfly-config.xml:

      <configuration> 

          <authentication-client xmlns="urn:elytron:1.0"> 

              <authentication-rules> 

                  <rule use-configuration="default"/> 

              </authentication-rules> 

              <authentication-configurations> 

                  <configuration name="default">

      <sasl-mechanism-selector selector="PLAIN"/>

                       <providers>

                           <use-service-loader />

                       </providers>

      <set-user-name name="ejbuser1"/> 

                      <credentials> 

                          <clear-password password="*****"/> 

                      </credentials>

      <set-mechanism-realm name="SSLRealm" />

                  </configuration> 

              </authentication-configurations> 

          </authentication-client> 

          <jboss-ejb-client xmlns="urn:jboss:wildfly-client-ejb:3.0"> 

              <connections> 

                  <connection uri="remote+http://localhost:8080" /> 

              </connections> 

          </jboss-ejb-client> 

      </configuration>

       

      After working this, I removed this file and added code for Programmatic Approach:

                  // create your authentication configuration

                  AuthenticationConfiguration namingConfig = AuthenticationConfiguration.empty()

                  .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("PLAIN"))

                  .useRealm("SSLRealm")

                  .useName(username)

                  .usePassword(password);

                 

                  // create your authentication context

                  AuthenticationContext context = AuthenticationContext.empty()

                  .with(MatchRule.ALL.matchHost("localhost"), namingConfig);

                  

                  // create a callable that creates and uses an InitialContext

                  Callable<Void> callable = () -> {

                      Properties properties1 = new Properties();

                      properties1.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");

                      properties1.put(Context.PROVIDER_URL, ejbProperties.get("java.naming.provider.url"));

                      ctx = new InitialContext(properties1);

                     

                      return null;

                  };

                  

                  // use your authentication context to run your callable

                  try {

                     context.runCallable(callable);

                     // ERROR HERE

                     appBean = (AppRemote) ctx.lookup(getJNDIPrefix() + "AppBean!" + AppRemote.class.getName());

                } catch (NamingException e) {

                     throw e;

                } catch (Exception e) {

                     e.printStackTrace();

                }

       

      Then got following error:

      Caused by: javax.security.sasl.SaslException: Authentication failed: none of the mechanisms presented by the server (PLAIN) are supported

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

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

      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:591)

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

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

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

      at org.jboss.remoting3.ConnectionInfo$None.getConnection(ConnectionInfo.java:82)

      at org.jboss.remoting3.ConnectionInfo.getConnection(ConnectionInfo.java:55)

      at org.jboss.remoting3.EndpointImpl.doGetConnection(EndpointImpl.java:488)

      at org.jboss.remoting3.EndpointImpl.getConnectedIdentity(EndpointImpl.java:434)

      at org.jboss.remoting3.UncloseableEndpoint.getConnectedIdentity(UncloseableEndpoint.java:52)

      at org.jboss.remoting3.Endpoint.getConnectedIdentity(Endpoint.java:123)

      at org.jboss.ejb.protocol.remote.RemoteEJBReceiver.lambda$getConnection$2(RemoteEJBReceiver.java:185)

      at java.security.AccessController.doPrivileged(Native Method)

      Any guess what may be wrong?

        • 1. Re: Programmatic remote ejb call issue with WildFly Naming Client?
          fjuma

          Caused by: javax.security.sasl.SaslException: Authentication failed: none of the mechanisms presented by the server (PLAIN) are supported

          Looks like the PLAIN mechanism is not considered to be supported on the client side. Try adding this when creating your AuthenticationConfiguration:

           

          .useProviders(() -> new Provider[] { new WildFlyElytronProvider() })
          • 2. Re: Programmatic remote ejb call issue with WildFly Naming Client?
            valsaraj007

            Hi Farah fjuma,

            Thanks much!

             

             

            The issue that I reported in ticket was getting when I set InitialContext in Callable and use that outside callable to lookup bean. When I moved bean lookup, it worked fine. But in our code, it is spread around a lot of files and need some solution to return IntialContext or bean. I tried the authentication context setting code on top class and put the code there in Callable. Then it worked for for endpoints that didn't take much. But for those doing more lookups and complex operations, getting error.

            The specified item was not found.  The exception is here.

            Caused by: javax.ejb.EJBException: WFTXN0021: Failed to acquire a connection for this operation

            at org.jboss.ejb.protocol.remote.EJBClientChannel.processInvocation(EJBClientChannel.java:471)

            at org.jboss.ejb.protocol.remote.RemoteEJBReceiver$1.lambda$handleDone$0(RemoteEJBReceiver.java:91)

            at org.xnio.FinishedIoFuture.addNotifier(FinishedIoFuture.java:79)

            at org.jboss.ejb.protocol.remote.RemoteEJBReceiver$1.handleDone(RemoteEJBReceiver.java:76)

            at org.jboss.ejb.protocol.remote.RemoteEJBReceiver$1.handleDone(RemoteEJBReceiver.java:74)

            at org.xnio.IoFuture$HandlingNotifier.notify(IoFuture.java:208)

            at org.xnio.AbstractIoFuture$NotifierRunnable.run(AbstractIoFuture.java:720)

            ...

            Caused by: javax.transaction.SystemException: WFTXN0021: Failed to acquire a connection for this operation

            at org.wildfly.transaction.client.provider.remoting.RemotingRemoteTransactionPeer.begin(RemotingRemoteTransactionPeer.java:212)

            at org.wildfly.transaction.client.RemoteTransaction.setLocation(RemoteTransaction.java:222)

            at org.jboss.ejb.protocol.remote.EJBClientChannel.writeTransaction(EJBClientChannel.java:557)

            at org.jboss.ejb.protocol.remote.EJBClientChannel.processInvocation(EJBClientChannel.java:367)

            ... 12 more

            Caused by: org.wildfly.security.auth.AuthenticationException: JBREM000308: Authentication failed (no mechanisms left), tried: (none)

            at org.jboss.remoting3.ConnectionPeerIdentityContext.doAuthenticate(ConnectionPeerIdentityContext.java:368)

            at org.jboss.remoting3.ConnectionPeerIdentityContext.authenticate(ConnectionPeerIdentityContext.java:174)

            But it works fine using the wildfly-config.xml. When I rename this file and use programamtic approach, this error comes when client does many remote actions & gets error always at the same point. But the operation is same. For eg: read a set of files and update in DB via EJB call one by one. Here at a particular files, the error comes. Is there any limitation when we use programmatic approach, when InitialContext is closed and created? That is the only action happens. But the same works with configuration file.

             

            Here is the modified code:

            // create your authentication configuration

                                    AuthenticationConfiguration namingConfig = AuthenticationConfiguration.empty()

                                    .useProviders(() -> new Provider[] { new WildFlyElytronProvider() })                      

                                    .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("PLAIN"))

                                    .useRealm("SSLRealm")

                                    .useName(userName)

                                    .usePassword(pass);

                                    // create your authentication context

                                    AuthenticationContext context = AuthenticationContext.empty()

                                    .with(MatchRule.ALL.matchHost("localhost"), namingConfig);

                                    ContextManager<AuthenticationContext> contextManager = authenticationContext.getInstanceContextManager(); 

                                    contextManager.setGlobalDefault(authenticationContext);

             

                                    // create a callable that creates and uses an InitialContext

                                    Callable<String> callable = () -> {

                                    String paswd = null;

                                  

                                        try {

                                        final Properties ejbProperties = new Properties();

                                            ejbProperties.put("java.naming.factory.initial", "org.wildfly.naming.client.WildFlyInitialContextFactory");

                                            ejbProperties.put("java.naming.provider.url", System.getProperty("java.naming.provider.url"));

                                          

                                              // Lookup EJBs & perform operations

                                              new InitialContext(ejbProperties).lookup(...)

                                              ...

             

             

                       // use your authentication context to run your callable

                       try {

                            context.runCallable(callable);

                        } catch (Exception e) {

                             e.printStackTrace();

                        }

            Is there any reason for the above error, why it's working on configuration file based approach but not when through code?

            • 3. Re: Programmatic remote ejb call issue with WildFly Naming Client?
              valsaraj007

              Is this the known issue mentioned here?

              [JBEAP-9662] Invocations on UserTransaction obtained from InitialContext don't take user credentials into account - JBos…

               

              It's working fine like configuration file based approach if I set security principal & credentials in the InitialContext.

              Ref: mock-artifacts/ejbclient/eap7.1-provider-url-with-transactions-secured at master · jmartisk/mock-artifacts · GitHub

               

              I wonder why it need security principal & credentials in the InitialContext since the global authentication context already set as below:

                          // create your authentication configuration

                          AuthenticationConfiguration namingConfig = AuthenticationConfiguration.empty()          

                          .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism(sasl).forbidMechanism("JBOSS-LOCAL-USER"))

                          //.useProviders( () -> new Provider[] { new WildFlyElytronProvider() } )          

                          .useDefaultProviders()

                          .useName(username)

                          .usePassword(password)

                          .useRealm(realm);

                          // create your authentication context

                          AuthenticationContext authenticationContext = AuthenticationContext.empty()

                          .with(MatchRule.ALL.matchHost(host), namingConfig);

                          ContextManager<AuthenticationContext> contextManager = authenticationContext.getInstanceContextManager(); 

                          contextManager.setGlobalDefault(authenticationContext);