1 2 3 4 5 6 Previous Next 79 Replies Latest reply on Jan 10, 2013 6:57 PM by Mark Evans Go to original post
      • 30. Re: How to call a remote EJB without a property file?
        Jaikiran Pai Master

        Sergey Zhigunov wrote:

         

        Say you have the same app deployed on N hosts. The same version. Each host serves different customer with its own database, configurations and so on. The app has admin service EJB.

         

        Now there is an admin console which calls the admin EJB on all N hosts. It lets the admin to control the apps for all customers from one screen. Admin needs to know on which host he is operating on. List of hosts is dynamic and comes from admin console database.  Admin console needs to call the same app, same release, same EJB running on different hosts, and needs to know the host.

        If I understand you correctly, you want to do N invocations on the EJB and each of those invocations should go to N different servers? That's possible and you don't need N selectors for that. You can configure distinct names for each of those applications deployed on N servers and then use that distinct name during invocation to get the right receiver from the context. But if you don't want to go that path, you still can achieve this by using a single selector. All you have to do is register/unregister the right receiver from the EJBClientContext returned by your selector. Here's some pseudo code:

         

        EJBClientContext.selector(mySelector); // register your selector responsible for creating the EJBClientContext
        for (int i = 0; i < numOfHosts; i++) {
            final EJBReceiver ejbReceiver = this.getReceiverForHost(i); // get a receiver for the specific host
           // register it to the EJBClientContext
           final EJBClientContext ejbClientContext = EJBClientContext.requireCurrent();
           // register the receiver for this host
           ejbClientContext.registerEJBReceiver(ejbReceiver);
           // now lookup and invoke on the bean
           lookupAndInvokeOnBean();
          // unregister the receiver so that it won't be used for the next invocation
          ejbClientContext.unRegisterEJBReceiver(ejbReceiver);
        }
        
        • 31. Re: How to call a remote EJB without a property file?
          Sergey Zhigunov Newbie

          jaikiran pai wrote:



          EJBClientContext.selector(mySelector); // register your selector responsible for creating the EJBClientContext
          for (int i = 0; i < numOfHosts; i++) {
              final EJBReceiver ejbReceiver = this.getReceiverForHost(i); // get a receiver for the specific host
             // register it to the EJBClientContext
             final EJBClientContext ejbClientContext = EJBClientContext.requireCurrent();
             // register the receiver for this host
             ejbClientContext.registerEJBReceiver(ejbReceiver);
             // now lookup and invoke on the bean
             lookupAndInvokeOnBean();
            // unregister the receiver so that it won't be used for the next invocation
            ejbClientContext.unRegisterEJBReceiver(ejbReceiver);
          }

           

           

          Is this solution thread-safe?

          • 32. Re: How to call a remote EJB without a property file?
            Bernd Koecke Novice

            jaikiran pai schrieb:

             

            Note that all my answers in this reply will be in context of a remote client which does not run within a AS7 instance.

            I have both usecases, most of the time one JBoss calls another. I know that the configuration of endpoints comes from e.g. standalone.xml instead of a properties file, but I think I can get it working, too.

             

             

            jaikiran pai schrieb:

             

             

            Bernd Koecke wrote:

             

            Now I can use the distinct name part of the JNDI lookup path only on the client side. I don't have to set it at deploy time. I can use a special prefix to seperate it from distinct names which were used at deploy time. This part can define a cluster or node. My receivers use it to match against the corresponding endpoint. And I don't need it in the JNDI path on the server.

             

            I read your previous reply related to this which tried to explain your usecase, but I could not understand it completely. Are you saying that your EJBClientContext has (for example) 5 nodes which have the same application (identified by the combination of app/module/bean name) deployed and you want to specifically select one of the 5 nodes? And you don't want to use the distinct name to do that? Let's keep out clustering from this because that's a different case which needs more explanation.

             

            Yes, I know it is a rare case that beans with the same app/module/bean name are deployed on two JBossAS and have a different behaviour. But in a test environment this could happen. And yes, I would like to have control over the hosts which should be used. My mistake was, that I thought, that the distinct name must be set at deploy time. But now I think, I can use it only on the client side, when I write my own selector and receiver. So I think this issue is solved, when my receiver uses the distinct name for selecting a node or a group of nodes only on the client side.

            • 33. Re: How to call a remote EJB without a property file?
              Rüdiger zu Dohna Newbie

              jaikiran pai wrote:

               

              The selector is what has the power to decide what the EJBClientContext looks like. The EJBClientContext in-turn has a collection of receivers for different nodes which will be used for the invocations. It's ultimately upto the selector to decide/implement the logic for creating and maintaining the EJBClientContext and adding/removing receivers from that EJBClientContext. By default, we provide a selector which is based on picking up node configurations from a properties file. But you can plugin your own implementation to use a different selector.

              It seems that the ConfigBasedEJBClientContextSelector actually just does the initialization and then behaves like a normal ConstantContextSelector. Maybe it would make the design more obvious, if the EJBClientContext would instead use a plain ConstantContextSelector for that aspect, while the setup stuff should go somewhere else? If you want, I could give it a try and provide a pull request after refactoring the setup code.

              • 34. Re: How to call a remote EJB without a property file?
                Jaikiran Pai Master

                Rüdiger zu Dohna wrote:

                 

                It seems that the ConfigBasedEJBClientContextSelector actually just does the initialization and then behaves like a normal ConstantContextSelector. Maybe it would make the design more obvious, if the EJBClientContext would instead use a plain ConstantContextSelector for that aspect, while the setup stuff should go somewhere else?

                Actually I introduced that selector intentionally so that anyone (including user applications) can reuse that if they want to. They just have to provide the EjbClientConfiguration (however which way they create) and the rest of the context setup with the handled by this ConfigBasedEJBClientContextSelector (one time during construction) and will return that constructed context every time.

                • 35. Re: How to call a remote EJB without a property file?
                  Rüdiger zu Dohna Newbie

                  jaikiran pai wrote:

                   

                  Rüdiger zu Dohna wrote:

                   

                  It seems that the ConfigBasedEJBClientContextSelector actually just does the initialization and then behaves like a normal ConstantContextSelector. Maybe it would make the design more obvious, if the EJBClientContext would instead use a plain ConstantContextSelector for that aspect, while the setup stuff should go somewhere else?

                  Actually I introduced that selector intentionally so that anyone (including user applications) can reuse that if they want to. They just have to provide the EjbClientConfiguration (however which way they create) and the rest of the context setup with the handled by this ConfigBasedEJBClientContextSelector (one time during construction) and will return that constructed context every time.

                   

                  The ConfigBasedEJBClientContextSelector wouldn't have to implement ContextSelector for that, would it?

                  • 36. Re: How to call a remote EJB without a property file?
                    Rüdiger zu Dohna Newbie

                    I understand that Bernd and others want to specify the host or cluster name to connect to, for one specific remote proxy, either in the JNDI context or the JNDI lookup name. This used to work in older versions of JBoss, and AFAIK works in other Java EE containers. In enterprise or cloud environments, this use-case is essential in order to select the correct host based on non-functional requirements. I think that I understand the reasoning behind JBoss taking a different path, and I think we should follow! But the current version of JBoss is not there, yet; and Bernd can't upgrade to JBoss 7.x until this is fixed.

                     

                    To explain exactly what I mean, I have to get into code level details... sorry:

                     

                    Right now, the EjbNamingContext only uses the "stateful" option from the JNDI lookup name to decide if it has to create a Stateful or StatelessEJBLocator. I think it would be straight forward for it to use another option to create an Affinity for the EJBLocators it creates, which currently is, for all four subclasses, Affinity.NONE and can't be changed. I assume that this would already fulfill the direct requiremtent of Bernd.

                     

                    The EjbNamingContext could also use the environment (the properties that are passed into the InitialContext) for the same purpose, which is more like what you do in AS < 7 and AFAIK in other EJB containers. But as JBoss 7.1 uses an URL package prefix instead of an InitialContextFactory, the root context for all names starting with "ejb:" is global and not specific to the InitialContext that's used for the lookup, i.e. the properties for the InitialContext can't be passed down into the lookup. Anyway, the lookup options would suffice for things like the Affinity mentioned above.

                     

                    But I think we should go one step beyond a fixed set of options, and this is what I understand JBoss is heading at: The EJBClientContext currently selects the correct EJBReceiver based on appName/moduleName/distinctName, simply returning the first match[*]. The ConfigBasedEJBClientContextSelector is only used to configure the EJBReceivers in the EJBClientContext, but the EJBReceiver selection mechanism itself is constant in the EJBClientContext, as that class is final.

                     

                    This is the "old" way, where the client specifies the implementation, i.e. *where* things are deployed (including the names of the host/cluster, app, and module). This requires hard-wiring and documenting the agreements between client and server. It would be more flexible, if the client only had to specify the requirements it has, i.e. *what* it needs.

                     

                    I see two things that would have to be changed:

                    1. Instead of three separate strings (app, module, and distinct name), the complete EjbJndiIdentifier (this is where the whole lookup name is parsed into) would have to be passed into EJBClientContext.requireEJBReceiver etc., so the selection algorithm could be based on any part of the lookup string, including the options!

                    2. The EJBClientContext would have an extensible SPI mechanism, so it would be easy to add other selection criteria.

                     

                    Then we would be able to use arbitrary options to qualify things like tenant, QoS, test/production, etc. , while the "new" way would ease operating and be über-cloudy

                     

                     

                    Sorry for the long post! I didn't find a way to make it shorter and still understandable. Does this sound feasible to you? I'd appreciate any comments!

                     

                     

                    Rüdiger

                     

                    [*] Actually the EJBReceiver does the match. But the method acceptsModule is final, so you can't do much about it.

                    • 37. Re: How to call a remote EJB without a property file?
                      Bernd Koecke Novice

                      When I took a first look at Rüdigers post, I thought I should disagree. Because I thought I have a solution. But I missed that EJBReceiver.acceptModule is final. So I think the only way to build a solution is to write my own receiver and try to register each module twcie. With and without my special distinct name. Because then I can use the code of the final method without changes. But then I think I try to hack your API. Rüdigers suggestion sounds like a cleaner design, but I know changing parts of the internal structure of a system which is going to be released is not very popular .

                       

                      Regards,

                      Bernd

                      • 38. Re: How to call a remote EJB without a property file?
                        markus78 Newbie

                        Now that this is in https://issues.jboss.org/browse/AS7-1338  , it seems that you can do lookup of EJB's the "old fashioned way", atleast it works for me now with this type of lookup (on latest nightly)

                         

                        Properties props = new Properties();

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

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

                         

                        Context context = new InitialContext(props);

                        SimpleBI bean = (SimpleBI) context.lookup("LogTest/simpleSLSB/SimpleBean!my.slsb.SimpleBI"); // server printout "java:jboss/exported/LogTest/simpleSLSB/SimpleBean!my.slsb.SimpleBI"

                        bean.sayHello("test");

                        context.close();

                         

                        I am happy about this, this will make converting my legacy code a bit less troublesome.

                         

                        BR

                        /Markus

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

                          Does it mean JNDI java:global/xyz bindings get  registered now also under java:jboss/exported/xyz .....?

                          This can work only if your Bean is registered under java:jboss/ jndi scope.

                          From the jiras and discussions... I thought via stand alone remote , only global JMS Ressources can be lookuped...

                          But if you can lookup EJBs.... I guest you will be able to loookup also DataSources any other binded Objects in java:jboss view...

                          I wonder if old fashion way has influance on clustering and security context and works same way als new way Factory Package with lookup("ejb:...)....

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

                            finishing thinking.... what will be the reason to use .lookup("ejb:/../.../..) which can only lookup ejb's... when I can use:

                             

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

                            Context context = new InitialContext(props);

                            context.lookup("java:jboss/exported/anyObjectIn")

                             

                            To lookup ejb, JMSConnectionFactories or DS.

                            You can just edit standalone.xml and set JNDI location  to  java:jboss/exported/mylocation ...

                            • 41. Re: How to call a remote EJB without a property file?
                              Jaikiran Pai Master

                              I'm writing up an document for this JNDI feature and the details related to it. That'll answer your questions.

                              • 42. Re: How to call a remote EJB without a property file?
                                Bernd Koecke Novice

                                Its nice that the result of this issue makes it easier to migrate from older versions to JB7. But the description of issue https://issues.jboss.org/browse/AS7-1338 says that it is deprecated from the beginning. So we should think about what should be possible in future. With the current API in jboss-ejb-client project I can extend it that adding or removeing endpoints at runtime is possible. But the second part is: Should there be an API on the client side to say at which of the configured endpoints an EJB is expected? The default should be the current implementation, that the routing is done behind the scenes. But do we want to have the possibility to influence this routing via an SPI?

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

                                  Yes, Thanks to jaikiran and 7 ^ 2 Heros of AS7 for this and all other solutions they provide to annoing jboss AS 7 users ... !

                                  Speaking about future... remote invocation is for me dead!  I want to have CDI , as I have in J EE Conatiner.... so for me future for stand alone client is embedded conatainer :-)

                                  • 44. Re: How to call a remote EJB without a property file?
                                    Rüdiger zu Dohna Newbie

                                    Radek Rodak wrote:

                                     

                                    remote invocation is for me dead!  I want to have CDI

                                     

                                    @Radek: I assume you mean that you think JNDI lookups are dead and you want to use CDI instead, right? But actually calling services that are running in a separate JVM and probably on a remote server, that's going to stay, ain't it? If that's what you mean, I fully agree... and you'll want to select services based on self-defined qualifiers.