Rest services enable Classpath scanning, and is controlled through the RESTContext
class.
Apache CXF is used to expose the REST sevice
<dependency> <groupId>com.guicedee.servlets</groupId> <artifactId>guiced-rest-services</artifactId> </dependency>
requires com.guicedee.guicedservlets.rest; opens my.package.rest to com.google.guice, org.apache.cxf;
RESTContext.baseWSUrl = "/rest"; RESTContext.autoRegisterProviders = true; //be careful, there are a lot of default providers
@Path("/test") @Produces({"application/json"}) @Consumes({"application/json"}) public class AccessAPI { @POST public Response ping(String pong) { return Response.ok(); } }Ok now we have a rest endpoint available at "http://xxx/rest/test" that accepts a call on the POST method,
Let's turn off auto register providers, because that set way more than what we need and build bottom up.
First, we want to use
Jackson JSON
to handle our JSON requests. We need to register the provider after we add a module compatible version (2.10.2 and up)
RESTContext.getProviders() .add(JacksonJsonProvider.class.getCanonicalName());Ok that's great, now lets make sure it can handle XML requests by adding the Jackson JAXB addon,
RESTContext.getProviders() .add(JacksonJaxbJsonProvider.class.getCanonicalName());We want bean validation, and we want bean validation to fire on parameters coming in
RESTContext.getInInterceptors() .add(JAXRSBeanValidationInInterceptor.class.getCanonicalName()); RESTContext.getProviders() .add(JAXRSBeanValidationInvoker.class.getCanonicalName());We want to be able to see the parameter names in our rest services,
RESTContext.getProviders() .add(JAXRSParameterNameProvider.class.getCanonicalName());
Right. Now, we want to make sure that we can wrap all exceptions and have an exception mapper build errored responses (thrown exceptions)
RESTContext.getProviders() .add(my.package.rest.ExceptionResponseMapper.class.getCanonicalName());
public class MyExceptionResponseMapper implements ExceptionMapper<MyException> { @Override public Response toResponse(MyException exception) { Response.status(INTERNAL_SERVER_ERROR) .header("exception", exception.getClass().getCanonicalName()) .header("stacktrace", ExceptionUtils.getStackTrace(exception)) .entity(new ErrorData(exception.getError()) .build(); } }And that's a basic Rest service. Of course all features from Apache CXF are enabled, and you can use them in any order.
All of the providers packaged with the cxf-bundle in maven are available for use. This is why auto registering them is a bit dangerous.
Below is a basic test case using JDK 11 native for a rest service
@Test void configureServlets() throws Exception { GuiceContext.instance().loadIGuiceModules() .add(new RestTestBinding()); Undertow undertow = GuicedUndertow.boot("0.0.0.0", 6003); HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.of(5, ChronoUnit.SECONDS)) .build(); HttpResponse response = client.send(HttpRequest.newBuilder() .GET() .uri(new URI("http://localhost:6003/rest/hello/world")) .build() ,HttpResponse.BodyHandlers.discarding()); assertEquals(200, response.statusCode()); response = client.send(HttpRequest.newBuilder() .GET() .uri(new URI("http://localhost:6003/rest/hello/helloObject/world")) .build() ,HttpResponse.BodyHandlers.discarding()); assertEquals(200, response.statusCode()); undertow.stop(); }
A list of all providers in the base CXF module
org.apache.cxf.jaxrs.client.cache.CacheControlFeature org.apache.cxf.jaxrs.ext.search.QueryContextProvider org.apache.cxf.jaxrs.ext.search.SearchContextProvider org.apache.cxf.jaxrs.nio.NioMessageBodyWriter org.apache.cxf.jaxrs.provider.AbstractCachingMessageProvider org.apache.cxf.jaxrs.provider.CachingMessageBodyReader org.apache.cxf.jaxrs.provider.CachingMessageBodyWriter org.apache.cxf.jaxrs.provider.DataBindingProvider org.apache.cxf.jaxrs.provider.DataSourceProvider org.apache.cxf.jaxrs.provider.FormEncodingProvider org.apache.cxf.jaxrs.provider.JAXBElementProvider org.apache.cxf.jaxrs.provider.JavaTimeTypesParamConverterProvider org.apache.cxf.jaxrs.provider.MultipartProvider org.apache.cxf.jaxrs.provider.SourceProvider org.apache.cxf.jaxrs.provider.XPathProvider org.apache.cxf.jaxrs.provider.XSLTJaxbProvider org.apache.cxf.jaxrs.provider.aegis.AegisElementProvider org.apache.cxf.jaxrs.provider.atom.AtomEntryProvider org.apache.cxf.jaxrs.provider.atom.AtomFeedProvider org.apache.cxf.jaxrs.provider.atom.AtomPojoProvider org.apache.cxf.jaxrs.provider.json.JSONProvider org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider org.apache.cxf.jaxrs.sse.OutboundSseEventBodyWriter org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor org.apache.cxf.jaxrs.validation.JAXRSBeanValidationOutInterceptor org.apache.cxf.jaxrs.validation.ValidationExceptionMapper org.apache.cxf.rs.security.oauth.filters.OAuthRequestFilter org.apache.cxf.rs.security.oauth.services.OOBResponseProvider org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter org.apache.cxf.rs.security.oauth2.provider.OAuthContextProvider org.apache.cxf.rs.security.oauth2.provider.OAuthJSONProvider