-
Notifications
You must be signed in to change notification settings - Fork 7
Features
Guice-CXF lets you use a EDSL to easily configure CXF JAX-RS module.
Extend the CXFModule
class to bind the needed classes and configure the server.
Use publish()
to register a resource class - a custom ResourceProvider
will be bound for each resource class.
It's a 'per-request' type and will get a new instance for each incoming request.
Use serve()
to configure server, e.g. set the root address.
The following methods let you register JAX-RS @Provider
s:
-
handleRequest()
- register aRequestHandler
; -
handleResponse()
- register aResponseHandler
; -
mapExceptions()
- register anExceptionMapper
; -
readBody()
- register aMessageBodyReader
; -
writeBody()
- register aMessageBodyWriter
; -
writeAndReadBody()
- register a class that is both aMessageBodyReader
and aMessageBodyWriter
(e.g.JAXBElementProvider
orJSONProvider
); -
provide()
- generic method to register any JAX-RS@Provider
, it's best to use specific methods if available, since they are type safe;
Please note that a single instance of each @Provider
class will be passed to the ServerFactoryBean
, regardless of the scope.
Use invokeVia()
to register custom invoker.
It is possible to bind concrete classes, but a very nice feature is the ability to bind interfaces.
protected void configureResources() {
publish(ResourceInterface.class);
}
Then in a separate module you can do something like
bind(ResourceInterface.class).to(ResourceImpl.class)
to define the concrete implementation. This let's you easily register mock objects for testing.
Another use of indirect binding is configuring the @Provider
s, see here an example configuration of the JSONProvider
.
@Provides
public JSONProvider provdeJsonProvider(@Named("ignoreNamespaces") boolean ignoreNamespaces) {
final JSONProvider json = new JSONProvider();
json.setIgnoreNamespaces(ignoreNamespaces);
return json;
}
Of course if you implement your own @Provider
s it's best to use constructor/method injections directly on them.
Since all resources and providers are created by Guice you can use all the usual bindings (remember to provide an @Inject
annotated constructor).
In addition you can use CXFScopes.REQUEST
scope (or Provider<T>
interface) to get access to bindings provided by Jax-Rs, or share your own classes inside a single request.
The available bindings are:
-
javax.ws.rs.core.HttpHeaders
; -
javax.ws.rs.core.Request
; -
javax.ws.rs.core.SecurityContext
; -
javax.ws.rs.core.UriInfo
; -
javax.ws.rs.ext.Providers
; -
org.apache.cxf.jaxrs.ext.MessageContext
; -
org.apache.cxf.message.Exchange
; -
org.apache.cxf.service.Service
;
You can register providers to bind any specific dependency you can extract from those classes too.
public class BookTitleResolver {
@Inject
private HttpHeaders headers;
public String resolveTitleFor(String id){
return getBook(id).getTitleForLanguage(headers.getLanguage());
}
// [...]
}
With guice-cxf you can have Guice construct subresource instances, completely with injecting them with appropriate dependencies.
First, you have to enable this feature
protected void configure() {
serve().atAddress("/rest").withSubresourcesInjection();
}
Then all you need to do is annotate the subresource locator method with @Injected annotation. The method must also be non-final.
@Path("foo");
public class LibraryResource {
// [...]
@Injected
@Path("{id}")
public BookResource getBook(@PathParam("id") String id){
throw new UnsupportedOperationException("will be implemented by Guice");
}
}
In one of modules you need to bind the declared class.
protected void configure(){
bind(BookResource.class).to(CachedBookResource.class).in(REQUEST);
// [...]
}
Guice will then take care of implementing the locator method for you, using AOP.
The server has to be started manually, this might be a bit cumbersome, however it will save you from running into this bug.
See the Bindings page for a list of resulting bindings.