From f3d76237f961a37b6b3b8c3d7f0ca75a63100cd3 Mon Sep 17 00:00:00 2001 From: Ben Hale Date: Sat, 4 Nov 2017 10:15:39 -0700 Subject: [PATCH] Shrink Cloud Foundry Connector Footprint Previously, the Cloud Foundry Connector utilized Jackson for parsing the VCAP_SERVICES JSON payload. While Jackson should be the default choice for most JSON parsing, the fact that the project does not need Object binding means that it is overkill for the need. In addition, since whichever JSON parser is chosen must be included in the distributable JAR and not shared with the rest of the application (which is likely to have its own version of Jackson) the size of the Jackson libraries becomes a significant concern. This change updates the code to use the org.json:json parser and shrinks the spring-cloud-cloudfoundry-connector from 1.2M to 84K with no difference in functionality. [resolves #73] --- spring-cloud-cloudfoundry-connector/build.gradle | 9 ++++----- .../cloud/cloudfoundry/CloudFoundryConnector.java | 13 +++++++------ .../AbstractCloudFoundryConnectorTest.java | 7 ++----- .../CassandraServiceInfoCreatorTests.java | 7 ++----- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/build.gradle b/spring-cloud-cloudfoundry-connector/build.gradle index e11a248..5624504 100644 --- a/spring-cloud-cloudfoundry-connector/build.gradle +++ b/spring-cloud-cloudfoundry-connector/build.gradle @@ -13,21 +13,20 @@ apply plugin: 'com.github.johnrengelman.shadow' apply from: "publish-maven.gradle" ext { - jacksonVersion = "2.3.3" + jsonVersion = "20171018" } dependencies { compile project(':spring-cloud-connectors-core') - compile("com.fasterxml.jackson.core:jackson-core:$jacksonVersion") - compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") + compile("org.json:json:$jsonVersion") } shadowJar { classifier = null dependencies { - include dependency('com.fasterxml.jackson.core:jackson-.*') + include dependency('org.json:json') } - relocate 'com.fasterxml.jackson', 'org.springframework.cloud.cloudfoundry.com.fasterxml.jackson' + relocate 'org.json', 'org.springframework.cloud.cloudfoundry.org.json' } assemble.dependsOn shadowJar diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryConnector.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryConnector.java index 4b64522..232bb40 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryConnector.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/CloudFoundryConnector.java @@ -4,7 +4,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.json.JSONObject; import org.springframework.cloud.AbstractCloudConnector; import org.springframework.cloud.CloudException; import org.springframework.cloud.FallbackServiceInfoCreator; @@ -12,8 +15,6 @@ import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; import org.springframework.cloud.util.EnvironmentAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * * @author Ramnivas Laddad @@ -21,7 +22,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; */ public class CloudFoundryConnector extends AbstractCloudConnector> { - private ObjectMapper objectMapper = new ObjectMapper(); private EnvironmentAccessor environment = new EnvironmentAccessor(); private ApplicationInstanceInfoCreator applicationInstanceInfoCreator = new ApplicationInstanceInfoCreator(); @@ -43,8 +43,8 @@ public class CloudFoundryConnector extends AbstractCloudConnector rawApplicationInstanceInfo - = objectMapper.readValue(environment.getEnvValue("VCAP_APPLICATION"), Map.class); + Map rawApplicationInstanceInfo + = new JSONObject(environment.getEnvValue("VCAP_APPLICATION")).toMap(); return applicationInstanceInfoCreator.createApplicationInstanceInfo(rawApplicationInstanceInfo); } catch (Exception e) { throw new CloudException(e); @@ -71,7 +71,8 @@ public class CloudFoundryConnector extends AbstractCloudConnector 0) { try { - rawServices = objectMapper.readValue(servicesString, CloudFoundryRawServiceData.class); + rawServices = new CloudFoundryRawServiceData(new JSONObject(servicesString).toMap().entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> (List>) entry.getValue()))); } catch (Exception e) { throw new CloudException(e); } diff --git a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorTest.java b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorTest.java index c1b3cb2..b7da29f 100644 --- a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorTest.java +++ b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorTest.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Scanner; +import org.json.JSONObject; import org.junit.Before; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -15,8 +16,6 @@ import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.util.EnvironmentAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; - import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -36,8 +35,6 @@ public abstract class AbstractCloudFoundryConnectorTest { protected static final int port = 1234; protected static String username = "myuser"; protected static final String password = "mypass"; - - private static ObjectMapper objectMapper = new ObjectMapper(); @Before public void setup() { @@ -116,7 +113,7 @@ public abstract class AbstractCloudFoundryConnectorTest { @SuppressWarnings("unchecked") private static String getServiceLabel(String servicePayload) { try { - Map serviceMap = objectMapper.readValue(servicePayload, Map.class); + Map serviceMap = new JSONObject(servicePayload).toMap(); return serviceMap.get("label").toString(); } catch (Exception e) { return null; diff --git a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/CassandraServiceInfoCreatorTests.java b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/CassandraServiceInfoCreatorTests.java index 948cffa..f45320b 100644 --- a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/CassandraServiceInfoCreatorTests.java +++ b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/CassandraServiceInfoCreatorTests.java @@ -22,11 +22,10 @@ import static org.junit.Assert.*; import java.util.List; import java.util.Map; +import org.json.JSONObject; import org.junit.Test; import org.springframework.cloud.service.common.CassandraServiceInfo; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * Unit tests for link {@link CassandraServiceInfoCreator}. * @@ -34,8 +33,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; */ public class CassandraServiceInfoCreatorTests extends AbstractCloudFoundryConnectorTest { - private ObjectMapper mapper = new ObjectMapper(); - @Test public void shouldCreateServiceInfo() throws Exception { @@ -91,7 +88,7 @@ public class CassandraServiceInfoCreatorTests extends AbstractCloudFoundryConnec } private Map readServiceData(String resource) throws java.io.IOException { - return mapper.readValue(readTestDataFile(resource), Map.class); + return new JSONObject(readTestDataFile(resource)).toMap(); } @SuppressWarnings("unchecked")