Skip to content

Commit

Permalink
Replace spread out ObjectMapper creation with shared singleton
Browse files Browse the repository at this point in the history
  • Loading branch information
tgianos committed Jan 17, 2018
1 parent 238514d commit 4b1a0a2
Show file tree
Hide file tree
Showing 36 changed files with 239 additions and 236 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@
*/
package com.netflix.genie.client;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.netflix.genie.client.configs.GenieNetworkConfiguration;
import com.netflix.genie.client.exceptions.GenieClientException;
import com.netflix.genie.client.interceptors.ResponseMappingInterceptor;
import com.netflix.genie.common.util.GenieDateFormat;
import com.netflix.genie.common.util.GenieObjectMapper;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -35,7 +32,6 @@
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

/**
Expand All @@ -47,7 +43,6 @@
abstract class BaseGenieClient {

private Retrofit retrofit;
private ObjectMapper mapper;

/**
* Constructor that takes the service url and a security interceptor implementation.
Expand All @@ -73,12 +68,6 @@ abstract class BaseGenieClient {
this.addConfigParamsFromConfig(builder, genieNetworkConfiguration);
}

this.mapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setDateFormat(new GenieDateFormat())
.setTimeZone(TimeZone.getTimeZone("UTC"))
.registerModule(new Jdk8Module());

// Add the interceptor to map the retrofit response code to corresponding Genie Exceptions in case of
// 4xx and 5xx errors.
builder.addInterceptor(new ResponseMappingInterceptor());
Expand All @@ -89,7 +78,7 @@ abstract class BaseGenieClient {

this.retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(JacksonConverterFactory.create(this.mapper))
.addConverterFactory(JacksonConverterFactory.create(GenieObjectMapper.getMapper()))
.client(client)
.build();
}
Expand Down Expand Up @@ -129,6 +118,6 @@ <T> T getService(final Class<T> clazz) {
}

<T> T treeToValue(final JsonNode node, final Class<T> clazz) throws IOException {
return this.mapper.treeToValue(node, clazz);
return GenieObjectMapper.getMapper().treeToValue(node, clazz);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.genie.client.exceptions.GenieClientException;
import com.netflix.genie.common.util.GenieObjectMapper;
import okhttp3.Interceptor;
import okhttp3.Response;
import okhttp3.ResponseBody;
Expand All @@ -38,13 +38,11 @@ public class ResponseMappingInterceptor implements Interceptor {

private static final String EMPTY_STRING = "";
private static final String ERROR_MESSAGE_KEY = "message";
private final ObjectMapper mapper;

/**
* Constructor.
*/
public ResponseMappingInterceptor() {
this.mapper = new ObjectMapper();
}

/**
Expand All @@ -63,7 +61,7 @@ public Response intercept(final Chain chain) throws IOException {

if (bodyReader != null) {
try {
final JsonNode responseBody = this.mapper.readTree(bodyReader);
final JsonNode responseBody = GenieObjectMapper.getMapper().readTree(bodyReader);
final String errorMessage =
responseBody == null || !responseBody.has(ERROR_MESSAGE_KEY)
? EMPTY_STRING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.netflix.genie.common.dto.Application;
import com.netflix.genie.common.dto.ApplicationStatus;
import com.netflix.genie.common.dto.Command;
import com.netflix.genie.common.util.GenieObjectMapper;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -439,7 +440,7 @@ public void testApplicationDependenciesMethods() throws Exception {
*/
@Test
public void testApplicationPatchMethod() throws Exception {
final ObjectMapper mapper = new ObjectMapper();
final ObjectMapper mapper = GenieObjectMapper.getMapper();
final String newName = UUID.randomUUID().toString();
final String patchString = "[{ \"op\": \"replace\", \"path\": \"/name\", \"value\": \"" + newName + "\" }]";
final JsonPatch patch = JsonPatch.fromJson(mapper.readTree(patchString));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.netflix.genie.common.dto.ClusterStatus;
import com.netflix.genie.common.dto.Command;
import com.netflix.genie.common.dto.CommandStatus;
import com.netflix.genie.common.util.GenieObjectMapper;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -521,7 +522,7 @@ public void testClusterCommandsMethods() throws Exception {
*/
@Test
public void testClusterPatchMethod() throws Exception {
final ObjectMapper mapper = new ObjectMapper();
final ObjectMapper mapper = GenieObjectMapper.getMapper();
final String newName = UUID.randomUUID().toString();
final String patchString = "[{ \"op\": \"replace\", \"path\": \"/name\", \"value\": \"" + newName + "\" }]";
final JsonPatch patch = JsonPatch.fromJson(mapper.readTree(patchString));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.netflix.genie.common.dto.Cluster;
import com.netflix.genie.common.dto.Command;
import com.netflix.genie.common.dto.CommandStatus;
import com.netflix.genie.common.util.GenieObjectMapper;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand Down Expand Up @@ -521,7 +522,7 @@ public void testCommandApplicationsMethods() throws Exception {
*/
@Test
public void testCommandPatchMethod() throws Exception {
final ObjectMapper mapper = new ObjectMapper();
final ObjectMapper mapper = GenieObjectMapper.getMapper();
final String newName = UUID.randomUUID().toString();
final String patchString = "[{ \"op\": \"replace\", \"path\": \"/name\", \"value\": \"" + newName + "\" }]";
final JsonPatch patch = JsonPatch.fromJson(mapper.readTree(patchString));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
package com.netflix.genie.common.dto;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.netflix.genie.common.util.GenieDateFormat;
import com.netflix.genie.common.util.GenieObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.Getter;

Expand All @@ -40,16 +38,8 @@
@Getter
@EqualsAndHashCode(of = "id", doNotUseGetters = true)
public abstract class BaseDTO implements Serializable {

static final ObjectMapper MAPPER;
private static final long serialVersionUID = 9093424855934127120L;

static {
final DateFormat iso8601 = new GenieDateFormat();
iso8601.setTimeZone(TimeZone.getTimeZone("UTC"));
MAPPER = new ObjectMapper().registerModule(new Jdk8Module()).setDateFormat(iso8601);
}

@Size(max = 255, message = "Max length for the ID is 255 characters")
private final String id;
private final Date created;
Expand Down Expand Up @@ -109,7 +99,7 @@ public Optional<Date> getUpdated() {
@Override
public String toString() {
try {
return MAPPER.writeValueAsString(this);
return GenieObjectMapper.getMapper().writeValueAsString(this);
} catch (final JsonProcessingException ioe) {
return ioe.getLocalizedMessage();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableSet;
import com.netflix.genie.common.exceptions.GeniePreconditionException;
import com.netflix.genie.common.util.GenieObjectMapper;
import lombok.Getter;
import org.hibernate.validator.constraints.NotEmpty;

Expand Down Expand Up @@ -166,7 +167,7 @@ public T withMetadata(@Nullable final String metadata) throws GeniePreconditionE
this.bMetadata = null;
} else {
try {
this.bMetadata = MAPPER.readTree(metadata);
this.bMetadata = GenieObjectMapper.getMapper().readTree(metadata);
} catch (final IOException ioe) {
throw new GeniePreconditionException("Invalid JSON string passed in " + metadata, ioe);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.netflix.genie.common.util.GenieObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.hibernate.validator.constraints.NotBlank;

import java.io.Serializable;
import java.text.DateFormat;
import java.util.TimeZone;

/**
* Base class for search results containing common fields.
Expand All @@ -42,13 +38,6 @@
public class BaseSearchResult implements Serializable {

private static final long serialVersionUID = -273035797399359914L;
private static final ObjectMapper MAPPER;

static {
final DateFormat iso8601 = new ISO8601DateFormat();
iso8601.setTimeZone(TimeZone.getTimeZone("UTC"));
MAPPER = new ObjectMapper().registerModule(new Jdk8Module()).setDateFormat(iso8601);
}

private final String id;
private final String name;
Expand All @@ -62,7 +51,7 @@ public class BaseSearchResult implements Serializable {
* @param user The user who created the object.
*/
@JsonCreator
public BaseSearchResult(
BaseSearchResult(
@NotBlank @JsonProperty("id") final String id,
@NotBlank @JsonProperty("name") final String name,
@NotBlank @JsonProperty("user") final String user
Expand All @@ -80,7 +69,7 @@ public BaseSearchResult(
@Override
public String toString() {
try {
return MAPPER.writeValueAsString(this);
return GenieObjectMapper.getMapper().writeValueAsString(this);
} catch (final JsonProcessingException ioe) {
return ioe.getLocalizedMessage();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
*
* Copyright 2018 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.genie.common.util;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.time.ZoneId;
import java.util.TimeZone;

/**
* A singleton for sharing a Jackson Object Mapper instance across Genie and not having to redefine the Object Mapper
* everywhere.
*
* @author tgianos
* @since 4.0.0
*/
public final class GenieObjectMapper {

private static final ObjectMapper MAPPER = new ObjectMapper()
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.setTimeZone(TimeZone.getTimeZone(ZoneId.of("UTC")));

private GenieObjectMapper() {
}

/**
* Get the preconfigured Object Mapper used across Genie for consistency.
*
* @return The object mapper to use
*/
public static ObjectMapper getMapper() {
return MAPPER;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.genie.common.exceptions.GenieException;
import com.netflix.genie.common.exceptions.GenieServerException;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -49,8 +48,7 @@ protected JsonUtils() {
*/
public static String marshall(final Object value) throws GenieException {
try {
final ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(value);
return GenieObjectMapper.getMapper().writeValueAsString(value);
} catch (final JsonProcessingException jpe) {
throw new GenieServerException("Failed to marshall object", jpe);
}
Expand All @@ -70,11 +68,10 @@ public static <T extends Collection> T unmarshall(
final TypeReference<T> typeReference
) throws GenieException {
try {
final ObjectMapper mapper = new ObjectMapper();
if (StringUtils.isNotBlank(source)) {
return mapper.readValue(source, typeReference);
return GenieObjectMapper.getMapper().readValue(source, typeReference);
} else {
return mapper.readValue("[]", typeReference);
return GenieObjectMapper.getMapper().readValue("[]", typeReference);
}
} catch (final IOException ioe) {
throw new GenieServerException("Failed to read JSON value", ioe);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import com.netflix.genie.common.exceptions.GeniePreconditionException;
import com.netflix.genie.common.util.GenieObjectMapper;
import com.netflix.genie.test.categories.UnitTest;
import com.netflix.genie.test.suppliers.RandomSuppliers;
import org.hamcrest.Matchers;
Expand Down Expand Up @@ -133,7 +134,7 @@ public void canBuildApplicationWithOptionals() {
*/
@Test
public void canBuildWithMetadata() throws IOException, GeniePreconditionException {
final ObjectMapper objectMapper = new ObjectMapper();
final ObjectMapper objectMapper = GenieObjectMapper.getMapper();
final String metadata = "{\"key1\":\"value1\",\"key2\":3}";
final JsonNode metadataNode = objectMapper.readTree(metadata);
final Application.Builder builder = new Application.Builder(NAME, USER, VERSION, ApplicationStatus.ACTIVE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package com.netflix.genie.common.dto;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.genie.common.util.GenieObjectMapper;
import com.netflix.genie.test.categories.UnitTest;
import org.junit.Assert;
import org.junit.Test;
Expand Down Expand Up @@ -49,8 +49,7 @@ public void canCreateValidJsonString() {

final String json = application.toString();
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(json);
GenieObjectMapper.getMapper().readTree(json);
} catch (final IOException ioe) {
Assert.fail();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package com.netflix.genie.common.dto.search;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.genie.common.util.GenieObjectMapper;
import com.netflix.genie.test.categories.UnitTest;
import org.hamcrest.Matchers;
import org.junit.Assert;
Expand Down Expand Up @@ -104,8 +104,7 @@ public void canCreateValidJsonString() {

final String json = searchResult.toString();
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(json);
GenieObjectMapper.getMapper().readTree(json);
} catch (final IOException ioe) {
Assert.fail();
}
Expand Down
Loading

0 comments on commit 4b1a0a2

Please sign in to comment.