10 Replies Latest reply on Jul 3, 2013 2:19 AM by jaikiran

    Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0

    sunil_dixit

      Hi,

       

      My requirement is to pass some additional information to security interceptors and do the same I am using " org.jboss.ejb.client.EJBClientContext.getCurrent().registerInterceptor()" for registering "EJBClientInterceptor" implementation.

      It was working with EAP 6.0.1 version but now I have upgraded by jboss EAP 6.1.0 and it's never gets invoked before any EJBs (i.e. remote ejbs) gets invoked.

       

      Here is remote client code

       

       

       

      public static void callEJB() throws Exception {

       

              Hashtable<String, Object> jndiProperties = new Hashtable<String, Object>();

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

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

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

              jndiProperties.put(Context.PROVIDER_URL, "remote://localhost:4447");

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

              jndiProperties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS",true);

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

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

              InitialContext context = new InitialContext(jndiProperties);

              registerClientCallBack(context);

              String ejbJNDI = "HelloWorldEAR/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldRemote";

              HelloWorldRemote remote = (HelloWorldRemote) context.lookup(ejbJNDI);

              remote.sayHello();

          }

       

       

      private static void registerClientCallBack(){

                   org.jboss.ejb.client.EJBClientContext.getCurrent().registerInterceptor(0, new ClientSecurityInterceptor()); // registering the EJBClientInterceptor

        }

       

      EJBClientInterceptor code


      public class ClientSecurityInterceptor implements EJBClientInterceptor {

         public void handleInvocation(EJBClientInvocationContext context) throws Exception {       

              System.out.println("INSIDE CLIENT INTERCEPTOR");

              context.sendRequest();

          }

       

          public Object handleInvocationResult(EJBClientInvocationContext context) throws Exception {

              return context.getResult();

          }

      }

       

       

      I have noticed one Strange problem in  EAP 6.1.0

       

      Earlier  (i.e. in EAP 6.0.1) "org.jboss.ejb.client.EJBClientContext.getCurrent()" was throwing "NullPointerException" and we need to use following classes to make this work

       

      EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(ejb3Props());

      ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);

      EJBClientContext.setSelector(selector);

      org.jboss.ejb.client.EJBClientContext.getCurrent().registerInterceptor(0, new ClientSecurityInterceptor()); // registering the EJBClientInterceptor

       

      Now in EAP 6.1.0 this behave in other manner and we don't need "EJBClientContext,EJBClientConfiguration,ContextSelector".

       

       

       

      Thanks,

      Sunil Dixit

        • 1. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
          wdfink

          I suppose that the problem is the use of the "remote://" protocoll. There are some restrictions here.

          I recommend to use the jboss-ejb-client.proprties or the EJBClientConfiguration (direct API use) as you did in the second example.

          This works for me with EAP6.0.1 and 6.1 for me.

          • 2. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
            wdfink

            I've done a short test and it did not work if you use the EAP6.1 jboss-client.jar if you use the remote-naming.

            This is because you are creating a different EJBClientContext and EJBCC.registerInterceptor(...) will add the inteceptor to the default context and not to yours.

            • 3. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
              sunil_dixit

              Thanks Wolf !

               

              All of my EJBs are deployed as EAR and if I use "EJBClientConfiguration"  to perform lookup then I get "java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling".


              naming approach is deprecated in JBoss 7 and shouldn't be used. See here for details https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project

               

               


              • 4. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                wdfink

                In that case there is somthing wrong with your initialisation or lookup.

                Do yo use the ejb: prefix for the lookup?

                 

                You can find examples in the JDF quickstarts see i.e. ejb-remote.

                 

                If you still have problems you might post the relevant part of code and an excerpt from the logfile to see how the JNDI look like.

                • 5. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                  sunil_dixit

                  Hi,

                   

                  I have already gone through those examples but that does not work. If I use  "ejb:" prefix then my interceptor is being called but I get

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

                   

                  Now here is JNDI view of my HelloWorldEJB

                   

                  java:global/HelloWorldEAR/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldRemote

                  java:app/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldRemote

                  java:module/HelloWorld!com.test.cl.HelloWorldRemote

                  java:jboss/exported/HelloWorldEAR/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldRemote

                  java:global/HelloWorldEAR/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldLocal

                  java:app/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldLocal

                  java:module/HelloWorld!com.test.cl.HelloWorldLocal

                   

                   

                  Java Client Code

                   

                          Hashtable<String, Object> jndiProperties = new Hashtable<String, Object>();

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

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

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

                          jndiProperties.put(Context.PROVIDER_URL, "remote://localhost:4447");             

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

                          jndiProperties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS",true);

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

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

                          InitialContext context = new InitialContext(jndiProperties);

                          registerClientCallBack(context);

                          String ejbJNDI = "ejb://HelloWorldEAR/HelloWorldEJB/HelloWorld!com.test.cl.HelloWorldRemote";

                          HelloWorldRemote remote = (HelloWorldRemote) context.lookup(ejbJNDI);

                          remote.sayHello();

                  • 6. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                    sunil_dixit

                    I think there are few changes made in "jboss-cleint.jar" w.r.t. "Context Scope" and other fixes.

                     

                    EAP 6.1.0 uses "7.2.0.Final-redhat-8" spec for "jboss-cleint.jar" and there are few new methods in "EJBClientContext" like "getSelector()" which was not there in EAP 6.0.X version.

                     

                    Now "ConfigBasedEJBClientContextSelector" has new field called "identifiableContexts" which is used to get current "EJBClientContext" by execution program (i.e. by initail context or other program).

                    New code (i.e. updated jar files ) maintaines two different instances of "EJBClientContext" ( i.e. one in ContextSelector.ejbClientConext and another in ContextSelector.ejbClientConext.identifiableContexts) and if you use

                    EJBClientContext.getSelector().getCurrent().registerInterceptor(0, new ClientSecurityInterceptor());

                     

                    to add new ClientSideInterceptor then it is added in

                     

                     

                    "ContextSelector.ejbClientConext" NOT in "ContextSelector.ejbClientConext.identifiableContexts".

                    Now system gets/retrives EJBContext from "ContextSelector.ejbClientConext.identifiableContexts" using org.jboss.ejb.client.EJBClientContext.require() API by passing "EJBClientContextIdentifier" object.

                     

                    You can add new client side interceptor by following lines of code

                     

                      IdentityEJBClientContextSelector ref = ((IdentityEJBClientContextSelector)org.jboss.ejb.client.EJBClientContext.getSelector());

                      EJBClientContextIdentifier clientContextIdentifier = new NamedEJBClientContextIdentifier("RemoteNamingEJBClientContext$1");//DEFAULT

                      ref.getContext(clientContextIdentifier).registerInterceptor(0, new ClientSecurityInterceptor());

                     

                     

                    I have also written one method which can get "EJBClientContextIdentifier" value from InitailContext

                     

                     

                    private static  EJBClientContextIdentifier findEJBClientContextIdentifier(InitialContext context)

                            {

                                EJBClientContextIdentifier clientContextIdentifier = new NamedEJBClientContextIdentifier("RemoteNamingEJBClientContext$1");//DEFAULT

                                if(null != context)

                                {

                                    try {

                                        Field defaultInitCtxField = context.getClass().getDeclaredField("defaultInitCtx");

                                        if(null != defaultInitCtxField && defaultInitCtxField.getType().isAssignableFrom(Context.class))

                                        {

                                            defaultInitCtxField.setAccessible(true);

                                            Object defaultInitCtxValue = defaultInitCtxField.get(context);

                                            if(null != defaultInitCtxValue)

                                            {

                                                Field namingStoreField = defaultInitCtxValue.getClass().getDeclaredField("namingStore");

                                                if(null != namingStoreField && namingStoreField.getType().isAssignableFrom(org.jboss.naming.remote.client.HaRemoteNamingStore.class))

                                                {

                                                    namingStoreField.setAccessible(true);

                                                    Object namingStoreFieldValue = namingStoreField.get(defaultInitCtxValue);

                                                    if(null != namingStoreFieldValue)

                                                    {

                                                        Field ejbClientHandlerField = namingStoreFieldValue.getClass().getDeclaredField("ejbClientHandler");

                                                        if(ejbClientHandlerField != null && ejbClientHandlerField.getType().isAssignableFrom(org.jboss.naming.remote.client.ejb.RemoteNamingStoreEJBClientHandler.class))

                                                        {

                                                            ejbClientHandlerField.setAccessible(true);

                                                            Object ejbClientHandlerFieldValue = ejbClientHandlerField.get(namingStoreFieldValue);

                                                            org.jboss.naming.remote.client.ejb.RemoteNamingStoreEJBClientHandler gg = null;

                                                            if(null != ejbClientHandlerFieldValue)

                                                            {

                                                                Field ejbClientContextIdentifierField = ejbClientHandlerFieldValue.getClass().getDeclaredField("ejbClientContextIdentifier");

                                                                if(null != ejbClientContextIdentifierField && ejbClientContextIdentifierField.getType().isAssignableFrom(NamedEJBClientContextIdentifier.class))

                                                                {

                                                                    ejbClientContextIdentifierField.setAccessible(true);

                                                                    EJBClientContextIdentifier ejbClientContextIdentifierFieldValue = (EJBClientContextIdentifier) ejbClientContextIdentifierField.get(ejbClientHandlerFieldValue);

                                                                    clientContextIdentifier = ejbClientContextIdentifierFieldValue;

                                                                }

                                                            }

                                                        }

                                                    }

                                                }

                                            }

                                        }

                                    } catch (SecurityException e) {

                                    } catch (NoSuchFieldException e) {

                                    } catch (IllegalArgumentException e) {

                                    } catch (IllegalAccessException e) {

                                    }

                                }

                                return clientContextIdentifier;

                            }

                     

                     

                    It works for me.

                    • 7. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                      wdfink

                      You should read the documentation.

                      If you use the remote-naming project PROVIDER_URL=remote://host:port the lookup is wihtout ejb: prefix!

                      In this case the design is different and you can not use the ejb-client features. It may work but I've seen many problems with GC or concurrency etc.

                      It is not designed to work if you manipulate both.

                       

                      If you use jboss-ejb-client.properties or even register the ClientContext with the API:

                         EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(ejb3Props());

                         ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);

                         EJBClientContext.setSelector(selector);

                      then you must lookup with ejb: prefix.

                      In this case you are able to use the client-interceptor and cluster features.

                       

                      The approach you describe in the comment above might work in that special environment but I recommend to not use it as the behavior might not correct under any circumstances and the implementation might change without notice in the next version.

                      • 8. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                        sunil_dixit

                        Thanks a lot for valuable input !

                         

                        much apperciated.

                        • 9. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                          wdfink

                          Does that answered your questions?

                          If yes you should mark the thread as answered

                          • 10. Re: Registered Interceptor using EJBClientContext.registerInterceptor(..) is not called on EAP 6.1.0
                            jaikiran

                            I'll just repeat what Wolf said. The best approach to follow is use the ejb: namespace approach instead of the remote naming approach. I would suggest you do the following:

                             

                            1) For now, keep aside the usage of EJB client interceptors

                            2) Follow the documentation and get the EJB invocation working without the interceptors, using the ejb: (a.k.a EJB remote client API) approach

                            3) If #2 doesn't work post back with the relevant details.

                            4) Once #2 works, you can then register the interceptors either by placing them in the client classpath to use the Java Service Loader mechanism or by explicitly adding them.