5 Replies Latest reply on Jul 10, 2015 6:18 AM by jmesnil

    Remote namespace for HornetQ

    benjamin.tillman

      Hello, I have a remote HornetQ instance and I was wondering if it's possible (in WildFly 9.0.0.CR2) to set up an external context to access it and allow me to then use @Resource(mappedName="blah") annotations in my code.

       

      I'm trying to follow Remote JNDI Reference - WildFly 9, with something like:

       

      <subsystem xmlns="urn:jboss:domain:naming:2.0">
          <bindings>
              <external-context name="java:global/hornetq" class="javax.naming.InitialContext">
                  <environment>
                      <property name="java.naming.factory.initial" value="org.jnp.interfaces.NamingContextFactory" />
                      <property name="java.naming.provider.url" value="jnp://host:port" />
                      <property name="java.naming.factory.url.pkgs" value="org.jboss.naming:org.jnp.interfaces" />
                  </environment>
              </external-context>
          </bindings>
          <remote-naming/>
      </subsystem>
      

       

      The above version fails when starting WildFly though:

       

      Message: WFLYCTL0133: Missing required attribute(s): module
        at org.jboss.as.controller.parsing.ParseUtils.missingRequired(ParseUtils.java:161)
        at org.jboss.as.naming.subsystem.NamingSubsystem14Parser.parseExternalContext(NamingSubsystem14Parser.java:249)
        at org.jboss.as.naming.subsystem.NamingSubsystem14Parser.parseBindings(NamingSubsystem14Parser.java:128)
        at org.jboss.as.naming.subsystem.NamingSubsystem14Parser.readElement(NamingSubsystem14Parser.java:85)
        at org.jboss.as.naming.subsystem.NamingSubsystem14Parser.readElement(NamingSubsystem14Parser.java:56)
        at org.jboss.staxmapper.XMLMapperImpl.processNested(XMLMapperImpl.java:110)
        at org.jboss.staxmapper.XMLExtendedStreamReaderImpl.handleAny(XMLExtendedStreamReaderImpl.java:69)
        at org.jboss.as.server.parsing.StandaloneXml.parseServerProfile(StandaloneXml.java:1199)
        at org.jboss.as.server.parsing.StandaloneXml.readServerElement_1_4(StandaloneXml.java:457)
        at org.jboss.as.server.parsing.StandaloneXml.readElement(StandaloneXml.java:144)
        at org.jboss.as.server.parsing.StandaloneXml.readElement(StandaloneXml.java:106)
        at org.jboss.staxmapper.XMLMapperImpl.processNested(XMLMapperImpl.java:110)
        at org.jboss.staxmapper.XMLMapperImpl.parseDocument(XMLMapperImpl.java:69)
        at org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:123)
        ... 3 more
      

       

      Any tips on getting this set up, or suggestions on other ways to achieve the same, would be much appreciated

        • 1. Re: Remote namespace for HornetQ
          benjamin.tillman

          I got this up and running to a degree, Wildfly now instantiates and binds an InitialContext for me to use - cool! But I still can't inject queues or topics. What I have so far ...

           

          <subsystem xmlns="urn:jboss:domain:naming:2.0">
              <bindings>
                  <external-context name="java:global/hornetq" module="org.jboss.jnp-client" class="javax.naming.InitialContext" cache="true">
                      <environment>
                          <property name="java.naming.factory.initial" value="org.jnp.interfaces.NamingContextFactory" />
                          <property name="java.naming.provider.url" value="jnp://host:port" />
                          <property name="java.naming.factory.url.pkgs" value="org.jboss.naming:org.jnp.interfaces" />
                      </environment>
                  </external-context>
              </bindings>
              <remote-naming/>
          </subsystem>
          
          

           

          Where I just created the org.jboss.jnp-client module myself: Place into WILDFLY_HOME/modules/system/layers/base/org/jboss/jnp-client/main jnp-client-4.2.2.GA.jar and the following module.xml:

           

          <module xmlns="urn:jboss:module:1.3" name="org.jboss.jnp-client">
              <properties>
                  <property name="jboss.api" value="private"/>
              </properties>
          
              <resources>
                  <resource-root path="jnp-client-4.2.2.GA.jar"/>
              </resources>
          
              <dependencies>
                  <module name="javax.api"/>
                  <module name="org.hornetq"/>
                  <module name="org.jboss.invocation"/>
                  <module name="org.jboss.logging"/>
              </dependencies>
          </module>
          
          

           

          This then binds an InitialContext to java:global/hornetq which I can successfully inject

           

          jndi.png

           

          @Resource(mappedName = "java:global/hornetq")
          InitialContext ic;
          
          ...
          
          private void walkJNDI(String name) {
              try {
                  NamingEnumeration ne = ic.list(name);
                  while (ne.hasMoreElements()) {
                      NameClassPair ncp = (NameClassPair) ne.nextElement();
                      System.out.println(name + "/" + ncp.getName());
                      if (ncp.getClassName().equals("org.jnp.interfaces.NamingContext")) {
                          walkJNDI(name + "/" + ncp.getName());
                      }
                  }
              } catch (NamingException e) {
                  e.printStackTrace();
              }
          }
          
          

           

          06:35:00,952 INFO  [stdout] (default task-3) /comp
          06:35:00,952 INFO  [stdout] (default task-3) /ConnectionFactory
          06:35:00,952 INFO  [stdout] (default task-3) /ThroughputConnectionFactory
          06:35:00,953 INFO  [stdout] (default task-3) /XAThroughputConnectionFactory
          06:35:00,953 INFO  [stdout] (default task-3) /topic
          06:35:00,955 INFO  [stdout] (default task-3) /topic/exampleTopic
          06:35:00,955 INFO  [stdout] (default task-3) /XAConnectionFactory
          06:35:00,956 INFO  [stdout] (default task-3) /queue
          06:35:00,958 INFO  [stdout] (default task-3) /queue/ExpiryQueue
          06:35:00,958 INFO  [stdout] (default task-3) /queue/DLQ
          
          

           

          Is there a way to ask Wildfly to add the bindings from the remote JNDI provider to it's own set of bindings? What I really want to be able to do is simply:

           

          @Resource(mappedName = "java:global/hornetq/topic/exampleTopic")
          Topic topic;
          
          

           

          When I try and do this anyway, I get the following exception:

           

          Caused by: javax.naming.InvalidNameException: Not a compound name: topic/exampleTopic
            at javax.naming.CompoundName.addAll(CompoundName.java:462)
            at org.jnp.interfaces.NamingContext.composeName(NamingContext.java:1018)
            at org.jnp.interfaces.NamingContext.getAbsoluteName(NamingContext.java:1612)
            at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:658)
            at javax.naming.InitialContext.lookup(InitialContext.java:415)
            at javax.naming.InitialContext.lookup(InitialContext.java:415)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:606)
            at org.jboss.as.naming.ExternalContextObjectFactory$CachedContext.invoke(ExternalContextObjectFactory.java:144)
            at javax.naming.InitialContext$$$$Proxy1.lookup(Unknown Source)
            at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:236)
            at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:184)
            at org.jboss.as.naming.InitialContext$DefaultInitialContext.lookup(InitialContext.java:237)
            at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:193)
            at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:189)
            at javax.naming.InitialContext.lookup(InitialContext.java:411)
            at javax.naming.InitialContext.lookup(InitialContext.java:411)
            at org.jboss.as.weld.services.bootstrap.WeldResourceInjectionServices.resolveResource(WeldResourceInjectionServices.java:209)
            at org.jboss.as.weld.services.bootstrap.WeldResourceInjectionServices$1.createResource(WeldResourceInjectionServices.java:157)
            at org.jboss.weld.injection.AbstractResourceInjection.getResourceReference(AbstractResourceInjection.java:44)
            at org.jboss.weld.injection.AbstractResourceInjection.injectResourceReference(AbstractResourceInjection.java:53)
            at org.jboss.weld.util.Beans.injectEEFields(Beans.java:348)
            at org.jboss.weld.injection.producer.ResourceInjector$1.proceed(ResourceInjector.java:69)
            at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48)
            at org.jboss.weld.injection.producer.ResourceInjector.inject(ResourceInjector.java:72)
            at org.jboss.weld.injection.producer.BasicInjectionTarget.inject(BasicInjectionTarget.java:121)
            at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:159)
            at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:96)
            at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:101)
            at org.jboss.weld.bean.ContextualInstanceStrategy$ApplicationScopedContextualInstanceStrategy.get(ContextualInstanceStrategy.java:141)
            at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50)
            at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:761)
            at org.jboss.weld.manager.BeanManagerImpl.getInjectableReference(BeanManagerImpl.java:861)
            at org.jboss.weld.injection.FieldInjectionPoint.inject(FieldInjectionPoint.java:92)
            ... 57 more
          

           

          Am I going about this the right way? Once again, any help would be appreciated.

          • 2. Re: Remote namespace for HornetQ
            jbertram

            I don't know much about the external JNDI context stuff.  However, I can say that there's nothing magic about looking up a JMS destination in JNDI from a remote server.  You could easily define a local queue which matched the remote one and look up the local one instead of trying to do a remote lookup.  You can also configure local connection factories to point to remote servers so that all your JNDI lookups are local.  That might be less work than what you're trying to do currently.

            • 3. Re: Remote namespace for HornetQ
              benjamin.tillman

              Hi Justin, thanks for the reply. I'm definitely open to suggestions here ... do you links or search terms I should be using to find out about pointing my connection factory to a remote server?

              • 4. Re: Remote namespace for HornetQ
                jbertram

                The HornetQ documentation and Wildfly messaging subsystem documentation should help.  Basically any JMS connection factory has a connector.  A connector has a socket-binding.  That socket-binding can point to anywhere.

                • 5. Re: Remote namespace for HornetQ
                  jmesnil

                  Could you try adding this property to your <external-context> configuration:

                   

                  <property name="org.jboss.as.naming.lookup.by.string" value="true"/>

                   

                  Some JNDI providers may fail when their resources are looked up if they do not implement properly the lookup(Name) method and it looks to be the case for the JNP client.


                  You can find some more information at https://docs.jboss.org/author/display/WFLY9/Naming+Subsystem+Configuration