Eliminate constructors with side-effects 55/95755/1
authorJim Hahn <jrh3@att.com>
Mon, 16 Sep 2019 15:38:20 +0000 (11:38 -0400)
committerJim Hahn <jrh3@att.com>
Mon, 16 Sep 2019 16:27:50 +0000 (12:27 -0400)
Several of the Gson and Jackson handlers take a GsonBuilder, which
they then configure with additional adapters prior to create a Gson
object that they subsequently use.  The code has been modified so
that the constructors no longer take a GsonBuilder, thus eliminating
the side-effects that they had on the builders.  Instead, a
configBuilder() method has been added to the handler classes that
makes it clear tht they modify the GsonBuilder.

This also has the advantage that classes that want a Gson object
configured per a given handler need only call that handler's
configBuilder() method; previously, they had to constructor the
handler and then retrieve its gson object.

Also updated a few tests to specify the HTTP "Accept" header to ensure
that return results are in yaml format.

Change-Id: I2ef98198041ff9f73913d01ee6ee14ecf20ba617
Issue-ID: POLICY-2081
Signed-off-by: Jim Hahn <jrh3@att.com>
gson/src/main/java/org/onap/policy/common/gson/GsonMessageBodyHandler.java
gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java
policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlJacksonHandler.java
policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/YamlMessageBodyHandler.java
policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java
policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestServerTest.java
utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java

index ad27091..37d2417 100644 (file)
@@ -37,6 +37,7 @@ import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Provider;
+import lombok.AccessLevel;
 import lombok.Getter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -54,7 +55,7 @@ public class GsonMessageBodyHandler implements MessageBodyReader<Object>, Messag
     /**
      * Object to be used to serialize and de-serialize.
      */
-    @Getter
+    @Getter(AccessLevel.PROTECTED)
     private final Gson gson;
 
     /**
@@ -62,17 +63,7 @@ public class GsonMessageBodyHandler implements MessageBodyReader<Object>, Messag
      * into Integer/Long, where possible.
      */
     public GsonMessageBodyHandler() {
-        this(new GsonBuilder());
-    }
-
-    /**
-     * Constructs the object, using a Gson object that translates Doubles inside of Maps
-     * into Integer/Long, where possible.
-     *
-     * @param builder builder to use to create the gson object
-     */
-    public GsonMessageBodyHandler(GsonBuilder builder) {
-        this(builder.registerTypeAdapterFactory(new MapDoubleAdapterFactory()).create());
+        this(configBuilder(new GsonBuilder()).create());
     }
 
     /**
@@ -86,6 +77,17 @@ public class GsonMessageBodyHandler implements MessageBodyReader<Object>, Messag
         logger.info("Using GSON for REST calls");
     }
 
+    /**
+     * Configures a builder with the adapters normally used by this handler (e.g., mapper
+     * that converts Double to Integer).
+     *
+     * @param builder builder to be configured
+     * @return the configured builder
+     */
+    public static GsonBuilder configBuilder(GsonBuilder builder) {
+        return builder.registerTypeAdapterFactory(new MapDoubleAdapterFactory());
+    }
+
     @Override
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return canHandle(mediaType);
index 6d94643..6df5ad2 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.policy.common.gson;
 
+import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,20 +37,30 @@ public class JacksonHandler extends GsonMessageBodyHandler {
      * Constructs the object.
      */
     public JacksonHandler() {
-        this(new GsonBuilder());
+        this(configBuilder(new GsonBuilder()).create());
+    }
 
+    /**
+     * Constructs the object.
+     *
+     * @param gson the Gson object to be used to serialize and de-serialize
+     */
+    public JacksonHandler(Gson gson) {
+        super(gson);
         logger.info("Using GSON with Jackson behaviors for REST calls");
     }
 
     /**
-     * Constructs the object.
-     * @param builder builder to use to create the gson object
+     * Configures a builder with the adapters normally used by this handler (e.g.,
+     * adapters for GsonJsonXxx annotations).
+     *
+     * @param builder builder to be configured
+     * @return the configured builder
      */
-    public JacksonHandler(GsonBuilder builder) {
-        super(builder
-                        .registerTypeAdapterFactory(new JacksonFieldAdapterFactory())
+    public static GsonBuilder configBuilder(GsonBuilder builder) {
+        return builder.registerTypeAdapterFactory(new JacksonFieldAdapterFactory())
                         .registerTypeAdapterFactory(new JacksonMethodAdapterFactory())
-                        .setExclusionStrategies(new JacksonExclusionStrategy()));
+                        .registerTypeAdapterFactory(new MapDoubleAdapterFactory())
+                        .setExclusionStrategies(new JacksonExclusionStrategy());
     }
-
 }
index 0cab374..f71aa90 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.policy.common.endpoints.http.server;
 
+import com.google.gson.GsonBuilder;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
@@ -40,7 +41,8 @@ public class YamlJacksonHandler extends YamlMessageBodyHandler {
      * Translator to be used. We want a GSON object that's configured the same way as it
      * is in {@link JacksonHandler}, so just get it from there.
      */
-    private static final YamlJsonTranslator TRANS = new YamlJsonTranslator(new JacksonHandler().getGson());
+    private static final YamlJsonTranslator TRANS =
+                    new YamlJsonTranslator(JacksonHandler.configBuilder(new GsonBuilder()).create());
 
     /**
      * Constructs the object.
index 89aa8ff..8506a28 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.policy.common.endpoints.http.server;
 
+import com.google.gson.GsonBuilder;
 import com.google.gson.JsonSyntaxException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -60,7 +61,7 @@ public class YamlMessageBodyHandler implements MessageBodyReader<Object>, Messag
      * from there.
      */
     private static final YamlJsonTranslator DEFAULT_TRANSLATOR =
-                    new YamlJsonTranslator(new GsonMessageBodyHandler().getGson());
+                    new YamlJsonTranslator(GsonMessageBodyHandler.configBuilder(new GsonBuilder()).create());
 
     private final YamlJsonTranslator translator;
 
index 6dee6f1..82faa05 100644 (file)
@@ -509,6 +509,7 @@ public class HttpServerTest {
         conn.setRequestMethod("POST");
         conn.setDoOutput(true);
         conn.setRequestProperty("Content-Type", mediaType);
+        conn.setRequestProperty("Accept", mediaType);
         IOUtils.write(post, conn.getOutputStream());
         return response(conn);
     }
index 519bbd1..959945b 100644 (file)
@@ -265,6 +265,7 @@ public class RestServerTest {
         String auth = params.getUserName() + ":" + params.getPassword();
         conn.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(auth.getBytes()));
         conn.setRequestProperty("Content-type", mediaType);
+        conn.setRequestProperty("Accept", mediaType);
         conn.connect();
 
         try (PrintWriter wtr = new PrintWriter(conn.getOutputStream())) {
index 1f697fd..dcf2775 100644 (file)
@@ -37,7 +37,7 @@ public class GsonTestUtilsBuilder {
         gsonBldr = new GsonBuilder();
 
         // register jackson behaviors with the builder
-        new JacksonHandler(gsonBldr);
+        JacksonHandler.configBuilder(gsonBldr);
     }
 
     /**