JAX-RS - Resource Field Injection

[Updated: May 17, 2017, Created: May 17, 2017]

In previous tutorials, we saw JAX-RS annotation can be used with resource methods parameters and with constructor parameter as well. There's a third option which we should be aware of i.e. using those annotation on field/property levels; the JAX-RS runtime will automatically inject their corresponding values.

Field injection

Following example shows how to use field injection:

@Path("/")
public class MyResource {
  @Context
  UriInfo uriInfo;
  @PathParam("num")
  int pathNum;
  @QueryParam("q")
  String qValue;

  @GET
  @Path("/test{num:[1-9]{0,1}}")
  public String handleRequest() {
      URI uri = uriInfo.getRequestUri();
      return String.format(" response from: %s%n PathNum: %s%n query paramMyResource: %s%n",
              uri, pathNum, qValue);
  }
}

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run

Testing above resource with JAX-RS client:

public class MyClient {
  public static void main(String[] args) {
      Client client = ClientBuilder.newClient();
      WebTarget target = client.target("http://localhost:8080/test9");
      String response = target.queryParam("q", "testVal")
                              .request()
                              .get(String.class);
      System.out.println(response);
  }
}

Output

 response from: http://localhost:8080/test9?q=testVal
PathNum: 9
query param: testVal

Property Injection

@Path("/property/")
public class MyResource1 {
  UriInfo uriInfo;
  int pathNum;
  String myParam;

  @GET
  @Path("/test{num:[1-9]{0,1}}")
  public String handleRequest() {
      URI uri = uriInfo.getRequestUri();
      return String.format("response from: %s%nPathNum: %s%nmyParam: %s%n",
              uri, pathNum, myParam);
  }

  @Context
  public void setUriInfo(UriInfo uriInfo) {
      this.uriInfo = uriInfo;
  }

  @PathParam("num")
  public void setPathNum(int pathNum) {
      this.pathNum = pathNum;
  }

  @QueryParam("q")
  public void setMyParam(String myParam) {
      this.myParam = myParam;
  }
}
public class MyClient1 {
  public static void main(String[] args) {
      Client client = ClientBuilder.newClient();
      WebTarget target = client.target("http://localhost:8080/property/test5");
      String response = target.queryParam("q", "testVal")
                              .request()
                              .get(String.class);
      System.out.println(response);
  }
}

Output

response from: http://localhost:8080/property/test5?q=testVal
PathNum: 5
myParam: testVal

Note that on field/property level, we can use other features of JAX-RS in a same way we use them with the resource method parameters, for example we can use @Default annotation with @QueryParam etc.

Field/Property injection with singleton resources

Only @Context annotation is allowed on singleton resources:

@Path("/static/")
public class MyResource2 {
  @Context
  UriInfo uriInfo;

  @Context
  HttpHeaders headers;

  @GET
  @Path("/test2")
  public String handleRequest() {
      return String.format("handleRequest, path: %s, headers: %s%n",
              uriInfo.getPath(),
              headers.getRequestHeader("myHeader"));
  }

  @GET
  @Path("/test3")
  public String handleRequest2() {
      return String.format("handleRequest2, path: %s, headers: %s%n",
              uriInfo.getPath(),
              headers.getRequestHeader("myHeader2"));
  }
}
@ApplicationPath("/")
public class MyRestApp extends Application {
    .............
  @Override
  public Set<Object> getSingletons() {
      Set<Object> set = new HashSet<>();
      set.add(new MyResource2());
      return set;
  }
}
public class MyClient2 {
  public static void main(String[] args) {
      Client client = ClientBuilder.newClient();
      WebTarget target = client.target("http://localhost:8080/static/test2");
      String response = target.request().header("myHeader", "header-value")
                              .get(String.class);
      System.out.println(response);

      //second request
      target = client.target("http://localhost:8080/static/test3");
      response = target.request().header("myHeader2", "header-value2")
                       .get(String.class);
      System.out.println(response);
  }
}

Output

handleRequest, path: static/test2, headers: [header-value]

handleRequest2, path: static/test3, headers: [header-value2]

Attempting to use other annotations will end up with an exception during startup time:

@Path("/static/")
public class MyResource2 {
    .....
    @QueryParam("q")
    String qValue;
    .....
}

Output

java.lang.IllegalStateException: Not inside a request scope.
	at jersey.repackaged.com.google.common.base.Preconditions.checkState(Preconditions.java:173)
	at org.glassfish.jersey.process.internal.RequestScope.current(RequestScope.java:233)
   ....

Example Project

Dependencies and Technologies Used :

  • jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
  • JDK 1.8
  • Maven 3.3.9

Field Injection Examples Select All Download
  • jaxrs-field-injection
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also