Jersey 2 InjectLink is ignored
Asked Answered
R

2

6

I'm creating a new Jersey 2.21, Jackson 2.6.1 REST server (I tried with Jersey 2.19 and Jackson 2.5.3 as well) and a want to use @InjectLink to provide HATEOAS links (like 'self') for my callers. The most basic app (taken from Jersey doc and Jersey sample apps) isn't working, and I can't figure out why.

I started by taking the basic Widgets class from the Jersey doc, but the JSON or XML returned is just an empty structure.

XML:

<Widgets/>

JSON:

{}

Widgets.java

package org.glassfish.jersey.examples.linking;

import java.net.URI;
import java.util.List;

import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlRootElement;

import org.glassfish.jersey.linking.InjectLink;
import org.glassfish.jersey.linking.InjectLinks;

@XmlRootElement()
public class Widgets {
    @InjectLink(resource=WidgetsResource.class)
    URI u;

    @InjectLinks({@InjectLink(resource=WidgetsResource.class, rel = "self")})
    List<Link> links;

    public Widgets() {}
}

I put a breakpoint in the resource code and examined the object being returned. it.links and it.u are both null. There's nothing injected.

WidgetsResource.java

@Path("widgets")
public class WidgetsResource {
    @GET
    public Widgets get() {
        Widgets it = new Widgets();
        return it;
    }
}

Maven dependencies:

<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-declarative-linking</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>2.2.4</version>
    </dependency>
    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>2.2.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-joda</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-xml-provider</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-yaml-provider</artifactId>
        <version>${jackson.version}</version>
    </dependency>
</dependencies>

<properties>
    <jersey.version>2.21</jersey.version>
    <jackson.version>2.6.1</jackson.version>
</properties>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">
    <display-name>Server</display-name>
    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    </welcome-file-list>

    <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>org.glassfish.jersey.examples.linking.Server</param-value>
    </init-param>
    </servlet>

    <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/v1/*</url-pattern>
    </servlet-mapping>

</web-app>

The application object:

package org.glassfish.jersey.examples.linking;

import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class Server extends ResourceConfig {
    public Server() {
        packages("org.glassfish.jersey.examples.linking",
            "com.fasterxml.jackson.jaxrs")
        .register(DeclarativeLinkingFeature.class);
    }
}

It appears that the @InjectLink(s) annotations are simply being ignored. There must be some magic setting I'm missing, but I've done everything the Jersey doc says to do.

I tried with both Servlet 2.x (shown) and Servlet 3.x (using @ApplicationPath) and that made no difference.

Some of you will notice from my package names that I also tried the slightly more advanced, but no more successful, Jersey declarative linking example (https://github.com/jersey/jersey/tree/master/examples/declarative-linking). Some of the basic fields were returned, but all of the injected links were missing or null.

.../Server/rest/v1/items/1 produced:

{
  "id": "1",
  "nextId": "2",
  "prevId": "0",
  "prev": true,
  "next": true
}

FYI - I'm running Java 1.8.0_60, Eclipse Mars, and Tomcat 8.0.26. There are no errors, no warnings and no runtime messages. I'm completely stumped. Anyone have any pointers???

Reptilian answered 31/8, 2015 at 2:49 Comment(0)
C
2

I have added the following to my servlet config:

`<init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>
            org.glassfish.jersey.linking.DeclarativeLinkingFeature
        </param-value>
    </init-param>'

and the links were rendered in the json response.

Currie answered 19/2, 2016 at 13:50 Comment(0)
S
2

For information, if you do not want to use web.xml config file, you can do that:

import javax.ws.rs.ApplicationPath;

import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("rest/v1")
public class MyApp extends ResourceConfig {

    public MyApp () {
        packages("the.package.where.your.services.are.located")
            .register(DeclarativeLinkingFeature.class);
    }
}
Sevenup answered 4/10, 2016 at 12:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.