Reputation: 753
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,
ResourceConfig
and do a registerClasses(MyImplementation.class)
. However, this doesn't work.web.xml
, create a custom javax.ws.rs.Application
and do a register
of your implementation from there. Doesn't work.ResourceConfig
and define a custom AbstractBinder
and do a bind
so that Jersey's dependency injection can find the concrete implementations. Doesn't work.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
Upvotes: 12
Views: 6479
Reputation: 73
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.
Upvotes: 2
Reputation: 977
In Jersey,We should Put the class level @Path on the implementation instead of the interface.
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;
@Path("/hello")
public class MyResourceImpl implements MyResource {
@Override
public String sayHello() {
return "Hello Jersey";
}
}
Upvotes: 2