6 Replies Latest reply on Jun 26, 2012 10:17 AM by kdolan1

    JNDI NameNotFoundException from background thread

    kdolan1

      I'm currently upgrading from JBoss 4.0.1sp1 to JBoss 7.1.1 Final.

       

      I have an EAR w/ WARs and JARs.  It accesses a database and therefore the standalone.xml contains a data source declaration and the deployment descriptors do as well as resolving the declarations.

       

      In JBoss 7, the application currently deploys and runs for the most part...it can read and write to the database w/o problem...with one exception.  I have a class that extends TimerTask and implements Runnable.  When it goes off, it calls (DataSource)ic.lookup(dsJndiName); w/ a JNDI name of "java:comp/env/jdbc/MyDataSource".  This invocations throws NameNotFoundException.

       

      In the application code, there are lots of calls to ic.lookup() w/ values passed that are identical in prefix (e.g., java:comp/env/jdbc) and deployment descriptors in check.  I don't see anything different w/ this particular one.  Therefore, I can only assume that context is different in the backgroup thread as opposed to when ic.lookup() is invoked as the result of a regular client/servlet/ejb call. 

       

      Any ideas?  I know JNDI stuff changed w/ JBoss 7.  I just can't figure out how I need to change my code/configuration to get this to work again.

       

      Kelly

        • 1. Re: JNDI NameNotFoundException from background thread
          jaikiran

          The java:comp namespace belongs to a EE "component". The thread that gets triggered and looks up under the java:comp namespace is not an EE component. So you can't access that namespace there. You might want to either use a EE component in that thread which then does the java:comp lookup (assuming you have setup that datasource in the java:comp namespace of that component) or just use the non-component specific JNDI name of that datasource (ex: java:jboss/datasources/...)

          1 of 1 people found this helpful
          • 2. Re: JNDI NameNotFoundException from background thread
            kdolan1

            Thanks.  I got something to work.

             

            I tried a number of things and ended up funnelling the call through an EE component (e.g., session EJB).

             

            Using the debugger, I tried changing the JNDI name I was looking up and it worked in some cases (I believe using the jndi-name value in standalone.xml as well as the java:jboss version).  However, I opted not to implement the solution this way because:

             

            a) re: jndi-name value in standalone.xml - the whole point of the JNDI name in code and the resolution in deployment descriptors is so the mapping from logical to physical can be changed w/o recompiling

            b) re: java:jboss - this does not work if the application is deployed in other EE containers

            c) the JNDI lookups encountered by the background thread are in some of our own "common" code that is also used directly by EE components.  In the latter case, the lookups succeed.

             

            I also tried using "java:app" and "java:global" and was not successful.  I'm not sure if they should work but did not because I needed to add env entry declarations elsewhere (but where?) or if they are also not intended to work outside of EE components.

            • 3. Re: JNDI NameNotFoundException from background thread
              jaikiran

              Kelly Dolan wrote:

               

               

              I also tried using "java:app" and "java:global" and was not successful.  I'm not sure if they should work but did not because I needed to add env entry declarations elsewhere (but where?) or if they are also not intended to work outside of EE components.

              Similar to java:comp, these java:app, java:module and java:global are all EE specific JNDI namespaces. So you can use them from within an EE component. A random thread is not a EE component, so you can't use it there.

               

              Why is that thread looking up that datasource? Instead of letting the EE components, that require the datasource, do the lookup or even injection?

              1 of 1 people found this helpful
              • 4. Re: JNDI NameNotFoundException from background thread
                kdolan1

                Thanks for the extra info. 

                 

                Why?  The application on request of certain commands by a user, does its thing and then some initiates some post-operation function (e.g., log, email).  Some post-operation functions are declared as asynchronous (e.g., not needed to be a part of the overall command transaction, if failed could be retried, user gets control back faster).  The asynchronous behavior was implemented as a TimerTask, that processes a queue of requests and for each request that is due to be executed, creates a Thread and executes it on that thread.  Some of these post-operation functions access the database and the existing code referenced something like "java:comp/env/jdbc/MyDataSource", which was declared in ejb-jar.xml and resolved to the actual JNDI name in jboss.xml (now jboss-ejb3.xml).  Lastly, the same code is "shared" w/ code executed in the EJB itself so it works when invoked this way.

                 

                Ultimately, the application was written long ago and how the asynchronous behavior was implemented was most likely the choice because it worked and there was probably no other option.  The question now rolling around in my head is how does one implement (or what is best practice for implementing) asynchronous behavior today and still have access to the JNDI environment?  I'm trying to think of all the background threads we have, if I'm going to encounter additional problems as I try to upgrade and if we need to totally re-work them.  Of course (a) and (b) noted in my previous post raised by you are options but not my first choice based on my reasons.  Currently, I resolved my issue by creating a new API on my EJB and having the background thread call it.  However, it seems awkward because I have EJB A that creates a background thread that calls EJB A which means in my deployment descriptor, I declare EJB A w/ a reference to itself.

                 

                In any case, I also recently ran into some information about an asynchronous EJB.  I have not had time to dig into this but is this an option and therefore worth pursuing?  Finally, we also have Quartz integrated into the application (recent addition).  I'm wondering if this is an option since it seems to perform tasks in the background and allow scheduling and retries (a feature of our post-operation functions).

                 

                Thoughts?

                • 5. Re: JNDI NameNotFoundException from background thread
                  jaikiran

                  Kelly Dolan wrote:

                   

                  Currently, I resolved my issue by creating a new API on my EJB and having the background thread call it.  However, it seems awkward because I have EJB A that creates a background thread that calls EJB A

                  That's where the problem starts. The EJB and EE spec states that the user application code is not expected to start a thread from within the EE components.

                   

                   

                  Kelly Dolan wrote:

                   

                   

                  In any case, I also recently ran into some information about an asynchronous EJB.  I have not had time to dig into this but is this an option and therefore worth pursuing?

                  Yes it is. The reason why @Asynchronous was introduced was to solve use cases like these and not have to resort of JMS MDBs for getting the EE functionality in an asynchronous task. So yes, that's a right path to pursue. You can then invoke the EJB method marked as @Asynchronous from within the EJB, using the bean's proxy (a.k.a business object. @see SessionContext.getBusinessObject() method).

                   

                   

                  Kelly Dolan wrote:

                   

                  Finally, we also have Quartz integrated into the application (recent addition).  I'm wondering if this is an option since it seems to perform tasks in the background and allow scheduling and retries (a feature of our post-operation functions).

                  Quartz and other similar timer implementations (and even EJB 3.1 timer service feature) have much more than just triggering asynchronous tasks. Like you say, you can "schedule" the tasks at various intervals. However, if you go the Quartz way, you still will end up with this issue of not being able to use the EE JNDI namespaces and other EE functionality directly within that Quartz task. Of course, you can just implement the Quartz task as something that just delegates to the EE component like EJB. It ultimately depends on the application needs.

                  • 6. Re: JNDI NameNotFoundException from background thread
                    kdolan1

                    Thanks!