9 Replies Latest reply on Aug 4, 2015 10:11 AM by prasanth_jboss

    Resource Injection in ServletContextListener

    prasanth_jboss

      I have a ServletContextListener into which a DataSource has to be injected. It works fine in Jboss7.1 but does not work in 8.2 or 8.2.1 or 9.01. I have created a sample project to test it and seems like the injection is working if the class is a HttpServlet but doesn't work if the class is just a ServletContextListener. Am I missing something or is there a bug in wildfly?

       

      Thanks,

      Prasanth

       

      -----------------------jboss-web.xml-------------------------------

      <?xml version="1.0" encoding="UTF-8"?>

      <jboss-web>

          <context-root>sample</context-root>

          <virtual-host>sample</virtual-host>

         

          <resource-ref>

              <res-ref-name>DocServer</res-ref-name>

              <jndi-name>java:jboss/datasources/doc_server</jndi-name>

          </resource-ref>

      </jboss-web>

      -----------------------------------------------------------------------------

       

      public class ContextListener implements ServletContextListener {

         

          @Resource(name="DocServer")

          private DataSource dataSource;

       

          @Override

          public void contextDestroyed(ServletContextEvent arg0) {

              // TODO Auto-generated method stub

             

          }

       

          @Override

          public void contextInitialized(ServletContextEvent arg0) {

              // TODO Auto-generated method stub

             

          }

         

          public DataSource getDataSource() {

              return dataSource;

          }

       

      }

        • 1. Re: Resource Injection in ServletContextListener
          prasanth_jboss

          Minor correction the variable DataSource is declared as static  (private static DataSource dataSource).

           

          If I remove static from variable declaration then the injection is working.

          • 2. Re: Resource Injection in ServletContextListener
            prasanth_jboss

            Looks like wildfly has stopped support for injecting into static variables. The work around is to create a non static variable for the injection to work and then in contextInitialized function set the static variable with the non static variable reference.

             

            @Resource(name="DocServer")

                private DataSource docDataSourceInjection;

                private static DataSource docDataSource;

             

            public void contextInitialized(ServletContextEvent event){

                 docDataSource = docDataSourceInjection;

            }

             

            Another approach is to make the class singleton (if that works for your design) and store the instance created by the container.

            • 3. Re: Resource Injection in ServletContextListener
              jaikiran

              The spec states that the resource injection is only supported in non-static fields. At some point, JBoss AS7 used to support injection in static fields but as far as I remember that was just accidental and not intentional and that was fixed in a later release as you notice now.

              • 4. Re: Resource Injection in ServletContextListener
                prasanth_jboss

                Good to know. Thank you JaiKiran.

                • 5. Re: Resource Injection in ServletContextListener
                  prasanth_jboss

                  It would be nice if Wildfly could through an error/warning message as to why the injection is not done, when it sees a static variable.

                  • 6. Re: Resource Injection in ServletContextListener
                    jameslivingston

                    Probably a better question is why you want to store it in a static variable, it probably means something is wrong in your design since the datasource may only be valid between the servlet instance's creating and destruction.

                    • 7. Re: Resource Injection in ServletContextListener
                      prasanth_jboss

                      This class handles all database connection requests for the project (has a static getConnection method). Rather than trying to get a datasource from JNDI every time it gets a connection request I am storing the datasource from the initial resource injection. I am open for any better solutions.

                       

                      Note: As mentioned above as a solution, I did make the class singleton. Saving the instance created by the container to call the context initialized method.

                      • 8. Re: Resource Injection in ServletContextListener
                        jameslivingston

                        The correct solution is to @Resource inject the DataSource object into anything that needs it, and simply use ds.getConnection() rather than YourUtility.getConnection().

                         

                        Using a static helper may appear easier, but you shouldn't do it since it can cause all sorts of issues like this.

                        • 9. Re: Resource Injection in ServletContextListener
                          prasanth_jboss

                          @Resource injection can't be used in business classes which would require the database connection. It is limited to Servlets, Filters & Listeners. Segregating the code that handles the database connections would make it easy to change how we get connections. We used to have a direct JNDI lookup for datasource if we had that code in every class that needs a connection that would be so much duplication of code. Later on the lookup was replaced with @Resource injection. In the future if we have to change this to some thing else there will be one class to modify rather than modifying every class that uses a database connection.

                           

                          I didn't realize the spec doesn't support static variable injection as JBoss was supporting it. With a singleton class you can avoid static variables and at the same time segregate the code that gets you the database connection.