diff --git a/pom.xml b/pom.xml index 48bb769..3dd9af6 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ 5.7.2 5.2.14.RELEASE - 2.34 + 2.35 3.3.2 diff --git a/src/main/java/com/inteligr8/rs/Client.java b/src/main/java/com/inteligr8/rs/Client.java index 03d93d9..a607652 100644 --- a/src/main/java/com/inteligr8/rs/Client.java +++ b/src/main/java/com/inteligr8/rs/Client.java @@ -15,13 +15,21 @@ import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; */ public abstract class Client { + private final Object sync = new Object(); + private javax.ws.rs.client.Client client; + protected abstract ClientConfiguration getConfig(); /** * @return A pre-configured JAX-RS client (no URL) with configured authorization. */ public final javax.ws.rs.client.Client getClient() { - return this.getClient(null); + synchronized (this.sync) { + if (this.client == null) + this.client = this.buildClient(null); + } + + return this.client; } /** @@ -29,6 +37,18 @@ public abstract class Client { * @return A pre-configured JAX-RS client (no URL) with the specified authorization. */ public javax.ws.rs.client.Client getClient(AuthorizationFilter authFilter) { + if (authFilter == null) { + return this.getClient(); + } else { + return this.buildClient(authFilter); + } + } + + /** + * @param authFilter A dynamic authorization filter. + * @return A pre-configured JAX-RS client (no URL) with the specified authorization. + */ + public javax.ws.rs.client.Client buildClient(AuthorizationFilter authFilter) { JacksonJsonProvider provider = new JacksonJaxbJsonProvider(); if (this.getConfig().isWrapRootValueEnabled()) @@ -37,7 +57,8 @@ public abstract class Client { provider.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); ClientBuilder clientBuilder = ClientBuilder.newBuilder() - .register(provider); + .register(provider) + .register(new LoggingFilter()); if (authFilter == null) authFilter = this.getConfig().createAuthorizationFilter(); @@ -51,7 +72,8 @@ public abstract class Client { * @return A pre-configured JAX-RS target (client w/ base URL) with configured authorization. */ public final WebTarget getTarget() { - return this.getTarget(null); + return this.getClient() + .target(this.getConfig().getBaseUrl()); } /** @@ -59,8 +81,12 @@ public abstract class Client { * @return A pre-configured JAX-RS target (client w/ base URL) with the specified authorization. */ public WebTarget getTarget(AuthorizationFilter authFilter) { - return this.getClient(authFilter) - .target(this.getConfig().getBaseUrl()); + if (authFilter == null) { + return this.getTarget(); + } else { + return this.getClient(authFilter) + .target(this.getConfig().getBaseUrl()); + } } /** diff --git a/src/main/java/com/inteligr8/rs/LoggingFilter.java b/src/main/java/com/inteligr8/rs/LoggingFilter.java new file mode 100644 index 0000000..a0cf2f5 --- /dev/null +++ b/src/main/java/com/inteligr8/rs/LoggingFilter.java @@ -0,0 +1,54 @@ +package com.inteligr8.rs; + +import java.io.IOException; + +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.MediaType; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class LoggingFilter implements ClientRequestFilter, ClientResponseFilter { + + private final Logger loggerRequest = LoggerFactory.getLogger("jaxrs.request"); + private final Logger loggerResponse = LoggerFactory.getLogger("jaxrs.response"); + + private final ObjectMapper om = new ObjectMapper(); + + @Override + public void filter(ClientRequestContext requestContext) throws IOException { + if (this.loggerRequest.isTraceEnabled()) { + if (MediaType.APPLICATION_JSON_TYPE.equals(requestContext.getMediaType())) { + this.loggerRequest.trace("request: {} {}: {}", requestContext.getMethod(), requestContext.getUri(), + this.om.writeValueAsString(requestContext.getEntity())); + } else if (MediaType.APPLICATION_FORM_URLENCODED_TYPE.equals(requestContext.getMediaType())) { + if (requestContext.getEntity() instanceof Form) { + this.loggerRequest.trace("request: {} {}: {}", requestContext.getMethod(), requestContext.getUri(), + ((Form)requestContext.getEntity()).asMap()); + } else { + this.loggerRequest.trace("request: {} {}: failed to output form", requestContext.getMethod(), requestContext.getUri()); + } + } else if (requestContext.getMediaType() != null) { + this.loggerRequest.trace("request '{}': {} {}", requestContext.getMediaType(), requestContext.getMethod(), requestContext.getUri()); + } else { + this.loggerRequest.trace("request: {} {}", requestContext.getMethod(), requestContext.getUri()); + } + } + } + + @Override + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { + if (this.loggerResponse.isTraceEnabled()) { + this.loggerResponse.trace("response: {} ", this.om.writeValueAsString(responseContext.getStatus())); + // WARN body is stream, which would need to be replaced after read + this.loggerResponse.warn("response: NOT YET SUPPORTED"); + } + } + +}