Dependency injection with bean in tomcat

2

I was trying a resource injection but I'm not following. I'm studying for the Web Components exam, so I was practicing some code.

I'm following an example given by the Tomcat 7 documentation, link , but I have not yet achieved success in my tests.

Before I was having a container problem I could not find my classes to be injected, but then I realized that I should put it inside the server's lib folder, so I could find it.

The problem now is that it can not create the instance as it can be seen in the log.

Do I still have to configure anything?

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>
    
asked by anonymous 27.10.2016 / 19:37

1 answer

1

I'm a bit rusty with these APIs, but the problem can occur if you've put the MyBean class together with the application, within WEB-INF/lib .

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

If you want to instantiate a class globally in Tomcat, what will happen when declaring the resource in 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 features that create JDBC connections. If the connection is managed by Tomcat, the driver should be in the global scope rather than in the application, after all the server.xml is loaded regardless of the applications installed on the server.

A place where you can put the class is in the libraries folder ( /lib ). See the documentation for further explanation: link

I'm sorry if it was repetitive, but it's a tricky concept to pick up at first, so hopefully things will get clearer.

    
28.10.2016 / 02:43