1 2 3 Previous Next 79 Replies Latest reply on Jan 10, 2013 6:57 PM by mevans7

    How to call a remote EJB without a property file?

    bernd.koecke

      Hello,

       

      when a client wants to call remote EJBs on more than one JBoss instance (7.1.CR1) it needs a jboss-ejb-client.properties file with

      the routing information, on which JBoss the bean is deployed. This file must be changed and the client restarted, when any of these

      endpoints changed. Is there a possibility to setup the information from the properties file by code?

       

      I see some posts here which look similar and that it should be possible, but 7.1.CR1 uses still the properties file.

      I think it could be possible to use a client interceptor to replace the class which parses the properties file. But this is a little bit

      complicated and I wonder if there is an easier way to do this .

       

      If you aks me for what I need this, here are some things, why it would be nice to have:

       

      With older JBoss versions we are listening to the deployments and fill the endpoint data into a small registry. We have utility classes

      which use a name and a version prefix as coordinates on the client side to ask the registry where a bean is deployed,

      initialize the naming context and do the lookup. If some care is taken, beans/apps may move between nodes or cluster without any changes or

      restarts on the client. And the client doesn't need to know anything about JNDI properties, auto discovery and so on.

       

      And we can use exactly the same client JARs for test and production environment, because the endpoint information comes from the test or

      production registry and not from the classpath.

       

      Thanks a lot

      Bernd

        • 1. Re: How to call a remote EJB without a property file?
          jaikiran

          The EJB client code does need to know about the connection information, so some kind of configuration is required. We have had some feedback around this and we have changed the code to allow the configurations to come from any source. By default we use the properties file, but you can implement your own logic to provide those configurations. These changes aren't yet merged upstream (since we are implementing some clustering support around this), but will be available upstream soon.

          • 2. Re: How to call a remote EJB without a property file?
            prasad.deshpande

            Bernd Koecke wrote:

             

            when a client wants to call remote EJBs on more than one JBoss instance (7.1.CR1) it needs a jboss-ejb-client.properties file with

            the routing information, on which JBoss the bean is deployed. This file must be changed and the client restarted, when any of these

            endpoints changed. Is there a possibility to setup the information from the properties file by code?

            This is exactly a reason for which https://issues.jboss.org/browse/EJBCLIENT-12 is raise & is under development.

             

             

            I see some posts here which look similar and that it should be possible, but 7.1.CR1 uses still the properties file.

             

            This issue is addressed by EJBClient API which is not yet published, if you wait for few more days, development on this one should be finished & hopefully should be in nightly builds for testing before AS7.1 final release.

             

            Current proposal is to pass properties that you'd normally specify in jboss-ejb-client.properties & then initiate the remote receivers. Once it's in nightly build (which I'm waiting for myself ) I might be able to provide you exact way to pass properties programatically so that you won't need jboss-ejb-client.properties file.

            • 3. Re: How to call a remote EJB without a property file?
              bernd.koecke

              These are very good news, thanks a lot! I haven't seen this issue. The line "EJBClient.setSelector(..." is exactly what I thought of and it its nice see that my idea was not wrong. This saves me a lot of time when there is something ready to use. If you need someone to test and play around with it, I would be happy to help .

              • 4. Re: How to call a remote EJB without a property file?
                bernd.koecke

                These are very good news, thanks a lot! I haven't seen this issue. The line "EJBClient.setSelector(..." is exactly what I thought of and it its nice see that my idea was not wrong. This saves me a lot of time when there is something ready to use. If you need someone to test and play around with it, I would be happy to help .

                • 5. Re: How to call a remote EJB without a property file?
                  jaikiran

                  I'll write up a more detailed documentation soon. But as a quick overview, the current AS7 upstream has been upgraded to 1.0.0.Beta12 of ejb-client library which is much more flexible for configuring the client context. By default we use the jboss-ejb-client.properties for the configurations, but with this latest version we can now accept the configurations from any source (not just properties file). The configuration comes from a https://github.com/jbossas/jboss-ejb-client/blob/master/src/main/java/org/jboss/ejb/client/EJBClientConfiguration.java.

                   

                  If a user application wants to use a different approach for configuring the EJB client context, then the typical approach would look like:

                   

                  // Create a EJB client configuration
                  final EJBClientConfiguration ejbClientConfiguration = .... // somehow create the EJBClientConfiguration depending on the user application's necessity.
                  
                  // EJB client context selection is based on selectors. So let's create a ConfigBasedEJBClientContextSelector which uses our EJBClientConfiguration created in previous step
                  final ContextSelector<EJBClientContext> ejbClientContextSelector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);
                  
                  // Now let's setup the EJBClientContext to use this selector
                  final ContextSelector<EJBClientContext> previousSelector = EJBClientContext.setSelector(ejbClientContextSelector);
                  
                  // Now that we have setup the EJB client context (backed by our client configuration and receiver information), let's now do the JNDI lookup and
                  invoke on the proxies
                  final Hashtable props = new Hashtable();
                  // setup the ejb: namespace URL factory
                  props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
                  // create the InitialContext
                  final Context context = new javax.naming.InitialContext(props);
                  
                  
                  final MyBeanInterface bean = ctx.lookup("ejb:appName/moduleName/distinctName/beanName!viewClassName");
                  // invoke on bean
                  bean.doSomething();
                  

                   

                  If the user application wants to create the EJBClientConfiguration from a properties file (where the keys in the properties file are well-known) but wants to have more control on where the properties file comes from or how the Properties are created, then you can reuse the PropertiesBasedEJBClientConfiguration which accepts a Properties object in its constructor. You can then pass that PropertiesBasedEJBClientConfiguration to the ConfigBasedEJBClientContextSelector:

                   

                  // fetch the Properties somehow (depending on user application's requirement)
                  final Properties clientConfigProps = ... 
                  // Create a EJB client configuration from the properties
                  final EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(myproperties);
                  
                  // EJB client context selection is based on selectors. So let's create a ConfigBasedEJBClientContextSelector which uses our EJBClientConfiguration created in previous step
                  final ContextSelector<EJBClientContext> ejbClientContextSelector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);
                  
                  // rest of the steps remain the same as explained previously
                  

                   

                  Edited by jaikiran: Minor change/fix to the example code

                  1 of 1 people found this helpful
                  • 6. Re: How to call a remote EJB without a property file?
                    stepanov

                    It's probably too late to ask this but it is still worth mentioning. Why have you guys decided to move from a completely JBoss-agnostic way of constructing the InitialContext (with a good choice of programmatic construction of its Properties argument with all JBoss-specific information encapsulated) to basically the same thing but with an additional JBoss API dependant step?

                    • 7. Re: How to call a remote EJB without a property file?
                      bernd.koecke

                      Its cool to have an API for setting my own configuration implementation. And the JBoss specific code is not a problem in my environment. I think the above approach gives me more flexibility to implement the combination of our registry with the JNDI context. Thanks a lot for the quick solution!

                      • 8. Re: How to call a remote EJB without a property file?
                        jaikiran

                        Oleg Stepanov wrote:

                         

                        Why have you guys decided to move from a completely JBoss-agnostic way of constructing the InitialContext (with a good choice of programmatic construction of its Properties argument with all JBoss-specific information encapsulated)

                        The InitialContext creation hasn't changed. It's the same and nothing JBoss specific. We register a URL factory for ejb: namespace as allowed by the JNDI APIs. The only thing that's changed is the way we communicate from the client to the server during these EJB invocations. A previous discussion is here https://community.jboss.org/message/637563#637563

                        • 9. Re: How to call a remote EJB without a property file?
                          rodakr

                          Sorry but it has changed...  I can't dynamically initiate InitialContext  just passing Hashtable with all properties to context idependent of any implementations...

                           

                          I need now jboss propriätary EJBClientConfiguration , EJBClientContext .... in my sources.

                          Even with commercial App Server like Oracle weblogic I can do this withous implementation dependency in my source code..

                           

                           

                          I wonder why you just don't want to use passed Hashtable to new InitialContext(props) to pass all your jboss remote properties to your jboss remote client for configuration...

                           

                           

                          Why not something like this:

                           

                           

                          //invoke on the proxies

                          final Hashtable props = new Hashtable();

                           

                          // fill Hashtable with Jboss client properties

                           

                          Properties prop = new Properties();

                           

                          prop.load(new FileInputStream(new File("jboss-client.properties")));

                           

                          // setup the ejb: namespace URL factory

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

                          // create the InitialContext

                          final Context context = new javax.naming.InitialContext(props);

                           

                           

                          And everything else yo do in jboss-remote implementation reading from passed Hashtable in InitialContext ( Properties extends Hashtable.. )...

                          • 10. Re: How to call a remote EJB without a property file?
                            jaikiran

                            Radek Rodak wrote:

                             

                             

                            I need now jboss propriätary EJBClientConfiguration , EJBClientContext .... in my sources.

                             

                            No. Have you checked the https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI article. That shows that you can use JNDI access with zero usage of JBoss specific APIs. You just have to have a jboss-ejb-client.properties file in the classpath. This thread is discussing advanced uses where users want to use JBoss specific APIs to have more control over the configuration.

                            • 11. Re: How to call a remote EJB without a property file?
                              rodakr

                              No.  My last post starts with "..  I can't dynamically initiate InitialContext"

                              You document says jboss-ejb-client.properties file in the classpath , this is static nothing dynamic....

                              I can't change value like connection URL  which is configured in static jboss-ejb-client.properties file ..  , dynamically without using Jboss specific API....  ( except when I start to deal with CLassloader.. )

                              Only purpose of this JBoss Specific API... is to change Properties for current EJBClientContext ....

                              This will be not needed, if you could use Hashtable from new InitialContext to initila your Jboss specific API.

                              • 12. Re: How to call a remote EJB without a property file?
                                stepanov

                                Radek is precisely right, that's what I meant saying that now I got to have JBoss-specific lines in my client's code just to be able to change server's IP dynamically (which is a primary use case for the majority of the remote clients). Do you guys think it can/should be fixed?

                                • 13. Re: How to call a remote EJB without a property file?
                                  bernd.koecke

                                  I looked at the above solution and have an additional issue. Can I define the combination of bean and endpoint from the configuration for each created context?

                                   

                                  With the old implementation it was possible to make sure that a lookup and a later call to a bean was made against one node or cluster.

                                   

                                  I can't find an "easy" way to do that with the current implementation. I can define a number of endpoints in a dynamic way with the above API. But during the initialisation each node is asked which beans are deployed and this is stored in a map on the client side. The key is build from the JNDI lookup name, but not a cluster or node name. When a bean method is called the code uses the beans lookup name to see on which cluster it is reachable and routes the call to it. But I can't find a way to set an option on the client side for a context that only one endpoint, cluster or node, should be used as destination.

                                   

                                  I could do it with thread local variables, but I think this is dangerous when the client is a JBossAS and the current thread comes from a pool. Its difficult to make sure that this variable is deleted when all calls are done and that there can't be a value from the previous thread user. This can happen when a developer doesn't use the right startup code before he uses the bean proxy.

                                   

                                  I have two situations in mind when this feature would be nice. The first one is when the client is a JBossAS 7.1 with two apps, X and Y and two additional cluster A and B. X expects a bean on cluster A and Y on cluster B. Both configure their endpoints. But in reality both dependant beans are deployed on cluster B. This is a deployment bug, but no one recognizes it. The above selector is stored in a static field and is used for all calls of the client and all works well. Next Y is undeployed and the endpoint to B is removed. Now X fails, too. With a defined routing it would have been failed at the deployment of X.

                                   

                                  Another situation is a test environment with a number of JBossAS instances where beans with the same JNDI name are deployed in a different development state on different cluster and there is another JBoss which has to call both from two indipendent deployed apps.

                                   

                                  My two examples will not happen very often. The JNDI names will be destinct enough most of the time. Especially when I change my deployment procedure and use the optional "distinct name". May be the general feature to set an option on the context which is visible in the interceptor chain is useful for others. But may be the feature is still there and I can't see it. Then it would be nice, if you can give me a hint where to look at.

                                   

                                  Thanks a lot and have a nice weekend

                                  Bernd

                                  • 14. Re: How to call a remote EJB without a property file?
                                    rzd

                                    I think the EJB spec as well as JBoss AS are heading in a different direction than what you try to do. Just as with DI, where you don't have/want to specify the implementation any more, the new JBoss EJB stack allows you to inject (more or less) the remote business interface, and the container does the wiring to the correct implementation.

                                     

                                    There are use cases, though, that need more fine grained control. In CDI you'd use qualifiers, which currently have no equivalent for remote EJBs.

                                     

                                    Ask yourself: Why do I need the control over the host to be contacted if I can get that automatically? There must be a difference, if the same EJB ist deployed multiple times (if not for clustering). Can I directly express this difference, instead of agreeing that one host has these, while the other host has those properties? Documenting these requirements in the code instead of on a wiki page is a Good Thing!

                                     

                                    These use cases exist, and taking away the option to (mis-)use the host name for that, means we need other ways to specify such qualifiers. I understand that right now you can't pass those qualifiers from the lookup/injection point to the selector, as it's (oversimplified) passed through the ejb context, which is a singleton.

                                     

                                    For more details please see here.

                                    1 2 3 Previous Next