2

I'm trying to have a simple Jersey based jaxrs listener, running on my existing tomcat 7.0.57. Tomcat has a global config in its context.xml for a jdbc datasource, which I want to use.

My problem is that I can't get the resource to resolve via the @Resource annotation.

Heres a simple test example

@Path("/")
public class TestJersey {
    @Resource(name = "jdbc/default")
    private DataSource dsA;

    @Resource(name = "java:comp/env/jdbc/default")
    private DataSource dsB;

    @Resource(lookup = "java:comp/env/jdbc/default")
    private DataSource dsC;

    @Resource(mappedName="jdbc/default")
    private DataSource dsD;

    @GET
    @Produces("text/plain")
    public String test() throws NamingException {
        StringBuffer ret = new StringBuffer();
        ret.append("A: " + dsA + "\n");
        ret.append("B: " + dsB + "\n");
        ret.append("C: " + dsC + "\n");
        ret.append("D: " + dsD + "\n");        
        DataSource ds1 = 
              (DataSource) InitialContext.doLookup("java:comp/env/jdbc/default");
        ret.append("1: " + ds1 + "\n");
        return ret.toString();
    }
}

This test app returns the following

A: null
B: null
C: null
D: null
1: org.apache.tomcat.jdbc.pool.DataSource@1518c95{ConnectionPool[d.....

So the jdbc connection is configured, and can be accessed with an explicit doLookup, so why can't I get it working with a @Resource annotation?

My apps web.xml contains

<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.test</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

I've spend some time searching for what I'm doing wrong but I can't find it. I've read posts suggesting adding things like the following web.xml snippets, but they haven't helped

  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/default</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>

For completeness, my maven dependencies are simply jersey:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.19</version>
</dependency>
AntonPiatek
  • 823
  • 6
  • 11
  • 1
    You may want to try [integrating CDI support](https://jersey.java.net/documentation/latest/cdi.support.html) – Paul Samsotha Aug 06 '15 at 03:10
  • Thanks "Apache Tomcat is another Servlet container that is known to work fine with Jersey CDI support. However, things do not work there out of the box. You need to enable CDI support in Tomcat e.g. using Weld". Will have a read and a play, see if it helps – AntonPiatek Aug 06 '15 at 09:13

1 Answers1

2

It looks like peeskillet was right about needing some level of CDI.

I'll explain what I had to add, as it kind of jumps away from a lot of the instructions I found.

First, you need a CDI manager, weld is one of those so we need a dependency in our pom for that

<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet</artifactId>
    <version>2.2.15.Final</version>
</dependency>

It will also need a logging dependency, to avoid warnings or get any logging, so something like this will get the logs going to normal java util logging

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.7.12</version>
</dependency>

Only that isn't enough, as jersey apparently uses hk, not cdi so you need an adapter.

<dependency>
    <groupId>org.glassfish.jersey.containers.glassfish</groupId>
    <artifactId>jersey-gf-cdi</artifactId>
    <version>2.6</version>
</dependency>

Then that adapter seems to have a broken dependency so we need to add one more to avoid a two page stack trace each request.

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.2</version>
</dependency>

So now you have all the code in place, you need to do one last thing to make it actually work.

You need an empty WEB-INF/beans.xml. I don't quite follow why though.

Some sites also state that you need a META-INF/context.xml entry, but I didn't find I needed that, perhaps it is for injecting custom classes?

Hopefully this helps someone else

AntonPiatek
  • 823
  • 6
  • 11
  • I think you have to replace dependency with the artifactId "jersey-gf-cdi" with https://mvnrepository.com/artifact/org.glassfish.jersey.ext.cdi/jersey-cdi1x . Source: https://jersey.java.net/release-notes/2.15.html – Asker Jan 06 '17 at 15:01