Bean dependency injection on Tomcat

Asked

Viewed 156 times

2

I was trying to get an emergency injection, but I’m not following. I’m studying for the Web Components test, so I was practicing some code.

I’m following an example given by the Tomcat 7 documentation, http://tomcat.apache.org/tomcat-7.0-doc/jndi-resources-howto.html, but I have not yet succeeded in my tests.

Before I had container problem I could not find my classes to be injected, but then I realized I should put it inside the server lib folder, so it was possible to find it.

The problem now is that it cannot create the instance as you can see in the log.

Still missing I perform some configuration?

Catalina.out

GRAVE: Allocate exception for servlet com.MyAnoServlet
javax.naming.NamingException: Cannot create resource instance
    at org.apache.naming.factory.ResourceEnvFactory.getObjectInstance(ResourceEnvFactory.java:115)
    at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:848)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:173)
    at org.apache.catalina.core.DefaultInstanceManager.lookupFieldResource(DefaultInstanceManager.java:545)
    at org.apache.catalina.core.DefaultInstanceManager.processAnnotations(DefaultInstanceManager.java:447)
    at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:133)
    at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:114)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1133)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:853)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1083)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:640)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

Myanoservlet.java

package com;

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
import java.io.*;
import javax.naming.*;
import javax.annotation.Resource;
import java.util.*;
import com.mycompany.*;

@WebServlet("/myservlet")
public class MyAnoServlet extends HttpServlet{

  public void doGet(HttpServletRequest req,HttpServletResponse resp) throws IOException{

    PrintWriter out = resp.getWriter();

    try{
      Context initCtx = new InitialContext();
      Context envCtx = (Context) initCtx.lookup("java:comp/env");
      MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory");

      out.println("foo = "+bean.getFoo()+", bar = "+bean.getBar());

    }catch(NamingException e){
      e.printStackTrace();
    }
  }
}

Mybean.java

package com.mycompany;

public class MyBean {

  private String foo = "Default Foo";

  public String getFoo() {
    return (this.foo);
  }

  public void setFoo(String foo) {
    this.foo = foo;
  }

  private int bar = 0;

  public int getBar() {
    return (this.bar);
  }

  public void setBar(int bar) {
    this.bar = bar;
  }

}

web xml.

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">

<resource-env-ref>
    <description>
      Object factory for MyBean instances.
    </description>
    <resource-env-ref-name>
      bean/MyBeanFactory
    </resource-env-ref-name>
    <resource-env-ref-type>
      com.mycompany.MyBean
    </resource-env-ref-type>
  </resource-env-ref>

</web-app>

server.xml (Tomcat)

<GlobalNamingResources>
<!-- Editable user database that can also be used by
     UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
          type="org.apache.catalina.UserDatabase"
          description="User database that can be updated and saved"
          factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          pathname="conf/tomcat-users.xml" readonly="false" />

<Resource name="bean/MyBeanFactory" auth="Container"
        type="com.mycompany.MyBean"
        factory="org.apache.naming.factory.BeanFactory"
        bar="23"/>
</GlobalNamingResources>

1 answer

1

I’m a little rusty with these Apis, but the problem might occur if you put the class MyBean together with the application, within WEB-INF/lib.

Web containers have a hierarchy of class loaders so that the classes of one application do not interfere with those of another application. In addition, they have some libraries shared among all applications, which are loaded into one class Loader upper-level.

If you want to instantiate a class globally in Tomcat, what will happen when declaring the resource on server.xml, which is global, so such classes must be in a library loaded by a class Loader global.

This is analogous, for example, to resources that create JDBC connections. If the connection is managed by Tomcat, the driver should be in the overall scope and not in the application, after all the server.xml is loaded independent of the applications installed on the server.

A place where you can place the class is in the library folder (/lib). See the documentation for further explanations: https://tomcat.apache.org/tomcat-7.0-doc/appdev/deployment.html

I’m sorry if I’ve been repetitive, but it’s a complicated concept to pick up at the beginning, so I hope that way things will become clearer.

  • I just put the Mybean class inside Tomcat’s lib folder and it is packaged in a jar.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.