5 Replies Latest reply on Jun 6, 2012 3:13 PM by madchedar0

    Binding to an InitialContext in JBoss 7.1.1

    madchedar0

      I've been scouring the forums/web for a way to bind objects to names using an InitialContext object.  I'm in the process of migrating our code from JBoss 5.1.0GA to JBoss 7.1.1Final.

       

      I have a few services with constructors like the following:

       

      public SomeServiceManager() {
           context = new InitialContext();
           try {
                context.bind(SERVICE_NAME, this); // where SERVICE_NAME is "java:/SomeServiceManager" or similar
           } catch(NamingException e ) {
                logger.error("Failed to bind name in context", e);
           }
      }
      

       

      But I get the following error during startup (I have an ear called nexus.ear that contains the sar I'm porting over to as7.1.1 called nexus.sar):

       

      10:57:33,683 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-13) MSC00001: Failed to start service jboss.deployment.subunit."nexus.ear"."nexus.sar".INSTALL: org.jboss.msc.service.StartExcepti

      on in service jboss.deployment.subunit."nexus.ear"."nexus.sar".INSTALL: Failed to process phase INSTALL of subdeployment "nexus.sar" of deployment "nexus.ear"

              at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:119) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]

              at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]

              at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746) [jboss-msc-1.0.2.GA.jar:1.0.2.GA]

              at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [rt.jar:1.6.0_30]

              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [rt.jar:1.6.0_30]

              at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_30]

      Caused by: java.lang.IllegalArgumentException: JBAS017221: Class not instantiated

              at org.jboss.as.service.ReflectionUtils.newInstance(ReflectionUtils.java:107)

              at org.jboss.as.service.ParsedServiceDeploymentProcessor.newInstance(ParsedServiceDeploymentProcessor.java:204)

              at org.jboss.as.service.ParsedServiceDeploymentProcessor.addServices(ParsedServiceDeploymentProcessor.java:109)

              at org.jboss.as.service.ParsedServiceDeploymentProcessor.deploy(ParsedServiceDeploymentProcessor.java:99)

              at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:113) [jboss-as-server-7.1.1.Final.jar:7.1.1.Final]

              ... 5 more

      Caused by: java.lang.reflect.InvocationTargetException

              at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [rt.jar:1.6.0_30]

              at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) [rt.jar:1.6.0_30]

              at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) [rt.jar:1.6.0_30]

              at java.lang.reflect.Constructor.newInstance(Constructor.java:513) [rt.jar:1.6.0_30]

              at org.jboss.as.service.ReflectionUtils.newInstance(ReflectionUtils.java:105)

              ... 9 more

      Caused by: java.lang.UnsupportedOperationException: JBAS011859: Naming context is read-only

              at org.jboss.as.naming.WritableServiceBasedNamingStore.requireOwner(WritableServiceBasedNamingStore.java:126)

              at org.jboss.as.naming.WritableServiceBasedNamingStore.bind(WritableServiceBasedNamingStore.java:56)

              at org.jboss.as.naming.NamingContext.bind(NamingContext.java:221)

              at org.jboss.as.naming.InitialContext.bind(InitialContext.java:161)

              at org.jboss.as.naming.NamingContext.bind(NamingContext.java:230)

              at javax.naming.InitialContext.bind(InitialContext.java:400) [rt.jar:1.6.0_30]

       

       

      Now I have seen similar topics start to address the read-only naming context issue:

      https://community.jboss.org/thread/177141

      https://issues.jboss.org/browse/AS7-2755

       

      And the solution is apparently by doing the following here:

      https://issues.jboss.org/browse/AS7-2667?focusedCommentId=12654355&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-12654355

       

      The code that's supposed to do the trick:

       

      WritableServiceBasedNamingStore.pushOwner(context.getChildTarget());
          try {
          jmsManager.createConnectionFactory(false, configuration, configuration.getBindings());
          } finally {
          WritableServiceBasedNamingStore.popOwner();
          }
      

       

      But isn't clear to me is:

      • The type of context object that is being used that has method "getChildTarget".  Is it not an InitialContext object?  Is it an OperationContext object?
      • Are services supposed to instantiate their own WritableServiceBasedNamingStore to accomplish this?

       

      I'm unclear because I was stepping through the WritableServiceBasedNamingStore code and it seems like unless there is a WritableServiceBasedNamingStore.WRITE_OWNER (http://grepcode.com/file/repo1.maven.org/maven2/org.jboss.as/jboss-as-naming/7.1.1.Final/org/jboss/as/naming/WritableServiceBasedNamingStore.java#WritableServiceBasedNamingStore.0WRITE_OWNER) associated with a ServiceTarget, then you get the "Naming Context is read-only" exception thrown here: http://grepcode.com/file/repo1.maven.org/maven2/org.jboss.as/jboss-as-naming/7.1.1.Final/org/jboss/as/naming/WritableServiceBasedNamingStore.java#WritableServiceBasedNamingStore.requireOwner%28%29

       

      When I've tried incorporating the above code into my services I've run into issues because I guess I'm supposed to create ServiceTarget objects and maybe have an OperationContext instead of an InitialContext object?  Problem is those classes (ServiceTargetImpl, ServiceBuilderImpl, OperationContext) are relagated to having only package access and aren't accessible.  So I'm unsure of where to turn next.

       

      Is there a way to bind objects to an InitialContext similar to the way it was done in JBoss 5.1.0GA?  If not, what is the correct way?

       

      Thank you

        • 1. Re: Binding to an InitialContext in JBoss 7.1.1
          jaikiran

          The easiest way to bind those objects would be to use a @javax.ejb.Startup @javax.ejb.Singleton and bind them in @PostConstruct method. You won't have to do anything additional and you won't even need the sar (assuming that's the only thing you are using it for):

           

          @Singleton
          @Startup
          public class SomeServiceManager {
          
           @PostConstruct
           private void onConstruct() {
           Context context = new InitialContext();
               try {
                    context.bind(SERVICE_NAME, this); // where SERVICE_NAME is "java:/SomeServiceManager" or similar
               } catch(NamingException e ) {
                    logger.error("Failed to bind name in context", e);
               }
          ... 
           }
          }
          

           

          Is that something that you want to try?

          • 2. Re: Binding to an InitialContext in JBoss 7.1.1
            madchedar0

            Thank you Jaikiran for posting/answering this!  I'm now able to have those services bind their contexts.  I'm going to research the annotations you used to better understand what's going on.  This helps me a great deal.  Thanks again!  I hope this post helps others that run into this.

            • 3. Re: Binding to an InitialContext in JBoss 7.1.1
              gandon

              Hi,

               

              I encountered exactly the same problem, and for some reason we'd like to not use the annotation way. Could you share how you get the services bound to the contexts?

               

              Thanks a lot.

              madchedar0 wrote:

               

              Thank you Jaikiran for posting/answering this!  I'm now able to have those services bind their contexts.  I'm going to research the annotations you used to better understand what's going on.  This helps me a great deal.  Thanks again!  I hope this post helps others that run into this.

              • 4. Re: Binding to an InitialContext in JBoss 7.1.1
                jaikiran

                Gan Dong wrote:

                 

                Hi,

                 

                I encountered exactly the same problem, and for some reason we'd like to not use the annotation way.

                You can do the same using the ejb-jar.xml. Create a session bean of type Singleton and set the init-on-startup element. Either way (annotations or ejb-jar.xml), this is a portable spec compliant way of doing it.

                • 5. Re: Binding to an InitialContext in JBoss 7.1.1
                  madchedar0

                  I guess I spoke too soon.  I *thought* my services were binding their InitialContext objects because I wasn't seeing the errors from the original post.

                   

                  The exception (java.lang.UnsupportedOperationException: JBAS011859: Naming context is read-only) wasn't occuring because the @PostConstruct method in my service isn't being called at all.  Is this possible?

                   

                  I'll come back to this when I can, but for the time being I've changed my services from xmbeans (they were xmbeans in JBoss 5.1.0GA) to regular mbeans.

                   

                  The services now look like the following (simplified code):

                   

                   

                  // SomeServiceManagerMBean.java
                  public interface SomeServiceManagerMBean {
                      // can be empty if you want
                  }
                  
                  // SomeServiceManager.java
                  @Singleton
                  @Startup
                  public class SomeServiceManager implements Serializable, SomeServiceManagerMBean {
                       public SomeServiceManager() {
                            // constructor stuff
                       }
                  
                       
                       @PostConstruct
                      private void onConstruct() {
                          try {
                              logger.info("--------------------------------------> About to bind context");
                              context.bind(SERVICE_NAME, this); 
                          } catch (NamingException e) {
                              logger.error("Failed to bind name in context", e);
                          }
                      }
                  
                       // other methods
                  }
                  

                   

                  The funny thing is that I can see through log prints that the SomeServiceManager is created (its constructor is called) but @PostConstruct doesn't get called. 

                   

                  As a hack I tried this: create a thread to call onConstruct (hopefully) after the constructor finishes:

                   

                   

                  public SomeServiceManager() {
                       logger.info("Manually calling onConstruct in separate thread");
                       onConstruct();
                       Thread onConstructThread = new Thread(new Runnable() {
                  
                              public void run() {
                                  while (true) {
                                      try {
                                          Thread.sleep((long) (3000));
                                          onConstruct();
                                      } catch (InterruptedException e) {
                                          logger.info("Trouble sleeping in thread: " + e);
                                      }
                  
                                  }
                              }
                          });
                          onConstructThread.start();
                  } 
                  

                   

                  That's just an attempt to force onConstruct() to be called.  When it tries to bind the InitialContext it still fails. 

                   

                  Like I said I'm at a loss of what to try for now but when I come back to this I'll post an answer or clarify with another question.