1 2 Previous Next 16 Replies Latest reply on Jun 26, 2019 8:40 AM by Greg Brown

    Transparent deployment for Cluster and Standalone modes

    Clemens August Newbie

      Hello,

       

      we deploy an EAR file with session beans in Wildfly 9.0.2. We support standalone and cluster installations. At one point, I have found no way to support both modes transparently. The problem is with the group system (org.wildfly.clustering.group).

       

      We do the group lookup with

       

           @Resource(lookup = "java:jboss/clustering/group/default")

           private Group group;

       

      This works fine in clustered mode. In standalone mode, the resource injection does not work. Anyway, going by a simple JNDI lookup on "java:jboss/clustering/group/default" does not work, either, as it always returns null, in clustered mode, too.

       

      For our logic it would be appropriate to get a null value for group in standalone mode. As it works only with a resource injection (i.e., deployment fails in standalone), up to now it seems, that we need different builds for cluster and standalone mode.

       

      I tried injecting a Group as a @Resource into a CDI bean in order to activate it at runtime (after deployment) and then decide, whether I am in cluster mode, but the CDI bean could not be instantiated due to a "Service not started" - error.

       

      Thus my question: is there a way to transparently look up the cluster group (or the org.wildfly.clustering.dispatcher.CommandDispatcherFactory) in a way, that would return null in standalone mode and the actual objects in cluster mode and be deployable in both standalone and cluster mode?

       

      Thank you for your time and input in advance.

       

      Clemens

        • 1. Re: Transparent deployment for Cluster and Standalone modes
          Clemens August Newbie

          I have found a viable solution: pack a minimal EAR with 1 session bean, which contains the injection as mentioned above:

           

               @Resource(lookup = "java:jboss/clustering/group/default")

               private Group group;

           

          This EAR is deployed only in a cluster installation. In all other places, the Group now can be fetched by a JNDI lookup. In a standalone installation the lookup will fail, and null can be returned.

          • 3. Re: Transparent deployment for Cluster and Standalone modes
            Clemens August Newbie

            Hello Paul

             

            Thank you very much for your answer. I would just like to make clear, what it is related to, because there was a reply by me already. So please allow me to follow up with 2 questions.

             

            1. Do you mean, that as of WF10.1, I can inject an org.wildfly.clustering.group.Group as a @Resource into a session bean, and it will work in standalone as well, giving a null value for the Group?
            2. Further on, can you confirm, that in WF9.0.2 this behaves differently, i.e., deployment of such a bean will fail in standalone mode?

             

            I am asking, because for the time being we have to stay with WF9.0.2, and I would like to understand, whether I missed something by introducing the workaround described in my own reply.

             

            Best regards

            Clemens

            • 4. Re: Transparent deployment for Cluster and Standalone modes
              Paul Ferraro Master

              clemens_august In WF10, all "default" clustering abstractions (including Group) will resolve to a local implementation when using a non-clustered server configuration.  The local implementation of Group only has a membership of itself, and can never receive membership change events.  I think this is more graceful than resolving to null.

               

              These local implementations existed in WF9, but they used a separate JNDI name, e.g. java:jboss/clustering/group/local

              So, the only way to make this transparent to your application was to externalize the absolute JNDI names to a deployment descriptor, and reference the clustering resources via their resource-ref names.

              • 5. Re: Transparent deployment for Cluster and Standalone modes
                Greg Brown Newbie

                I realize this is an old question, but I'm still seeing something similar in Wildfly 17. I'm trying to inject a CommandDispatcherFactory as follows (based on the documentation in the High Availability Guide):

                 

                @Resource(lookup = "java:jboss/clustering/dispatcher/default")

                private CommandDispatcherFactory factory;

                 

                This works fine when running in a cluster, but generates the following exception when running standalone:

                 

                Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'java:jboss/clustering/dispatcher/default' available: not found in JNDI environment

                at org.springframework.jndi.support.SimpleJndiBeanFactory.getBean(SimpleJndiBeanFactory.java:122)

                at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:487)

                at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:636)

                at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)

                at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)

                at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:321)

                ... 175 more

                 

                Injecting the default group works correctly in both configurations:

                 

                @Resource(lookup = "java:jboss/clustering/group/default")

                private Group group;

                 

                Any suggestions would be very much appreciated.

                 

                Thanks,

                Greg Brown

                 

                [edit] For what it's worth, looking up the local command dispatcher factory (java:jboss/clustering/dispatcher/local) throws a NamingException in standalone mode.

                • 6. Re: Transparent deployment for Cluster and Standalone modes
                  Paul Ferraro Master

                  That's strange.  We have an integration test that validate this exact scenario:

                  wildfly/CommandDispatcherTestCase.java at master · wildfly/wildfly · GitHub

                   

                  Have you made any changes to the default standalone.xml?

                  • 7. Re: Transparent deployment for Cluster and Standalone modes
                    Paul Ferraro Master

                    It's also unclear to my why spring is resolving the @Resource annotation.  This is the responsibility of the container (i.e. ee subsystem of WildFly).

                    • 8. Re: Transparent deployment for Cluster and Standalone modes
                      Greg Brown Newbie

                      Thanks for the response. We have modified standalone.xml as well as standalone-ha.xml. I looked at the diff for both but didn't see anything obvious. Is there something in particular I should be looking for?

                      • 9. Re: Transparent deployment for Cluster and Standalone modes
                        Greg Brown Newbie

                        Hi Paul,

                        I just installed a fresh download of Wildfly 17 (no changes to the default config), and the "java:jboss/clustering/group/default" name doesn't appear to be registered in the JNDI tree. There's actually no entry for "clustering" at all.

                        Greg

                        • 10. Re: Transparent deployment for Cluster and Standalone modes
                          Paul Ferraro Master

                          These are not static jndi bindings.  The bindings are only resolvable if the deployment references them.  Normally, a @Resource annotation is sufficient to establish a dependency on the given clustering service to the deployment.  Can you paste the class that contains the @Resource annotation?

                          • 11. Re: Transparent deployment for Cluster and Standalone modes
                            Greg Brown Newbie

                            Hi Paul,

                             

                            I believe this is the relevant source code:

                             

                            @Service

                            public class ClusterCallService

                            {

                             

                              @Resource(lookup = "java:jboss/clustering/dispatcher/default")

                              private CommandDispatcherFactory dispatcherFactory;

                             

                              private ClusterMembershipService clusterMembershipService = null;

                             

                              private CommandDispatcher<ClusterCallService> dispatcher = null;

                             

                              private Map<String, Object> handlers = new HashMap<>();

                             

                              private static final Logger log = Logger.getLogger(ClusterCallService.class);

                             

                              @Autowired

                              public void setClusterMembershipService(ClusterMembershipService clusterMembershipService)

                              {

                                this.clusterMembershipService = clusterMembershipService;

                              }

                             

                              @PostConstruct

                              protected void init()

                              {

                                log.info("Initializing cluster call service for " + clusterMembershipService.getNodeName());

                             

                                dispatcher = dispatcherFactory.createCommandDispatcher(getClass().getName(), this);

                              }

                             

                              @PreDestroy

                              protected void dispose()

                              {

                                dispatcher.close();

                              }

                             

                              ...

                            }

                             

                            Thanks!

                            Greg

                            • 12. Re: Transparent deployment for Cluster and Standalone modes
                              Paul Ferraro Master

                              OK - I'm not sure how, but it looks to me like Spring is getting first crack at wiring you bean, which would explain the failure to resolve the jndi name (as well as the stacktrace).  Try moving your CommandDispatcherFactory jndi binding to your deployment descriptor and reference it by name.

                               

                              e.g.

                               

                              <resource-ref>

                                 <res-ref-name>clustering/dispatcher</res-ref-name>

                                 <lookup-name>java:jboss/clustering/dispatcher/default</lookup-name>

                              </resource-ref>

                               

                              This has the effect of both establishing the dependency on the CommandDispatcherFactory to your deployment, as well as create a static JNDI binding to your application's local namespace (i.e. java:comp/env/clustering/dispatcher)

                              Then inject the CommandDispatcherFactory into your ClusterCallService bean via:

                               

                              @Resource(name = "clustering/dispatcher")

                              private CommandDispatcherFactory dispatcherFactory;

                               

                              That should do the trick.

                              • 13. Re: Transparent deployment for Cluster and Standalone modes
                                Jaikiran Pai Master

                                pferraro  wrote:

                                 

                                OK - I'm not sure how, but it looks to me like Spring is getting first crack at wiring you bean, which would explain the failure to resolve the jndi name (as well as the stacktrace). 

                                Hi Paul,

                                it looks like Greg is trying to inject this resource into a non-Java EE component:

                                 

                                @Service

                                public class ClusterCallService

                                {

                                 

                                  @Resource(lookup = "java:jboss/clustering/dispatcher/default")

                                  private CommandDispatcherFactory dispatcherFactory;

                                The @Service isn't a Java EE annotation. We (JBoss AS) used to support a @org.jboss.ejb3.annotation.Service during AS 5.x days but that support was removed starting AS7. So I don't think, it any of our Java EE or WildFly specific annotations.

                                Greg, can you post the fully qualified name of this annotation that you are importing? I'm guessing it's some kind of a Spring annotation which marks this as a Spring bean, which then explains why Spring takes control over this injection and fails.

                                • 14. Re: Transparent deployment for Cluster and Standalone modes
                                  Greg Brown Newbie

                                  It is a Spring annotation (org.springframework.stereotype.Service). However, I'm not sure that's the source of the problem. For example, this code works fine:

                                   

                                  @Service

                                  public class ClusterMembershipService

                                  {

                                   

                                    @Resource(lookup = "java:jboss/clustering/group/default")

                                    private Group group = null;

                                   

                                    ...

                                  }

                                   

                                  Greg

                                  1 2 Previous Next