CAMEL-8516: Fixed 300 status code exception handling, minor polish
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/865b7ffe Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/865b7ffe Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/865b7ffe Branch: refs/heads/camel-2.14.x Commit: 865b7ffea2ed21a5b661ec9fa2c6ee6a9a1d2c37 Parents: 7422cac Author: Dhiraj Bokde <dhira...@yahoo.com> Authored: Fri Mar 20 13:36:48 2015 -0700 Committer: Dhiraj Bokde <dhira...@yahoo.com> Committed: Fri Mar 20 13:43:50 2015 -0700 ---------------------------------------------------------------------- .../salesforce/SalesforceConsumer.java | 4 +- .../salesforce/api/SalesforceException.java | 44 ++++--- .../api/SalesforceMultipleChoicesException.java | 41 ++++++ .../salesforce/internal/SalesforceSession.java | 21 ++- .../internal/client/AbstractClientBase.java | 4 +- .../internal/client/DefaultBulkApiClient.java | 2 +- .../internal/client/DefaultRestClient.java | 68 +++++++--- .../salesforce/internal/dto/RestChoices.java | 40 ++++++ .../salesforce/RestApiIntegrationTest.java | 131 ++++++++++++++++++- 9 files changed, 296 insertions(+), 59 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java index b47f658..ac44d5a 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceConsumer.java @@ -141,8 +141,8 @@ public class SalesforceConsumer extends DefaultConsumer { // TODO do we need to add NPE checks for message/data.get***??? Map<String, Object> data = message.getDataAsMap(); - @SuppressWarnings("unchecked") final - Map<String, Object> event = (Map<String, Object>) data.get(EVENT_PROPERTY); + @SuppressWarnings("unchecked") + final Map<String, Object> event = (Map<String, Object>) data.get(EVENT_PROPERTY); final Object eventType = event.get(TYPE_PROPERTY); Object createdDate = event.get(CREATED_DATE_PROPERTY); if (log.isDebugEnabled()) { http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java index 4005ec4..dd25f0a 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java @@ -58,13 +58,13 @@ public class SalesforceException extends CamelException { } public SalesforceException(List<RestError> errors, int statusCode, String message, Throwable cause) { - super(toErrorMessage(errors, statusCode), cause); + super(message == null ? toErrorMessage(errors, statusCode) : message, cause); this.errors = errors; this.statusCode = statusCode; } public List<RestError> getErrors() { - return Collections.unmodifiableList(errors); + return errors != null ? Collections.unmodifiableList(errors) : null; } public int getStatusCode() { @@ -73,30 +73,42 @@ public class SalesforceException extends CamelException { @Override public String toString() { + final StringBuilder builder = new StringBuilder("{"); + appendFields(builder); + builder.append("}"); + return builder.toString(); + } + + protected void appendFields(StringBuilder builder) { + // append message + builder.append("message:'"); + builder.append(getMessage()); + builder.append("',"); + + // check for error if (errors != null) { - return toErrorMessage(errors, statusCode); - } else { - // make sure we include the custom message - final StringBuilder builder = new StringBuilder("{ "); - builder.append(getMessage()); - builder.append(", statusCode: "); - builder.append(statusCode); - builder.append("}"); - - return builder.toString(); + builder.append("errors:["); + for (RestError error : errors) { + builder.append(error.toString()); + } + builder.append("],"); + } + // append statusCode + builder.append("statusCode:"); + builder.append(statusCode); } private static String toErrorMessage(List<RestError> errors, int statusCode) { - StringBuilder builder = new StringBuilder("{ "); + StringBuilder builder = new StringBuilder("{"); if (errors != null) { - builder.append(" errors: ["); + builder.append("errors:["); for (RestError error : errors) { builder.append(error.toString()); } - builder.append("], "); + builder.append("],"); } - builder.append("statusCode: "); + builder.append("statusCode:"); builder.append(statusCode); builder.append("}"); http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceMultipleChoicesException.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceMultipleChoicesException.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceMultipleChoicesException.java new file mode 100644 index 0000000..8330e5e --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceMultipleChoicesException.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.salesforce.api; + +import java.util.List; + +public class SalesforceMultipleChoicesException extends SalesforceException { + + private static final long serialVersionUID = 1L; + private final List<String> choices; + + public SalesforceMultipleChoicesException(String message, int statusCode, List<String> choices) { + super(message, statusCode); + this.choices = choices; + } + + public List<String> getChoices() { + return choices; + } + + @Override + public void appendFields(StringBuilder builder) { + super.appendFields(builder); + builder.append(",choices="); + builder.append(choices.toString()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java index 2364697..bf3a395 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java @@ -28,6 +28,7 @@ import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.component.salesforce.api.dto.RestError; import org.apache.camel.component.salesforce.internal.dto.LoginError; import org.apache.camel.component.salesforce.internal.dto.LoginToken; +import org.apache.camel.util.ObjectHelper; import org.codehaus.jackson.map.ObjectMapper; import org.eclipse.jetty.client.ContentExchange; import org.eclipse.jetty.client.HttpClient; @@ -61,13 +62,13 @@ public class SalesforceSession implements Service { public SalesforceSession(HttpClient httpClient, SalesforceLoginConfig config) { // validate parameters - assertNotNull("Null httpClient", httpClient); - assertNotNull("Null SalesforceLoginConfig", config); - assertNotNull("Null loginUrl", config.getLoginUrl()); - assertNotNull("Null clientId", config.getClientId()); - assertNotNull("Null clientSecret", config.getClientSecret()); - assertNotNull("Null userName", config.getUserName()); - assertNotNull("Null password", config.getPassword()); + ObjectHelper.notNull(httpClient, "httpClient"); + ObjectHelper.notNull(config, "SalesforceLoginConfig"); + ObjectHelper.notNull(config.getLoginUrl(), "loginUrl"); + ObjectHelper.notNull(config.getClientId(), "clientId"); + ObjectHelper.notNull(config.getClientSecret(), "clientSecret"); + ObjectHelper.notNull(config.getUserName(), "userName"); + ObjectHelper.notNull(config.getPassword(), "password"); this.httpClient = httpClient; this.config = config; @@ -80,12 +81,6 @@ public class SalesforceSession implements Service { this.listeners = new CopyOnWriteArraySet<SalesforceSessionListener>(); } - private void assertNotNull(String s, Object o) { - if (o == null) { - throw new IllegalArgumentException(s); - } - } - @SuppressWarnings("unchecked") public synchronized String login(String oldToken) throws SalesforceException { http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AbstractClientBase.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AbstractClientBase.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AbstractClientBase.java index a115a31..a00d289 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AbstractClientBase.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/AbstractClientBase.java @@ -150,7 +150,7 @@ public abstract class AbstractClientBase implements SalesforceSession.Salesforce if (responseStatus < HttpStatus.OK_200 || responseStatus >= HttpStatus.MULTIPLE_CHOICES_300) { final String msg = String.format("Error {%s:%s} executing {%s:%s}", responseStatus, reason, request.getMethod(), request.getRequestURI()); - final SalesforceException exception = new SalesforceException(msg, responseStatus, createRestException(request)); + final SalesforceException exception = new SalesforceException(msg, responseStatus, createRestException(request, reason)); callback.onResponse(null, exception); } else { // TODO not memory efficient for large response messages, @@ -190,6 +190,6 @@ public abstract class AbstractClientBase implements SalesforceSession.Salesforce protected abstract void setAccessToken(HttpExchange httpExchange); - protected abstract SalesforceException createRestException(ContentExchange httpExchange); + protected abstract SalesforceException createRestException(ContentExchange httpExchange, String reason); } http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultBulkApiClient.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultBulkApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultBulkApiClient.java index a72aee7..3ab4227 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultBulkApiClient.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultBulkApiClient.java @@ -386,7 +386,7 @@ public class DefaultBulkApiClient extends AbstractClientBase implements BulkApiC } @Override - protected SalesforceException createRestException(ContentExchange request) { + protected SalesforceException createRestException(ContentExchange request, String reason) { // this must be of type Error try { final Error error = unmarshalResponse(new ByteArrayInputStream(request.getResponseContentBytes()), http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java index 9a9f91b..7269984 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRestClient.java @@ -28,10 +28,13 @@ import java.util.Map; import com.thoughtworks.xstream.XStream; import org.apache.camel.component.salesforce.api.SalesforceException; +import org.apache.camel.component.salesforce.api.SalesforceMultipleChoicesException; import org.apache.camel.component.salesforce.api.dto.RestError; import org.apache.camel.component.salesforce.internal.PayloadFormat; import org.apache.camel.component.salesforce.internal.SalesforceSession; +import org.apache.camel.component.salesforce.internal.dto.RestChoices; import org.apache.camel.component.salesforce.internal.dto.RestErrors; +import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.URISupport; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; @@ -40,6 +43,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpMethods; +import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.util.StringUtil; public class DefaultRestClient extends AbstractClientBase implements RestClient { @@ -63,6 +67,7 @@ public class DefaultRestClient extends AbstractClientBase implements RestClient this.objectMapper = new ObjectMapper(); this.xStream = new XStream(); xStream.processAnnotations(RestErrors.class); + xStream.processAnnotations(RestChoices.class); } @Override @@ -77,32 +82,61 @@ public class DefaultRestClient extends AbstractClientBase implements RestClient } @Override - protected SalesforceException createRestException(ContentExchange httpExchange) { + protected SalesforceException createRestException(ContentExchange httpExchange, String reason) { + // get status code and reason phrase + final int statusCode = httpExchange.getResponseStatus(); + if (reason == null || reason.isEmpty()) { + reason = HttpStatus.getMessage(statusCode); + } // try parsing response according to format + String responseContent = null; try { - if (PayloadFormat.JSON.equals(format)) { - List<RestError> restErrors = objectMapper.readValue( - httpExchange.getResponseContent(), new TypeReference<List<RestError>>() { + responseContent = httpExchange.getResponseContent(); + if (responseContent != null && !responseContent.isEmpty()) { + final List<String> choices; + // return list of choices as error message for 300 + if (statusCode == HttpStatus.MULTIPLE_CHOICES_300) { + if (PayloadFormat.JSON.equals(format)) { + choices = objectMapper.readValue( + responseContent, new TypeReference<List<String>>() { + } + ); + } else { + RestChoices restChoices = new RestChoices(); + xStream.fromXML(responseContent, restChoices); + choices = restChoices.getUrls(); + } + return new SalesforceMultipleChoicesException(reason, statusCode, choices); + } else { + final List<RestError> restErrors; + if (PayloadFormat.JSON.equals(format)) { + restErrors = objectMapper.readValue( + responseContent, new TypeReference<List<RestError>>() { + } + ); + } else { + RestErrors errors = new RestErrors(); + xStream.fromXML(responseContent, errors); + restErrors = errors.getErrors(); } - ); - return new SalesforceException(restErrors, httpExchange.getResponseStatus()); - } else { - RestErrors errors = new RestErrors(); - xStream.fromXML(httpExchange.getResponseContent(), errors); - return new SalesforceException(errors.getErrors(), httpExchange.getResponseStatus()); + return new SalesforceException(restErrors, statusCode); + } } } catch (IOException e) { // log and ignore - String msg = "Unexpected Error parsing " + format + " error response: " + e.getMessage(); + String msg = "Unexpected Error parsing " + format + + " error response body + [" + responseContent + "] : " + e.getMessage(); log.warn(msg, e); } catch (RuntimeException e) { // log and ignore - String msg = "Unexpected Error parsing " + format + " error response: " + e.getMessage(); + String msg = "Unexpected Error parsing " + format + + " error response body + [" + responseContent + "] : " + e.getMessage(); log.warn(msg, e); } // just report HTTP status info - return new SalesforceException("Unexpected error", httpExchange.getResponseStatus()); + return new SalesforceException("Unexpected error: " + reason + ", with content: " + responseContent, + statusCode); } @Override @@ -357,16 +391,12 @@ public class DefaultRestClient extends AbstractClientBase implements RestClient } private String versionUrl() { - if (version == null) { - throw new IllegalArgumentException("NULL API version", new NullPointerException("version")); - } + ObjectHelper.notNull(version, "version"); return servicesDataUrl() + "v" + version + "/"; } private String sobjectsUrl(String sObjectName) { - if (sObjectName == null) { - throw new IllegalArgumentException("Null SObject name", new NullPointerException("sObjectName")); - } + ObjectHelper.notNull(sObjectName, "sObjectName"); return versionUrl() + "sobjects/" + sObjectName; } http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/dto/RestChoices.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/dto/RestChoices.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/dto/RestChoices.java new file mode 100644 index 0000000..cd639ff --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/dto/RestChoices.java @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.component.salesforce.internal.dto; + +import java.util.List; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamImplicit; + +/** + * DTO for Salesforce REST choices XML response for status code 300 + */ +@XStreamAlias("Choices") +public class RestChoices { + + @XStreamImplicit(itemFieldName = "Url") + private List<String> urls; + + public List<String> getUrls() { + return urls; + } + + public void setUrls(List<String> urls) { + this.urls = urls; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/865b7ffe/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java index 52a95f6..9627cf3 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java @@ -29,6 +29,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import org.apache.camel.CamelExecutionException; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.salesforce.api.SalesforceException; +import org.apache.camel.component.salesforce.api.SalesforceMultipleChoicesException; import org.apache.camel.component.salesforce.api.dto.AbstractDTOBase; import org.apache.camel.component.salesforce.api.dto.CreateSObjectResult; import org.apache.camel.component.salesforce.api.dto.GlobalObjects; @@ -172,7 +173,7 @@ public class RestApiIntegrationTest extends AbstractSalesforceTestBase { merchandise.setDescription__c("Microlite plane"); merchandise.setPrice__c(2000.0); merchandise.setTotal_Inventory__c(50.0); - CreateSObjectResult result = template().requestBody("direct:CreateSObject" + suffix, + CreateSObjectResult result = template().requestBody("direct:createSObject" + suffix, merchandise, CreateSObjectResult.class); assertNotNull(result); assertTrue("Create success", result.getSuccess()); @@ -186,7 +187,7 @@ public class RestApiIntegrationTest extends AbstractSalesforceTestBase { // also need to set the Id merchandise.setId(result.getId()); - assertNull(template().requestBodyAndHeader("direct:UpdateSObject" + suffix, + assertNull(template().requestBodyAndHeader("direct:updateSObject" + suffix, merchandise, SalesforceEndpointConfig.SOBJECT_ID, result.getId())); LOG.debug("Update successful"); @@ -391,6 +392,124 @@ public class RestApiIntegrationTest extends AbstractSalesforceTestBase { } } + @Test + public void testStatus300() throws Exception { + doTestStatus300(""); + doTestStatus300("Xml"); + } + + private void doTestStatus300(String suffix) throws Exception { + // clone test merchandise with same external Id + if (testId == null) { + // execute getBasicInfo to get test id from recent items + doTestGetBasicInfo(""); + } + + // get test merchandise + // note that the header value overrides sObjectFields in endpoint + Merchandise__c merchandise = template().requestBodyAndHeader("direct:getSObject" + suffix, testId, + "sObjectFields", "Name,Description__c,Price__c,Total_Inventory__c", Merchandise__c.class); + assertNotNull(merchandise); + assertNotNull(merchandise.getName()); + assertNotNull(merchandise.getPrice__c()); + assertNotNull(merchandise.getTotal_Inventory__c()); + + CreateSObjectResult result = null; + try { + merchandise.clearBaseFields(); + result = template().requestBody("direct:createSObject" + suffix, + merchandise, CreateSObjectResult.class); + assertNotNull(result); + assertNotNull(result.getId()); + LOG.debug("Clone SObject: {}", result); + + // look by external Id to cause 300 error + // note that the request SObject overrides settings on the endpoint for LineItem__c + try { + template().requestBody("direct:getSObjectWithId" + suffix, merchandise, Merchandise__c.class); + fail("Expected SalesforceException with statusCode 300"); + } catch (CamelExecutionException e) { + assertTrue(e.getCause() instanceof SalesforceException); + assertTrue(e.getCause().getCause() instanceof SalesforceMultipleChoicesException); + final SalesforceMultipleChoicesException cause = (SalesforceMultipleChoicesException) e.getCause().getCause(); + assertEquals(300, cause.getStatusCode()); + final List<String> choices = cause.getChoices(); + assertNotNull(choices); + assertFalse(choices.isEmpty()); + LOG.debug("Multiple choices: {}", choices); + } + } finally { + // delete the test clone + if (result != null) { + template().requestBody("direct:deleteSObject" + suffix, result.getId()); + } + } + } + + @Test + public void testStatus400() throws Exception { + doTestStatus400(""); + doTestStatus400("Xml"); + } + + private void doTestStatus400(String suffix) throws Exception { + // clone test merchandise with same external Id + if (testId == null) { + // execute getBasicInfo to get test id from recent items + doTestGetBasicInfo(""); + } + + // get test merchandise + // note that the header value overrides sObjectFields in endpoint + Merchandise__c merchandise = template().requestBodyAndHeader("direct:getSObject" + suffix, testId, + "sObjectFields", "Description__c,Price__c", Merchandise__c.class); + assertNotNull(merchandise); + assertNotNull(merchandise.getPrice__c()); + assertNull(merchandise.getTotal_Inventory__c()); + + merchandise.clearBaseFields(); + // required field Total_Inventory__c is missing + CreateSObjectResult result = null; + try { + result = template().requestBody("direct:createSObject" + suffix, + merchandise, CreateSObjectResult.class); + fail("Expected SalesforceException with statusCode 400"); + } catch (CamelExecutionException e) { + assertTrue(e.getCause() instanceof SalesforceException); + assertTrue(e.getCause().getCause() instanceof SalesforceException); + final SalesforceException cause = (SalesforceException) e.getCause().getCause(); + assertEquals(400, cause.getStatusCode()); + assertEquals(1, cause.getErrors().size()); + assertEquals("[Total_Inventory__c]", cause.getErrors().get(0).getFields().toString()); + } finally { + // delete the clone if created + if (result != null) { + template().requestBody("direct:deleteSObject" + suffix, result.getId()); + } + } + } + + @Test + public void testStatus404() { + doTestStatus404(""); + doTestStatus404("Xml"); + } + + private void doTestStatus404(String suffix) { + // try to get a non existent SObject + try { + template().requestBody("direct:getSObject" + suffix, "ILLEGAL_ID", Merchandise__c.class); + fail("Expected SalesforceException"); + } catch (CamelExecutionException e) { + assertTrue(e.getCause() instanceof SalesforceException); + assertTrue(e.getCause().getCause() instanceof SalesforceException); + final SalesforceException cause = (SalesforceException) e.getCause().getCause(); + assertEquals(404, cause.getStatusCode()); + assertEquals(1, cause.getErrors().size()); + LOG.debug("Errors for 404: {}", cause.getErrors()); + } + } + @Override protected RouteBuilder doCreateRouteBuilder() throws Exception { @@ -442,17 +561,17 @@ public class RestApiIntegrationTest extends AbstractSalesforceTestBase { .to("salesforce:getSObject?format=XML&sObjectName=Merchandise__c&sObjectFields=Description__c,Total_Inventory__c"); // testCreateSObject - from("direct:CreateSObject") + from("direct:createSObject") .to("salesforce:createSObject?sObjectName=Merchandise__c"); - from("direct:CreateSObjectXml") + from("direct:createSObjectXml") .to("salesforce:createSObject?format=XML&sObjectName=Merchandise__c"); // testUpdateSObject - from("direct:UpdateSObject") + from("direct:updateSObject") .to("salesforce:updateSObject?sObjectName=Merchandise__c"); - from("direct:UpdateSObjectXml") + from("direct:updateSObjectXml") .to("salesforce:updateSObject?format=XML&sObjectName=Merchandise__c"); // testDeleteSObject