From 7d2ce54690a031d7d9292fc1db1bfb408dc0ed97 Mon Sep 17 00:00:00 2001 From: "Heitor Araujo [DATACOM]" Date: Tue, 7 Nov 2017 09:37:18 +1300 Subject: [PATCH 1/2] adding insert nested records feature https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_sobject_tree_create.htm --- src/main/java/com/force/api/ForceApi.java | 33 ++++++++- src/main/java/com/force/api/NestedRecord.java | 63 +++++++++++++++++ .../com/force/api/NestedRecordRequest.java | 48 +++++++++++++ .../java/com/force/api/NestedResponse.java | 70 +++++++++++++++++++ .../java/com/force/api/http/HttpRequest.java | 2 +- .../java/com/force/api/NestedAccount.java | 42 +++++++++++ .../java/com/force/api/NestedContact.java | 33 +++++++++ .../java/com/force/api/NestedRecordTest.java | 65 +++++++++++++++++ 8 files changed, 352 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/force/api/NestedRecord.java create mode 100644 src/main/java/com/force/api/NestedRecordRequest.java create mode 100644 src/main/java/com/force/api/NestedResponse.java create mode 100644 src/test/java/com/force/api/NestedAccount.java create mode 100644 src/test/java/com/force/api/NestedContact.java create mode 100644 src/test/java/com/force/api/NestedRecordTest.java diff --git a/src/main/java/com/force/api/ForceApi.java b/src/main/java/com/force/api/ForceApi.java index d91932b..2a60b2b 100644 --- a/src/main/java/com/force/api/ForceApi.java +++ b/src/main/java/com/force/api/ForceApi.java @@ -4,7 +4,6 @@ import com.force.api.http.HttpRequest; import com.force.api.http.HttpResponse; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; @@ -416,11 +415,39 @@ public DescribeSObject describeSObject(String sobject) { throw new ResourceException(e); } } - + + /** + * Create nested objects + * ex: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_sobject_tree_create.htm + * + * @param nestedRecordRequest Nested recursive object to be included + * @return NestedResponse + */ + public NestedResponse insertNestedObjects(NestedRecordRequest nestedRecordRequest){ + + try { + return jsonMapper.readValue( + apiRequest( + new HttpRequest() + .url(uriBase() + "/composite/tree/" + nestedRecordRequest.getObjectApiName() ) + .method("POST") + .header("Accept", "application/json") + .header("Content-Type", "application/json") + .content(jsonMapper.writeValueAsBytes(nestedRecordRequest)) + ) + .getStream(), + NestedResponse.class); + + } catch (IOException e) { + throw new ResourceException(e); + } + + } + private final String uriBase() { return(session.getApiEndpoint()+"/services/data/"+config.getApiVersionString()); } - + private final HttpResponse apiRequest(HttpRequest req) { req.setAuthorization("Bearer "+session.getAccessToken()); req.setRequestTimeout(this.config.getRequestTimeout()); diff --git a/src/main/java/com/force/api/NestedRecord.java b/src/main/java/com/force/api/NestedRecord.java new file mode 100644 index 0000000..26da6a9 --- /dev/null +++ b/src/main/java/com/force/api/NestedRecord.java @@ -0,0 +1,63 @@ +package com.force.api; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; + +public class NestedRecord { + + @JsonProperty(value = "attributes") + protected Attribute attribute; + +// @JsonSerialize(keyUsing = KeyInnerNestedSerializer.class, contentUsing = InnerNestedSerializer.class) + private Map innerNestedRecordsByType; + + @JsonAnyGetter + public Map getInnerNestedRecordsByType() { + return innerNestedRecordsByType; + } + + @JsonAnySetter + public void setInnerNestedRecordsByType(Map innerNestedRecordsByType) { + this.innerNestedRecordsByType = innerNestedRecordsByType; + } + + public Attribute getAttribute() { + return attribute; + } + + public void setAttribute(Attribute attribute) { + this.attribute = attribute; + } + + public class Attribute{ + + private String type; + private String referenceId; + + public Attribute() { } + + public Attribute(String type, String referenceId){ + this.type = type; + this.referenceId = referenceId; + } + + public String getReferenceId() { + return referenceId; + } + + public void setReferenceId(String referenceId) { + this.referenceId = referenceId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + } +} diff --git a/src/main/java/com/force/api/NestedRecordRequest.java b/src/main/java/com/force/api/NestedRecordRequest.java new file mode 100644 index 0000000..e290cdf --- /dev/null +++ b/src/main/java/com/force/api/NestedRecordRequest.java @@ -0,0 +1,48 @@ +package com.force.api; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; + +public class NestedRecordRequest { + + @JsonProperty(value = "records") + private List records; + + @JsonIgnore + private String objectApiName; + + /** + * + * @param objectApiName Object API Name ex: Account, CustomObject__c + */ + public NestedRecordRequest(String objectApiName){ + this.records = new ArrayList(); + this.objectApiName = objectApiName; + } + + public NestedRecordRequest(String objectApiName, List records){ + this.records = records; + this.objectApiName = objectApiName; + } + + public NestedRecordRequest(String objectApiName, T t){ + this.records = new ArrayList(); + this.records.add(t); + this.objectApiName = objectApiName; + } + + public String getObjectApiName() { + return objectApiName; + } + + public List getRecords() { + return records; + } + + public void setRecords(List records) { + this.records = records; + } +} diff --git a/src/main/java/com/force/api/NestedResponse.java b/src/main/java/com/force/api/NestedResponse.java new file mode 100644 index 0000000..811ef04 --- /dev/null +++ b/src/main/java/com/force/api/NestedResponse.java @@ -0,0 +1,70 @@ +package com.force.api; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown=true) +public class NestedResponse { + + public NestedResponse(){} + + @JsonCreator + public NestedResponse(@JsonProperty("hasErrors") boolean hasErrors, @JsonProperty("results") List results){ + this.hasErrors = hasErrors; + this.results = results; + } + + @JsonProperty("hasErrors") private boolean hasErrors; + @JsonProperty("results") private List results; + + public boolean getHasErrors() { + return hasErrors; + } + + public void setHasErrors(boolean hasErrors) { + this.hasErrors = hasErrors; + } + + public List getResults() { + return results; + } + + public void setResults(List results) { + this.results = results; + } + + @JsonIgnoreProperties(ignoreUnknown=true) + static class Result{ + + public Result(){ } + + @JsonCreator + public Result(@JsonProperty("referenceId") String referenceId, @JsonProperty("id") String id){ + + this.referenceId = referenceId; + this.id = id; + } + + @JsonProperty("referenceId") private String referenceId; + @JsonProperty("id") private String id; + + public String getReferenceId() { + return referenceId; + } + + public void setReferenceId(String referenceId) { + this.referenceId = referenceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } +} diff --git a/src/main/java/com/force/api/http/HttpRequest.java b/src/main/java/com/force/api/http/HttpRequest.java index e99615b..56a5a55 100644 --- a/src/main/java/com/force/api/http/HttpRequest.java +++ b/src/main/java/com/force/api/http/HttpRequest.java @@ -17,7 +17,7 @@ static public HttpRequest formPost() { public enum ResponseFormat { STREAM, BYTE, STRING }; ResponseFormat responseFormat = ResponseFormat.STREAM; - + byte[] contentBytes; InputStream contentStream; diff --git a/src/test/java/com/force/api/NestedAccount.java b/src/test/java/com/force/api/NestedAccount.java new file mode 100644 index 0000000..597158c --- /dev/null +++ b/src/test/java/com/force/api/NestedAccount.java @@ -0,0 +1,42 @@ +package com.force.api; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class NestedAccount extends NestedRecord { + + @JsonProperty(value = "Name") + private String name; + + public NestedAccount(String refId){ + + this.attribute = new Attribute("Account", refId); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setContacts(List contacts){ + + Map innerNestedRecordsByType = getInnerNestedRecordsByType(); + if(innerNestedRecordsByType == null) + innerNestedRecordsByType = new HashMap(); + + NestedRecordRequest innerContacts = innerNestedRecordsByType.get("Contacts"); + if(innerContacts == null) + innerContacts = new NestedRecordRequest("Account"); + + innerContacts.setRecords(contacts); + innerNestedRecordsByType.put("Contacts", innerContacts); + setInnerNestedRecordsByType(innerNestedRecordsByType); + + } +} diff --git a/src/test/java/com/force/api/NestedContact.java b/src/test/java/com/force/api/NestedContact.java new file mode 100644 index 0000000..6765958 --- /dev/null +++ b/src/test/java/com/force/api/NestedContact.java @@ -0,0 +1,33 @@ +package com.force.api; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class NestedContact extends NestedRecord { + + @JsonProperty(value = "LastName") + private String lastName; + + @JsonProperty(value = "Email") + private String email; + + public NestedContact(String refId){ + + this.attribute = new NestedRecord.Attribute("Contact", refId); + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/src/test/java/com/force/api/NestedRecordTest.java b/src/test/java/com/force/api/NestedRecordTest.java new file mode 100644 index 0000000..9689157 --- /dev/null +++ b/src/test/java/com/force/api/NestedRecordTest.java @@ -0,0 +1,65 @@ +package com.force.api; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +public class NestedRecordTest { + + static ForceApi api = new ForceApi(new ApiConfig() + .setUsername(Fixture.get("username")) + .setPassword(Fixture.get("password")) + .setClientId(Fixture.get("clientId")) + .setClientSecret(Fixture.get("clientSecret"))); + + @Test + public void testInsert(){ + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); +// mapper.registerModule(module); + + NestedAccount acc = new NestedAccount("acc2"); + acc.setName("Acc 3"); + + NestedContact con1 = new NestedContact("con1"); + con1.setLastName("Con1"); + con1.setEmail("con1@nestedrecord.com"); + + NestedContact con2 = new NestedContact("con2"); + con2.setLastName("Con2"); + con2.setEmail("con2@nestedrecord.com"); + + List contacts = new ArrayList(); + contacts.add(con1); + contacts.add(con2); + + acc.setContacts(contacts); + + NestedContact con3 = new NestedContact("con3"); + con3.setLastName("Con3"); + con3.setEmail("con3@nestedrecord.com"); + + NestedRecordRequest nestedRequest = new NestedRecordRequest("Account"); + nestedRequest.getRecords().add(acc); +// nestedRequest.getRecords().add(con3); + + try { + System.out.println( mapper.writeValueAsString(nestedRequest) ); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + NestedResponse response = api.insertNestedObjects(nestedRequest); + assertTrue(response != null); +// ResourceRepresentation result = api.post("/composite/tree/Account/", nestedRequest); +// System.out.println(result.response.getString()); + } + +} From 63ed6c52ed6a14cad2438183cb88788c8441b99b Mon Sep 17 00:00:00 2001 From: "Heitor Araujo [DATACOM]" Date: Tue, 7 Nov 2017 09:42:55 +1300 Subject: [PATCH 2/2] removing commented code --- src/main/java/com/force/api/NestedRecord.java | 1 - src/test/java/com/force/api/NestedRecordTest.java | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/main/java/com/force/api/NestedRecord.java b/src/main/java/com/force/api/NestedRecord.java index 26da6a9..3995f77 100644 --- a/src/main/java/com/force/api/NestedRecord.java +++ b/src/main/java/com/force/api/NestedRecord.java @@ -11,7 +11,6 @@ public class NestedRecord { @JsonProperty(value = "attributes") protected Attribute attribute; -// @JsonSerialize(keyUsing = KeyInnerNestedSerializer.class, contentUsing = InnerNestedSerializer.class) private Map innerNestedRecordsByType; @JsonAnyGetter diff --git a/src/test/java/com/force/api/NestedRecordTest.java b/src/test/java/com/force/api/NestedRecordTest.java index 9689157..a743654 100644 --- a/src/test/java/com/force/api/NestedRecordTest.java +++ b/src/test/java/com/force/api/NestedRecordTest.java @@ -23,7 +23,6 @@ public void testInsert(){ ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); -// mapper.registerModule(module); NestedAccount acc = new NestedAccount("acc2"); acc.setName("Acc 3"); @@ -48,7 +47,6 @@ public void testInsert(){ NestedRecordRequest nestedRequest = new NestedRecordRequest("Account"); nestedRequest.getRecords().add(acc); -// nestedRequest.getRecords().add(con3); try { System.out.println( mapper.writeValueAsString(nestedRequest) ); @@ -58,8 +56,6 @@ public void testInsert(){ NestedResponse response = api.insertNestedObjects(nestedRequest); assertTrue(response != null); -// ResourceRepresentation result = api.post("/composite/tree/Account/", nestedRequest); -// System.out.println(result.response.getString()); } }