Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to annotate JAX-RS on an interface while using Jersey

This question had been asked a few times before, however the answers doesn't seem to work and/or Jersey has moved on with more changes.

I'm exposing some REST APIs using JAX-RS and Jersey (version 2.24). And I wish to annotate the interface with JAX-RS and a concrete implementation (without any annotations). However, since this patch Jersey stopped supporting this possibility. As far as I understand the spec, it doesn't strictly prohibit doing that.

If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the superclass or interface method are ignored.

implying that it is totally okay to do that. In many cases it is good to use an interface, and have a server and client each have their respective implementations.

There are plenty of solutions out there,

  1. Use a ResourceConfig and do a registerClasses(MyImplementation.class) . However, this doesn't work.
  2. Disable the package scanning configuration in web.xml, create a custom javax.ws.rs.Application and do a register of your implementation from there. Doesn't work.
  3. use a ResourceConfig and define a custom AbstractBinder and do a bind so that Jersey's dependency injection can find the concrete implementations. Doesn't work.
  4. Use RESTEasy. RESTEasy doesn't seem to impose the interface restrictions as in Jersey. Never tried it myself.

I would appreciate if someone can share their experience with this. Any help on how to get Jersey working would be great too. As for the option (4) is it really necessary to switch ? A sample code below.

MyResource

 package com.foo;

import javax.ws.rs.GET;
import javax.ws.rs.Path;


@Path("/hello")
public interface MyResource {

  @GET
  public String sayHello();

}

MyResourceImpl

package com.bar;

public class MyResourceImpl implements MyResource {

  @Override
  public String sayHello() {
    return "Hello Jersey";
  }
}

Also have a web.xml that has the package scanning enabled to scan com.foo

like image 390
Alavalathi Avatar asked Nov 29 '16 22:11

Alavalathi


People also ask

Is JAX-RS and Jersey same?

The JAX-RS (JSR 311: The Java API for RESTful Web Services) specification provides a standardized Java-based approach to implementing REST-style web services. Jersey is the reference implementation of JAX-RS and I provide a brief introduction to JAX-RS via Jersey in this blog post.

Can we use annotation in interface?

Annotation gives you the ability to provide additional metadata alongside a Java entity (such as classes, interfaces, fields and methods). This additional metadata, called annotation, can be read and interrelated by the compiler or other utilities. They can also be stored in the class files.

Is Jersey implementation of JAX-RS?

Jersey RESTful Web Services framework is open source, production quality, framework for developing RESTful Web Services in Java that provides support for JAX-RS APIs and serves as a JAX-RS (JSR 311 & JSR 339) Reference Implementation. Jersey framework is more than the JAX-RS Reference Implementation.


1 Answers

If you want to separate Resource interface from implementation (allowing you to use the interface with some REST client like resteasy client) you can use @RequestScoped on the implementation. Thus, this bean could use injected resources like EJB, EntityManager, ... Using your sample :

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/hello")
public interface MyResource {

   @GET
   public String sayHello();
}

MyResourceImpl

package com.bar;

@RequestScoped
public class MyResourceImpl implements MyResource {

  @Override
  public String sayHello() {
    return "Hello Jersey";
  }
}

Nevertheless, you have to take into consideration that as soon as you use specific JAX-RS classes in your implementation code (like UriInfo, Response object, ...) you will create a coupling between your implementation and the JAX-RS API.

like image 154
Jérôme Blanchard Avatar answered Sep 21 '22 13:09

Jérôme Blanchard