diff --git a/pom.xml b/pom.xml index 1c85f02..94aea04 100644 --- a/pom.xml +++ b/pom.xml @@ -1,198 +1,202 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - com.springml - salesforce-wave-api - 1.0.7 - jar + com.springml + salesforce-wave-api + 1.0.9 + jar - salesforce-wave-api - Java client for Salesforce Wave API - - - samuel-pt - Samuel Alexander - - + salesforce-wave-api + Java client for Salesforce Wave API + + + samuel-pt + Samuel Alexander + + + kagan-turgut + Kagan Turgut + + - https://github.com/springml/salesforce-wave-api - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - + https://github.com/springml/salesforce-wave-api + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + - - scm:git:github.com/springml/salesforce-wave-api - scm:git:git@github.com:springml/salesforce-wave-api - github.com/springml/salesforce-wave-api - + + scm:git:github.com/springml/salesforce-wave-api + scm:git:git@github.com:springml/salesforce-wave-api + github.com/springml/salesforce-wave-api + - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + - - UTF-8 - 1.8 - + + UTF-8 + 1.8 + true + - - - com.force.api - force-partner-api - 34.0.0 - - - com.force.api - force-wsc - 34.2.2 - - - org.apache.httpcomponents - httpclient - 4.5 - - - com.fasterxml.jackson.core - jackson-core - 2.4.4 - - - com.fasterxml.jackson.core - jackson-databind - 2.4.4 - - - commons-io - commons-io - 2.5 - - - log4j - log4j - 1.2.17 - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - 2.4.4 - - - org.codehaus.woodstox - woodstox-core-asl - 4.4.0 - - - org.apache.commons - commons-lang3 - 3.4 - + + + com.force.api + force-partner-api + 39.0.0 + + + com.force.api + force-wsc + 39.0.1 + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + com.fasterxml.jackson.core + jackson-core + 2.8.7 + + + com.fasterxml.jackson.core + jackson-databind + 2.8.7 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.8.7 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + 2.8.7 + + + + commons-io + commons-io + 2.5 + + + log4j + log4j + 1.2.17 + + + + org.apache.commons + commons-lang3 + 3.5 + + + junit + junit + 4.12 + test + + + org.mockito + mockito-core + 2.7.10 + - - junit - junit - 4.12 - test - - - org.mockito - mockito-core - 2.0.31-beta - test - - - org.mockito - mockito-core - 2.0.31-beta - test - + - + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5 + + false + release + deploy + + + + - - - - - org.apache.maven.plugins - maven-release-plugin - 2.5 - - false - release - deploy - - - - + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.3 + true + + ossrh + https://oss.sonatype.org/ + true + + - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 - true - - ossrh - https://oss.sonatype.org/ - true - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - -Xdoclint:none - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + -Xdoclint:none + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + true + + + + sign-artifacts + verify + + sign + + + + + + diff --git a/src/main/java/com/springml/salesforce/wave/api/APIFactory.java b/src/main/java/com/springml/salesforce/wave/api/APIFactory.java index 60d8263..23b0db5 100644 --- a/src/main/java/com/springml/salesforce/wave/api/APIFactory.java +++ b/src/main/java/com/springml/salesforce/wave/api/APIFactory.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Contributors : + * Samual Alexander, springml + * Kagan Turgut + * + * 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.springml.salesforce.wave.api; import com.springml.salesforce.wave.impl.BulkAPIImpl; diff --git a/src/main/java/com/springml/salesforce/wave/api/BulkAPI.java b/src/main/java/com/springml/salesforce/wave/api/BulkAPI.java index f2141be..613b22e 100644 --- a/src/main/java/com/springml/salesforce/wave/api/BulkAPI.java +++ b/src/main/java/com/springml/salesforce/wave/api/BulkAPI.java @@ -1,8 +1,31 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, oolong, springml + * Contributors : + * Kagan Turgut, oolong + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; +import java.io.InputStream; +import java.util.List; + import com.springml.salesforce.wave.model.BatchInfo; import com.springml.salesforce.wave.model.BatchInfoList; +import com.springml.salesforce.wave.model.BatchResult; import com.springml.salesforce.wave.model.JobInfo; +import com.springml.salesforce.wave.model.SOQLResult; /** * Java client for Salesforce Bulk API @@ -15,8 +38,58 @@ public interface BulkAPI { * @param The Salesforce object to be updated * @return @JobInfo * @throws Exception + * @deprecated Use createUpdateJob or createQueryJob instead */ public JobInfo createJob(String object) throws Exception; + + /** + * Create Update Job + * @param object + * @return + * @throws Exception + */ + public JobInfo createUpdateJob(String object) throws Exception; + + /** + * + * @param object + * @return + * @throws Exception + */ + public JobInfo createQueryJob(String object) throws Exception; + + /** + * Create bulk query job with PK chunking + * @param object + * @param pkChunking + * @return + * @throws Exception + */ + public JobInfo createQueryJob(String object, Boolean pkChunking) throws Exception; + + + /** + * Create bulk query job with PK chunking. if QueryAll is set, it will bring deleted Salesforce records as well. + * @param object : name of the object in salesforce + * @param pkChunking : whether the result will be returned in batches + * @param queryAll : whether to bring deleted records from salesforce. subject to Salesforce garbage bin limitations + * @return + * @throws Exception + */ + public JobInfo createQueryJob(String object, Boolean pkChunking, Boolean queryAll) throws Exception; + + /** + * Create bulk query job with PK chunking. if QueryAll is set, it will bring deleted Salesforce records as well. + * Use this method if you want to specify additional pkChunking parameters such as chunkSize. + * @param object + * @param pkChunkingKey + * @param pkChunkingValue : you can optionally pass chunksize, but better to go with the default. + * @param queryAll : if true, it will bring deleted records as well. + * @return + * @throws Exception + */ + public JobInfo createQueryJob(String object, String pkChunkingKey, String pkChunkingValue, Boolean queryAll) throws Exception; + /** * Create a new Bulk Job @@ -35,6 +108,7 @@ public interface BulkAPI { * @throws Exception */ public JobInfo createJob(JobInfo jobInfo) throws Exception; + /** * Add a batch to an existing Job @@ -45,6 +119,15 @@ public interface BulkAPI { * @throws Exception */ public BatchInfo addBatch(String jobId, String csvContent) throws Exception; + + /** + * Close the job + * @param jobId + * @param checkBatchesFirst + * @return + * @throws Exception + */ + public JobInfo closeJob(String jobId, Boolean checkBatchesFirst) throws Exception; /** * Close the specified Salesforce Bulk Job @@ -88,4 +171,34 @@ public interface BulkAPI { * @throws Exception */ public BatchInfo getBatchInfo(String jobId, String batchId) throws Exception; + + /** + * Get list of active jobs + * @return + */ + public List getActiveJobIds(); + + /** + * Get list of recently completed jobs + * @return + */ + public List getCompletedJobIds(); + + /** + * Return batchResults for this batch. This is in CSV format, and by default includes the header rows + * @param batch + * @return + * @throws Exception + */ + public BatchResult queryBatch(BatchInfo batch) throws Exception; + + /** + * Return batchresults as a stream. CSV format, includes the header rows by default. + * @param batch + * @return + * @throws Exception + */ + public InputStream queryBatchStream(BatchInfo batch) throws Exception; + + } diff --git a/src/main/java/com/springml/salesforce/wave/api/ForceAPI.java b/src/main/java/com/springml/salesforce/wave/api/ForceAPI.java index 1b90a3b..95db20c 100644 --- a/src/main/java/com/springml/salesforce/wave/api/ForceAPI.java +++ b/src/main/java/com/springml/salesforce/wave/api/ForceAPI.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Contributors : + * Samual Alexander, springml + * Kagan Turgut + * + * 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.springml.salesforce.wave.api; import com.springml.salesforce.wave.model.AddTaskRequest; diff --git a/src/main/java/com/springml/salesforce/wave/api/WaveAPI.java b/src/main/java/com/springml/salesforce/wave/api/WaveAPI.java index d6d77d9..035d8df 100644 --- a/src/main/java/com/springml/salesforce/wave/api/WaveAPI.java +++ b/src/main/java/com/springml/salesforce/wave/api/WaveAPI.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Contributors : + * Samual Alexander, springml + * Kagan Turgut + * + * 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.springml.salesforce.wave.api; import com.springml.salesforce.wave.model.QueryResult; diff --git a/src/main/java/com/springml/salesforce/wave/impl/AbstractAPIImpl.java b/src/main/java/com/springml/salesforce/wave/impl/AbstractAPIImpl.java index dd20daf..12c42ac 100644 --- a/src/main/java/com/springml/salesforce/wave/impl/AbstractAPIImpl.java +++ b/src/main/java/com/springml/salesforce/wave/impl/AbstractAPIImpl.java @@ -1,8 +1,30 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * Kagan Turgut + * + * 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.springml.salesforce.wave.impl; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; +import com.fasterxml.jackson.dataformat.csv.CsvParser; import com.springml.salesforce.wave.util.HTTPHelper; import com.springml.salesforce.wave.util.SFConfig; @@ -12,8 +34,10 @@ public abstract class AbstractAPIImpl { private ObjectMapper objectMapper; private XmlMapper xmlMapper; + private CsvMapper csvMapper; private HTTPHelper httpHelper; private SFConfig sfConfig; + private ObjectReader objectReader; public AbstractAPIImpl(SFConfig sfConfig) throws Exception { setHttpHelper(new HTTPHelper()); @@ -24,6 +48,12 @@ public AbstractAPIImpl(SFConfig sfConfig) throws Exception { setObjectMapper(objectMapper); this.xmlMapper = new XmlMapper(); + + this.csvMapper = new CsvMapper(); + CsvSchema schema = CsvSchema.builder().setColumnSeparator(',').build(); + csvMapper.enable(CsvParser.Feature.WRAP_AS_ARRAY); + objectReader = csvMapper.readerFor(String[].class).with(schema); + this.sfConfig = sfConfig; } @@ -58,5 +88,21 @@ public XmlMapper getXmlMapper() { public void setXmlMapper(XmlMapper xmlMapper) { this.xmlMapper = xmlMapper; } + + public CsvMapper getCsvMapper() { + return csvMapper; + } + + public ObjectReader getObjectReader() { + return objectReader; + } + + public void setObjectReader(ObjectReader reader) { + this.objectReader=reader; + } + + public void setCsvMapper(CsvMapper csvMapper) { + this.csvMapper = csvMapper; + } } diff --git a/src/main/java/com/springml/salesforce/wave/impl/BulkAPIImpl.java b/src/main/java/com/springml/salesforce/wave/impl/BulkAPIImpl.java index 2e842e5..ef474fd 100644 --- a/src/main/java/com/springml/salesforce/wave/impl/BulkAPIImpl.java +++ b/src/main/java/com/springml/salesforce/wave/impl/BulkAPIImpl.java @@ -1,10 +1,54 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Authors : + * Kagan Turgut, oolong + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.impl; -import static com.springml.salesforce.wave.util.WaveAPIConstants.*; - +import static com.springml.salesforce.wave.util.WaveAPIConstants.CONTENT_TYPE_APPLICATION_JSON; +import static com.springml.salesforce.wave.util.WaveAPIConstants.CONTENT_TYPE_APPLICATION_XML; +import static com.springml.salesforce.wave.util.WaveAPIConstants.CONTENT_TYPE_TEXT_CSV; +import static com.springml.salesforce.wave.util.WaveAPIConstants.PATH_BATCH; +import static com.springml.salesforce.wave.util.WaveAPIConstants.PATH_JOB; +import static com.springml.salesforce.wave.util.WaveAPIConstants.PATH_RESULT; +import static com.springml.salesforce.wave.util.WaveAPIConstants.SERVICE_ASYNC_PATH; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_CLOSED; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_COMPLETED; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_CSV; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_FAILED; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_JSON; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_PARALLEL; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_QUERY; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_QUERY_ALL; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_UPDATE; +import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_XML; + + + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -13,194 +57,356 @@ import com.springml.salesforce.wave.api.BulkAPI; import com.springml.salesforce.wave.model.BatchInfo; import com.springml.salesforce.wave.model.BatchInfoList; +import com.springml.salesforce.wave.model.BatchResult; import com.springml.salesforce.wave.model.JobInfo; import com.springml.salesforce.wave.util.LRUCache; import com.springml.salesforce.wave.util.SFConfig; public class BulkAPIImpl extends AbstractAPIImpl implements BulkAPI { - private static final Logger LOG = Logger.getLogger(BulkAPIImpl.class); - private Map jobContentTypeMap = new LRUCache(100); - - public BulkAPIImpl(SFConfig sfConfig) throws Exception { - super(sfConfig); - } - - public JobInfo createJob(String object) throws Exception { - JobInfo jobInfo = new JobInfo(STR_CSV, object, STR_UPDATE); - - return createJob(jobInfo); - } - - public JobInfo createJob(String object, String operation, String contentType) throws Exception { - JobInfo jobInfo = new JobInfo(contentType, object, operation); - - return createJob(jobInfo); - } - - public JobInfo createJob(JobInfo jobInfo) throws Exception { - PartnerConnection connection = getSfConfig().getPartnerConnection(); - URI requestURI = getSfConfig().getRequestURI(connection, getJobPath()); - - String response = getHttpHelper().post(requestURI, getSfConfig().getSessionId(), - getObjectMapper().writeValueAsString(jobInfo), true); - LOG.debug("Response from Salesforce Server " + response); - - JobInfo respJobInfo = getObjectMapper().readValue(response.getBytes(), JobInfo.class); - jobContentTypeMap.put(respJobInfo.getId(), getRespectiveCntType(jobInfo)); - - return respJobInfo; - } - - public BatchInfo addBatch(String jobId, String csvContent) throws Exception { - PartnerConnection connection = getSfConfig().getPartnerConnection(); - URI requestURI = getSfConfig().getRequestURI(connection, getBatchPath(jobId)); - - String contentType = getContentType(jobId); - String response = getHttpHelper().post(requestURI, getSfConfig().getSessionId(), - csvContent, contentType, true); - LOG.debug("Response from Salesforce Server " + response); - - // Response is in xml though Accept is set to application/json - if (CONTENT_TYPE_APPLICATION_JSON.equals(contentType)) { - return getObjectMapper().readValue(response.getBytes(), BatchInfo.class); - } - - return getXmlMapper().readValue(response.getBytes(), BatchInfo.class); - } - - public JobInfo closeJob(String jobId) throws Exception { - PartnerConnection connection = getSfConfig().getPartnerConnection(); - URI requestURI = getSfConfig().getRequestURI(connection, getJobPath(jobId)); - - JobInfo jobInfo = new JobInfo(STR_CLOSED); - String response = getHttpHelper().post(requestURI, getSfConfig().getSessionId(), - getObjectMapper().writeValueAsString(jobInfo), true); - LOG.debug("Response from Salesforce Server " + response); - - return getObjectMapper().readValue(response.getBytes(), JobInfo.class); - } - - public boolean isCompleted(String jobId) throws Exception { - BatchInfoList batchInfoList = getBatchInfoList(jobId); - List batchInfos = batchInfoList.getBatchInfo(); - boolean isCompleted = false; - LOG.debug("BatchInfos : " + batchInfos); - if (batchInfos != null) { - for (BatchInfo batchInfo : batchInfos) { - LOG.debug("Batch state : " + batchInfo.getState()); - isCompleted = STR_COMPLETED.equals(batchInfo.getState()); - if (STR_FAILED.equals(batchInfo.getState())) { - throw new Exception("Batch '" + batchInfo.getId() + "' failed with error '" + batchInfo.getStateMessage() + "'"); - } - - LOG.info("Number of records failed : " + batchInfo.getNumberRecordsFailed()); - if (batchInfo.getNumberRecordsFailed() > 0) { - String result = getResult(jobId, batchInfo.getId()); - LOG.error("Failed record details \n " + result); - throw new Exception("Batch '" + batchInfo.getId() + - "' failed. Number of failed records is " + batchInfo.getNumberRecordsFailed()); - } - } - } - - return isCompleted; - } - - private String getResult(String jobId, String batchId) throws Exception { - PartnerConnection connection = getSfConfig().getPartnerConnection(); - URI requestURI = getSfConfig().getRequestURI(connection, getBatchResultPath(jobId, batchId)); - return getHttpHelper().get(requestURI, getSfConfig().getSessionId(), true); - } - - public BatchInfoList getBatchInfoList(String jobId) throws Exception { - PartnerConnection connection = getSfConfig().getPartnerConnection(); - URI requestURI = getSfConfig().getRequestURI(connection, getBatchPath(jobId)); - - String response = getHttpHelper().get(requestURI, getSfConfig().getSessionId(), true); - LOG.debug("Response from Salesforce Server " + response); - - if (CONTENT_TYPE_APPLICATION_JSON.equals(getContentType(jobId))) { - return getObjectMapper().readValue(response.getBytes(), BatchInfoList.class); + + private static final Logger LOG = Logger.getLogger(BulkAPIImpl.class); + + private Map jobContentTypeMap = new LRUCache(200); + private Map batchedJobMap = new LRUCache(200); + private Map finishedJobMap = new LRUCache(100); + + public BulkAPIImpl(SFConfig sfConfig) throws Exception { + super(sfConfig); + } + + public JobInfo createJob(String object) throws Exception { + return createUpdateJob(object); + } + + public JobInfo createUpdateJob(String object) throws Exception { + JobInfo jobInfo = new JobInfo(STR_CSV, object, STR_UPDATE); + + return createJob(jobInfo); + } + + public JobInfo createQueryJob(String object) throws Exception { + return createQueryJob(object, false); + } + + public JobInfo createQueryJob(String object, Boolean pkChunking) throws Exception { + return createQueryJob(object,pkChunking, true); + } + + public JobInfo createQueryJob(String object, Boolean pkChunking, Boolean queryAll) throws Exception { + return (pkChunking)? + createQueryJob(object, "Sforce-Enable-PKChunking", "true", queryAll): + createQueryJob(object, null, null, queryAll); + } + + public JobInfo createQueryJob(String object, String pkChunkingKey, String pkChunkingValue, Boolean queryAll) throws Exception { + // TODO fix JSON handling for non-pk chunking requests + String contentType = (pkChunkingKey!=null && !"false".equals(pkChunkingValue))?STR_CSV:STR_CSV; + JobInfo jobInfo = new JobInfo(contentType, object, queryAll?STR_QUERY_ALL:STR_QUERY); + jobInfo.setConcurrencyMode(STR_PARALLEL); + if (pkChunkingKey != null && pkChunkingValue != null) + jobInfo.setHeader(pkChunkingKey, pkChunkingValue); + + return createJob(jobInfo); + } + + public JobInfo createJob(String object, String operation, String contentType, String concurrencyMode, String header) + throws Exception { + JobInfo jobInfo = new JobInfo(contentType, object, operation, header); + + return createJob(jobInfo); + } + + public JobInfo createJob(String object, String operation, String contentType) throws Exception { + return createJob(object, operation, contentType, null, null); + } + + public JobInfo createJob(JobInfo jobInfo) throws Exception { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, getJobPath()); + + String response = getHttpHelper().post(requestURI, getSfConfig().getSessionId(), + getObjectMapper().writeValueAsString(jobInfo), true, jobInfo.getHeader()); + LOG.debug("Response from Salesforce Server " + response); + + JobInfo respJobInfo = getObjectMapper().readValue(response.getBytes(), JobInfo.class); + jobContentTypeMap.put(respJobInfo.getId(), getRespectiveCntType(jobInfo)); + + return respJobInfo; + } + + public BatchInfo addBatch(String jobId, String csvContent) throws Exception { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, getBatchPath(jobId)); + + String contentType = getContentType(jobId); + String response = getHttpHelper().post(requestURI, getSfConfig().getSessionId(), csvContent, contentType, true); + LOG.debug("Response from Salesforce Server " + response); + + // Response is in xml though Accept is set to application/json + if (CONTENT_TYPE_APPLICATION_JSON.equals(contentType)) { + return getObjectMapper().readValue(response.getBytes(), BatchInfo.class); + } + + BatchInfo result = getXmlMapper().readValue(response.getBytes(), BatchInfo.class); + if (result.isQueued()) { + batchedJobMap.put(result.getJobId(), result); + } + return result; + } + + public JobInfo closeJob(String jobId, Boolean checkBatchesFirst) throws Exception { + if (checkBatchesFirst && !this.isCompleted(jobId)) { + LOG.error("Job " + jobId + " has unprocessed batches. Can not be closed"); + return null; + } + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, getJobPath(jobId)); + + JobInfo jobInfo = new JobInfo(STR_CLOSED); + String response = getHttpHelper().post(requestURI, getSfConfig().getSessionId(), + getObjectMapper().writeValueAsString(jobInfo), true); + LOG.debug("Response from Salesforce Server " + response); + + return getObjectMapper().readValue(response.getBytes(), JobInfo.class); + } + + public JobInfo closeJob(String jobId) throws Exception { + return closeJob(jobId, false); + } + + public boolean isCompleted(String jobId) throws Exception { + BatchInfoList batchInfoList = getBatchInfoList(jobId); + List batchInfos = batchInfoList.getBatchInfo(); + boolean isCompleted = true; + LOG.debug("BatchInfos : " + batchInfos); + if (batchInfos != null) { + for (BatchInfo batchInfo : batchInfos) { + LOG.debug("Batch state : " + batchInfo.getState()); + isCompleted = STR_COMPLETED.equals(batchInfo.getState()); + if (STR_FAILED.equals(batchInfo.getState())) { + throw new Exception("Batch '" + batchInfo.getId() + "' failed with error '" + + batchInfo.getStateMessage() + "'"); + } + + LOG.info("Number of records failed : " + batchInfo.getNumberRecordsFailed()); + if (batchInfo.getNumberRecordsFailed() > 0) { + String result = getResult(jobId, batchInfo.getId()); + LOG.error("Failed record details \n " + result); + throw new Exception("Batch '" + batchInfo.getId() + "' failed. Number of failed records is " + + batchInfo.getNumberRecordsFailed()); + } + } + } + + return isCompleted; + } + + private String getResult(String jobId, String batchId) throws Exception { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, getBatchResultPath(jobId, batchId)); + return getHttpHelper().get(requestURI, getSfConfig().getSessionId(), true); + } + + public BatchInfoList getBatchInfoList(String jobId) throws Exception { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, getBatchPath(jobId)); + + String response = getHttpHelper().get(requestURI, getSfConfig().getSessionId(), true); + // LOG.debug("Response from Salesforce Server " + response); + + if (CONTENT_TYPE_APPLICATION_JSON.equals(getContentType(jobId))) { + return getObjectMapper().readValue(response.getBytes(), BatchInfoList.class); + } + + return getXmlMapper().readValue(response.getBytes(), BatchInfoList.class); + } + + public BatchInfo getBatchInfo(String jobId, String batchId) throws Exception { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, getBatchPath(jobId, batchId)); + + String response = getHttpHelper().get(requestURI, getSfConfig().getSessionId(), true); + // LOG.debug("Response from Salesforce Server " + response); + + String contentType = getContentType(jobId); + + // Response is in xml though Accept is set to application/json + if (CONTENT_TYPE_APPLICATION_JSON.equals(contentType)) { + return getObjectMapper().readValue(response.getBytes(), BatchInfo.class); + } + else + return getXmlMapper().readValue(response.getBytes(), BatchInfo.class); + } + + public boolean isSuccess(String jobId) throws Exception { + // TODO Auto-generated method stub + return false; + } + + private String getContentType(String jobId) { + String contentType = jobContentTypeMap.get(jobId); + if (StringUtils.isEmpty(contentType)) { + contentType = CONTENT_TYPE_TEXT_CSV; + } + + return contentType; + } + + private String getRespectiveCntType(JobInfo jobInfo) { + String contentType = null; + if (STR_JSON.equals(jobInfo.getContentType())) { + contentType = CONTENT_TYPE_APPLICATION_JSON; + } else if (STR_XML.equals(jobInfo.getContentType())) { + contentType = CONTENT_TYPE_APPLICATION_XML; + } else { + contentType = CONTENT_TYPE_TEXT_CSV; + } + + return contentType; + } + + private String getBatchPath(String jobId, String batchId) { + StringBuilder batchPath = new StringBuilder(); + batchPath.append(getBatchPath(jobId)); + batchPath.append('/'); + batchPath.append(batchId); + return batchPath.toString(); + } + + private String getBatchResultPath(String jobId, String batchId) { + StringBuilder batchResultPath = new StringBuilder(); + batchResultPath.append(getBatchPath(jobId, batchId)); + batchResultPath.append(PATH_RESULT); + + return batchResultPath.toString(); + } + + private String getBatchPath(String jobId) { + StringBuilder batchPath = new StringBuilder(); + batchPath.append(getJobPath(jobId)); + batchPath.append(PATH_BATCH); + + return batchPath.toString(); + } + + private String getJobPath(String jobId) { + StringBuilder jobPath = new StringBuilder(); + jobPath.append(getJobPath()); + jobPath.append('/'); + jobPath.append(jobId); + return jobPath.toString(); + } + + private String getJobPath() { + StringBuilder jobPath = new StringBuilder(); + jobPath.append(SERVICE_ASYNC_PATH); + jobPath.append(getSfConfig().getApiVersion()); + jobPath.append(PATH_JOB); + return jobPath.toString(); + } + + /** + * Get list of active jobs + * + * @return + */ + public List getActiveJobIds() { + Set jobs = new HashSet(batchedJobMap.size()); + for (BatchInfo batch : batchedJobMap.values()) { + jobs.add(batch.getJobId()); + } + return new ArrayList(jobs); + } + + /** + * Get list of recently completed jobs + * + * @return + */ + public List getCompletedJobIds() { + Set jobs = new HashSet(finishedJobMap.size()); + for (BatchInfo batch : finishedJobMap.values()) { + jobs.add(batch.getJobId()); + } + return new ArrayList(jobs); + + } + + /////// Bulk Query + + public BatchResult queryBatch(BatchInfo batch) throws Exception { +// Thread.sleep(30000); // 30 secs + if (!batch.hasDataToLoad()) return null; + BatchResult result = new BatchResult(); + InputStream is = null; + try { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, this.getBatchQueryPath(batch, super.getSfConfig())); + is = getHttpHelper().getQuery(requestURI, + getSfConfig().getSessionId(getSfConfig().getPartnerConnection()), getSfConfig().getBatchSize(),true); + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + String line = reader.readLine(); + LOG.trace("HEADER:" + line); + if (line!=null) { + result.setHeader(Arrays.asList(line.split(","))); + } + while ((line = reader.readLine())!=null) { + //LOG.trace(line); + result.addRecord(Arrays.asList(line.split(","))); + } + } catch (Exception e) { + LOG.error("Error while executing salesforce bulk batch query ", e); + System.exit(-1); + throw e; } - - return getXmlMapper().readValue(response.getBytes(), BatchInfoList.class); - } - - public BatchInfo getBatchInfo(String jobId, String batchId) throws Exception { - PartnerConnection connection = getSfConfig().getPartnerConnection(); - URI requestURI = getSfConfig().getRequestURI(connection, getBatchPath(jobId, batchId)); - - String response = getHttpHelper().get(requestURI, getSfConfig().getSessionId(), true); - LOG.debug("Response from Salesforce Server " + response); - - return getXmlMapper().readValue(response.getBytes(), BatchInfo.class); - } - - public boolean isSuccess(String jobId) throws Exception { - // TODO Auto-generated method stub - return false; - } - - private String getContentType(String jobId) { - String contentType = jobContentTypeMap.get(jobId); - if (StringUtils.isEmpty(contentType)){ - contentType = CONTENT_TYPE_TEXT_CSV; + finally { + if (is!=null) + is.close(); } - - return contentType; + return result; } - - private String getRespectiveCntType(JobInfo jobInfo) { - String contentType = null; - if (STR_JSON.equals(jobInfo.getContentType())) { - contentType = CONTENT_TYPE_APPLICATION_JSON; - } else if (STR_XML.equals(jobInfo.getContentType())) { - contentType = CONTENT_TYPE_APPLICATION_XML; - } else { - contentType = CONTENT_TYPE_TEXT_CSV; + + + // callers must close the stream + public InputStream queryBatchStream(BatchInfo batch) throws Exception { + if (!batch.hasDataToLoad()) return null; + try { + PartnerConnection connection = getSfConfig().getPartnerConnection(); + URI requestURI = getSfConfig().getRequestURI(connection, this.getBatchQueryPath(batch, super.getSfConfig())); + return getHttpHelper().getQuery(requestURI, + getSfConfig().getSessionId(getSfConfig().getPartnerConnection()), getSfConfig().getBatchSize(),true); + } catch (Exception e) { + LOG.error("Error while executing salesforce bulk batch query ", e); + System.exit(-1); + throw e; } - - return contentType; - } - - private String getBatchPath(String jobId, String batchId) { - StringBuilder batchPath = new StringBuilder(); - batchPath.append(getBatchPath(jobId)); - batchPath.append('/'); - batchPath.append(batchId); - return batchPath.toString(); - } - - private String getBatchResultPath(String jobId, String batchId) { - StringBuilder batchResultPath = new StringBuilder(); - batchResultPath.append(getBatchPath(jobId, batchId)); - batchResultPath.append(PATH_RESULT); - - return batchResultPath.toString(); - } - - private String getBatchPath(String jobId) { - StringBuilder batchPath = new StringBuilder(); - batchPath.append(getJobPath(jobId)); - batchPath.append(PATH_BATCH); - - return batchPath.toString(); } - private String getJobPath(String jobId) { - StringBuilder jobPath = new StringBuilder(); - jobPath.append(getJobPath()); - jobPath.append('/'); - jobPath.append(jobId); - return jobPath.toString(); + + + private String getBatchQueryPath(BatchInfo batch, SFConfig sfConfig) throws Exception { + StringBuilder queryPath = new StringBuilder(); + queryPath.append(this.getBatchResultPath(batch.getJobId(), batch.getId())); + try { + String result = this.getResult(batch.getJobId(), batch.getId()); //75236000005tpQ0 + Boolean isJson = CONTENT_TYPE_APPLICATION_JSON.equals(getContentType(batch.getJobId())); + String pattern = isJson?"[\"[\\s\\S]]":"[\\s\\S]*?<\\/result>"; // TODO fix regex + java.util.regex.Pattern r = Pattern.compile(pattern); + java.util.regex.Matcher m = r.matcher(result); + if (isJson || m.find()) { + queryPath.append("/"); + java.util.regex.MatchResult ff = m.toMatchResult(); + String toAppend = isJson?result.substring(2, result.length()-2):result.substring(ff.start()+8, ff.end()-9); + LOG.trace("Query batch metadata path" + toAppend); + queryPath.append(toAppend); + } else { + BatchInfo b = this.getBatchInfo(batch.getJobId(), batch.getId()); + // LOG.trace("Actual state: " + b.getState()); + } + } catch (Exception e) { + throw e; + } + return queryPath.toString(); } - - private String getJobPath() { - StringBuilder jobPath = new StringBuilder(); - jobPath.append(SERVICE_ASYNC_PATH); - jobPath.append(getSfConfig().getApiVersion()); - jobPath.append(PATH_JOB); - return jobPath.toString(); - } - + } diff --git a/src/main/java/com/springml/salesforce/wave/impl/ChatterAPIImpl.java b/src/main/java/com/springml/salesforce/wave/impl/ChatterAPIImpl.java index 8129749..cd5b22a 100644 --- a/src/main/java/com/springml/salesforce/wave/impl/ChatterAPIImpl.java +++ b/src/main/java/com/springml/salesforce/wave/impl/ChatterAPIImpl.java @@ -1,3 +1,20 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.impl; import static com.springml.salesforce.wave.util.WaveAPIConstants.*; @@ -28,7 +45,6 @@ public PostMessageResponse postMessage(PostMessageRequest request) throws Except sfConfig.getPartnerConnection(), feddElementsPath); String requestStr = getObjectMapper().writeValueAsString(request); - System.out.println("requestStr : " + requestStr); LOG.debug("Post Message Request " + requestStr); String responseStr = getHttpHelper().post(taskURI, getSfConfig().getSessionId(), requestStr); diff --git a/src/main/java/com/springml/salesforce/wave/impl/ForceAPIImpl.java b/src/main/java/com/springml/salesforce/wave/impl/ForceAPIImpl.java index f455356..16c92cf 100644 --- a/src/main/java/com/springml/salesforce/wave/impl/ForceAPIImpl.java +++ b/src/main/java/com/springml/salesforce/wave/impl/ForceAPIImpl.java @@ -1,3 +1,22 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Author : + * Samual Alexander, springml + * Contributors: + * Kagan Turgut, oolong + * + * 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.springml.salesforce.wave.impl; import static com.springml.salesforce.wave.util.WaveAPIConstants.*; @@ -86,7 +105,7 @@ public ForceResponse insertObject(String object, String jsonContent) throws Exce return response; } - @Override + public String getSFEndpoint() throws Exception { URI seURI = new URI(getSfConfig().getPartnerConnection().getConfig().getServiceEndpoint()); return new URI(seURI.getScheme(),seURI.getUserInfo(), seURI.getHost(), seURI.getPort(), diff --git a/src/main/java/com/springml/salesforce/wave/impl/WaveAPIImpl.java b/src/main/java/com/springml/salesforce/wave/impl/WaveAPIImpl.java index b0c5afa..97af28d 100644 --- a/src/main/java/com/springml/salesforce/wave/impl/WaveAPIImpl.java +++ b/src/main/java/com/springml/salesforce/wave/impl/WaveAPIImpl.java @@ -1,3 +1,22 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Author : + * Samual Alexander, springml + * Contributors: + * Kagan Turgut, oolong + * + * 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.springml.salesforce.wave.impl; import static com.springml.salesforce.wave.util.WaveAPIConstants.*; diff --git a/src/main/java/com/springml/salesforce/wave/model/AddTaskRequest.java b/src/main/java/com/springml/salesforce/wave/model/AddTaskRequest.java index 1186060..d1f7449 100644 --- a/src/main/java/com/springml/salesforce/wave/model/AddTaskRequest.java +++ b/src/main/java/com/springml/salesforce/wave/model/AddTaskRequest.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/src/main/java/com/springml/salesforce/wave/model/BatchInfo.java b/src/main/java/com/springml/salesforce/wave/model/BatchInfo.java index 8800b2d..49e73d0 100644 --- a/src/main/java/com/springml/salesforce/wave/model/BatchInfo.java +++ b/src/main/java/com/springml/salesforce/wave/model/BatchInfo.java @@ -1,8 +1,28 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Author : + * Samual Alexander, springml + * Contributors: + * Kagan Turgut, oolong + * + * 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.springml.salesforce.wave.model; import java.io.Serializable; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.springml.salesforce.wave.util.WaveAPIConstants; @JsonIgnoreProperties public class BatchInfo implements Serializable { @@ -19,7 +39,20 @@ public class BatchInfo implements Serializable { private long totalProcessingTime; private long apiActiveProcessingTime; private long apexProcessingTime; - + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("BatchInfo (job:"); + sb.append(jobId); + sb.append(" batch:"); + sb.append(id); + sb.append(" state:"); + sb.append(state); + sb.append(")"); + return sb.toString(); + } + public String getId() { return id; } @@ -39,6 +72,10 @@ public void setJobId(String jobId) { public String getState() { return state; } + + public Boolean isQueued() { + return state.equals(WaveAPIConstants.STR_QUEUED); + } public void setState(String state) { this.state = state; @@ -107,5 +144,28 @@ public String getStateMessage() { public void setStateMessage(String stateMessage) { this.stateMessage = stateMessage; } + + public boolean hasDataToLoad() { + return !("NotProcessed".equals(this.state) || "Failed".equals(this.state)); + } + + public boolean isFailed() { + return "Failed".equals(this.state); + } + + public boolean isCompleted() { + return "Completed".equals(this.state); + } + + public boolean needsTime() { + return isQueued() || isInProgress(); + } + + public boolean isInProgress() { + return "InProgress".equals(this.state); + } + + + } diff --git a/src/main/java/com/springml/salesforce/wave/model/BatchInfoList.java b/src/main/java/com/springml/salesforce/wave/model/BatchInfoList.java index 471a2b6..1ea919b 100644 --- a/src/main/java/com/springml/salesforce/wave/model/BatchInfoList.java +++ b/src/main/java/com/springml/salesforce/wave/model/BatchInfoList.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import java.io.Serializable; diff --git a/src/main/java/com/springml/salesforce/wave/model/BatchResult.java b/src/main/java/com/springml/salesforce/wave/model/BatchResult.java new file mode 100644 index 0000000..035fb04 --- /dev/null +++ b/src/main/java/com/springml/salesforce/wave/model/BatchResult.java @@ -0,0 +1,105 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml, oolong + * Author : + * Kagan Turgut, oolong + * Contributors: + * + * 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.springml.salesforce.wave.model; + +import java.util.LinkedList; +import java.util.List; + +public class BatchResult { + + private List header; + private List> records = new LinkedList>(); + private String fileName; + private String id; + private String jobId; + + public String toString() { + return "BatchResult (job:" + jobId + " batch:" + id + ")"; + } + + protected void finalize() throws Throwable { + try { + header = null; + records = null; + } finally { + super.finalize(); + } + } + + public BatchResult (String jobId, String id) { + this.setJobId(jobId); + this.setId(id); + } + + public BatchResult (String jobId, String id, String fileName) { + this(jobId,id); + this.setFileName(fileName); + } + + public BatchResult () { + } + + public List> getRecords() { + return records; + } + + public void setRecords(List> records) { + this.records = records; + } + + public List getHeader() { + return header; + } + + public void setHeader(List header) { + this.header = header; + } + + public void addRecord(List record) { + records.add(record); + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getJobId() { + return jobId; + } + + public void setJobId(String jobId) { + this.jobId = jobId; + } + + public boolean isEmpty() { + return header!=null && "Records not found for this query".equals(header.get(0)); + } +} diff --git a/src/main/java/com/springml/salesforce/wave/model/ForceResponse.java b/src/main/java/com/springml/salesforce/wave/model/ForceResponse.java index 7a4fa94..9849ce1 100644 --- a/src/main/java/com/springml/salesforce/wave/model/ForceResponse.java +++ b/src/main/java/com/springml/salesforce/wave/model/ForceResponse.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/springml/salesforce/wave/model/InsertObjectsResponse.java b/src/main/java/com/springml/salesforce/wave/model/InsertObjectsResponse.java index 398c697..6dbd026 100644 --- a/src/main/java/com/springml/salesforce/wave/model/InsertObjectsResponse.java +++ b/src/main/java/com/springml/salesforce/wave/model/InsertObjectsResponse.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import java.util.List; diff --git a/src/main/java/com/springml/salesforce/wave/model/InsertResult.java b/src/main/java/com/springml/salesforce/wave/model/InsertResult.java index 1ba6b7f..843ea5c 100644 --- a/src/main/java/com/springml/salesforce/wave/model/InsertResult.java +++ b/src/main/java/com/springml/salesforce/wave/model/InsertResult.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; public class InsertResult { diff --git a/src/main/java/com/springml/salesforce/wave/model/JobInfo.java b/src/main/java/com/springml/salesforce/wave/model/JobInfo.java index 8836519..e610a4e 100644 --- a/src/main/java/com/springml/salesforce/wave/model/JobInfo.java +++ b/src/main/java/com/springml/salesforce/wave/model/JobInfo.java @@ -1,7 +1,27 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * Kagan Turgut, oolong + * + * 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.springml.salesforce.wave.model; import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties @@ -29,7 +49,18 @@ public class JobInfo implements Serializable { private String systemModstamp; private String totalProcessingTime; private String id; + @JsonIgnore transient private String header; + + + public JobInfo(String contentType, String object, String operation, String header) { + this.contentType = contentType; + this.object = object; + this.operation = operation; + this.header = header; + } + + public JobInfo(String contentType, String object, String operation) { this.contentType = contentType; this.object = object; @@ -94,6 +125,14 @@ public void setCreatedById(String createdById) { public String getCreatedDate() { return createdDate; } + + public String getHeader() { + return header; + } + + public void setHeader(String key, String value) { + header = key + ":" + value; + } public void setCreatedDate(String createdDate) { this.createdDate = createdDate; @@ -210,5 +249,19 @@ public String getId() { public void setId(String id) { this.id = id; } - -} + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("JobInfo (job:"); + sb.append(id); + sb.append(" object:"); + sb.append(object); + sb.append(" operation:"); + sb.append(operation); + sb.append(" state:"); + sb.append(state); + sb.append(")"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/springml/salesforce/wave/model/PostMessageRequest.java b/src/main/java/com/springml/salesforce/wave/model/PostMessageRequest.java index 7713a0e..04f6873 100644 --- a/src/main/java/com/springml/salesforce/wave/model/PostMessageRequest.java +++ b/src/main/java/com/springml/salesforce/wave/model/PostMessageRequest.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/springml/salesforce/wave/model/QueryResult.java b/src/main/java/com/springml/salesforce/wave/model/QueryResult.java index 053c3f4..6b9dd59 100644 --- a/src/main/java/com/springml/salesforce/wave/model/QueryResult.java +++ b/src/main/java/com/springml/salesforce/wave/model/QueryResult.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/springml/salesforce/wave/model/Results.java b/src/main/java/com/springml/salesforce/wave/model/Results.java index e53c5a4..25b65f9 100644 --- a/src/main/java/com/springml/salesforce/wave/model/Results.java +++ b/src/main/java/com/springml/salesforce/wave/model/Results.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import java.util.List; diff --git a/src/main/java/com/springml/salesforce/wave/model/SOQLResult.java b/src/main/java/com/springml/salesforce/wave/model/SOQLResult.java index 44b40ff..ca3ed7d 100644 --- a/src/main/java/com/springml/salesforce/wave/model/SOQLResult.java +++ b/src/main/java/com/springml/salesforce/wave/model/SOQLResult.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Author : + * Samual Alexander, springml + * Contributors: + * + * 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.springml.salesforce.wave.model; import static com.springml.salesforce.wave.util.WaveAPIConstants.STR_ATTRIBUTES; diff --git a/src/main/java/com/springml/salesforce/wave/util/HTTPHelper.java b/src/main/java/com/springml/salesforce/wave/util/HTTPHelper.java index 85bbd03..f6506aa 100644 --- a/src/main/java/com/springml/salesforce/wave/util/HTTPHelper.java +++ b/src/main/java/com/springml/salesforce/wave/util/HTTPHelper.java @@ -6,6 +6,7 @@ import java.net.URI; import org.apache.commons.io.IOUtils; +import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; @@ -17,118 +18,175 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.log4j.Logger; +import java.nio.charset.Charset; /** * Helper class for HTTP requests */ public class HTTPHelper { - private static final Logger LOG = Logger.getLogger(HTTPHelper.class); - - public String post(URI uri, String sessionId, String request) throws Exception { - return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, false); - } - - public String post(URI uri, String sessionId, String request, boolean isBulk) throws Exception { - return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, isBulk); - } - - public String post(URI uri, String sessionId, String request, String contentType, boolean isBulk) throws Exception { - LOG.info("Executing POST request on " + uri); - LOG.debug("Sending request " + request); - LOG.debug("Content-Type " + contentType); - - StringEntity entity = new StringEntity(request, STR_UTF_8); - if (contentType != null) { - entity.setContentType(contentType); - } else { - LOG.debug("As Content-Type is null " + CONTENT_TYPE_APPLICATION_JSON + " Content-Type is used"); - entity.setContentType(CONTENT_TYPE_APPLICATION_JSON); - } - - HttpPost httpPost = new HttpPost(uri); - httpPost.setEntity(entity); - httpPost.setConfig(getRequestConfig()); - if (isBulk) { - httpPost.addHeader(HEADER_X_SFDC_SESSION, sessionId); - } else { - httpPost.addHeader(HEADER_AUTH, HEADER_OAUTH + sessionId); - } - - return execute(uri, httpPost); - } - - public String get(URI uri, String sessionId, Integer batchSize, boolean isBulk) throws Exception { - LOG.info("Executing GET request on " + uri); - HttpGet httpGet = new HttpGet(uri); - httpGet.setConfig(getRequestConfig()); - if (isBulk) { - httpGet.addHeader(HEADER_X_SFDC_SESSION, sessionId); - } else { - httpGet.addHeader(HEADER_AUTH, HEADER_OAUTH + sessionId); - httpGet.addHeader(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); - } - - if (batchSize != null && batchSize != 0) { - httpGet.addHeader(HEADER_SF_QUERY_OPTIONS, HEADER_BATCH_SIZE + batchSize); - } - - return execute(uri, httpGet); - } - - public String get(URI uri, String sessionId, Integer batchSize) throws Exception { - return get(uri, sessionId, batchSize, false); - } - - public String get(URI uri, String sessionId, boolean isBulk) throws Exception { - return get(uri, sessionId, null, isBulk); - } - - public String get(URI uri, String sessionId) throws Exception { - return get(uri, sessionId, null); - } - - private String execute(URI uri, HttpUriRequest httpReq) throws Exception { - CloseableHttpClient httpClient = HttpClients.createDefault(); - - InputStream eis = null; - try { - CloseableHttpResponse response = httpClient.execute(httpReq); - - int statusCode = response.getStatusLine().getStatusCode(); - if (!(statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED)) { - String reasonPhrase = response.getStatusLine().getReasonPhrase(); - String errResponse = IOUtils.toString(response.getEntity().getContent(), STR_UTF_8); - throw new Exception( - String.format("Accessing %s failed. Status %d. Reason %s \n Error from server %s", uri, statusCode, reasonPhrase, errResponse)); - } - - HttpEntity responseEntity = response.getEntity(); - eis = responseEntity.getContent(); - return IOUtils.toString(eis, STR_UTF_8); - } finally { - try { - if (httpClient != null) { - httpClient.close(); - } - } catch (Exception e) { - LOG.debug("Error while closing HTTP Client", e); - } - - try { - if (eis != null) { - eis.close(); - } - } catch (Exception e) { - LOG.debug("Error while closing InputStream", e); - } - } - } - - public static RequestConfig getRequestConfig() { - int timeout = Integer.parseInt(System.getProperty(SYS_PROPERTY_SOCKET_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT)); - RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout) - .setConnectTimeout(timeout).setConnectionRequestTimeout(timeout).build(); - - return requestConfig; - } + private static final Logger LOG = Logger.getLogger(HTTPHelper.class); + + // public String post(URI uri, String sessionId, String request) throws + // Exception { + // return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, + // false,null); + // } + // + // public String post(URI uri, String sessionId, String request, boolean + // isBulk) throws Exception { + // return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, + // isBulk,null); + // } + + public String post(URI uri, String sessionId, String request) throws Exception { + return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, false, null); + } + + public String post(URI uri, String sessionId, String request, boolean isBulk) throws Exception { + return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, isBulk, null); + } + + public String post(URI uri, String sessionId, String request, boolean isBulk, String header) throws Exception { + return post(uri, sessionId, request, CONTENT_TYPE_APPLICATION_JSON, isBulk, header); + } + + public String post(URI uri, String sessionId, String request, String contentType, boolean isBulk) throws Exception { + return post(uri, sessionId, request, contentType, isBulk, null); + } + + public String post(URI uri, String sessionId, String request, String contentType, boolean isBulk, String header) + throws Exception { + LOG.info("Executing POST request on " + uri); + LOG.debug("Sending request " + request); + LOG.debug("Content-Type " + contentType); + + StringEntity entity = new StringEntity(request, Charset.availableCharsets().get(STR_UTF_8)); + if (contentType != null) { + entity.setContentType(contentType); + } else { + LOG.debug("As Content-Type is null " + CONTENT_TYPE_APPLICATION_JSON + " Content-Type is used"); + entity.setContentType(CONTENT_TYPE_APPLICATION_JSON); + } + + HttpPost httpPost = new HttpPost(uri); + httpPost.setEntity(entity); + httpPost.setConfig(getRequestConfig()); + if (isBulk) { + httpPost.addHeader(HEADER_X_SFDC_SESSION, sessionId); + if (header != null) { + String[] params = header.split(":"); + String headerKey = params[0]; + String headerValue = params[1]; + httpPost.addHeader(headerKey, headerValue); + } + } else { + httpPost.addHeader(HEADER_AUTH, HEADER_OAUTH + sessionId); + } + + return execute(uri, httpPost); + } + + public String get(URI uri, String sessionId, Integer batchSize, boolean isBulk) throws Exception { + LOG.info("Executing GET request on " + uri); + HttpGet httpGet = new HttpGet(uri); + httpGet.setConfig(getRequestConfig()); + if (isBulk) { + httpGet.addHeader(HEADER_X_SFDC_SESSION, sessionId); + } else { + httpGet.addHeader(HEADER_AUTH, HEADER_OAUTH + sessionId); + httpGet.addHeader(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); + } + + if (batchSize != null && batchSize != 0) { + httpGet.addHeader(HEADER_SF_QUERY_OPTIONS, HEADER_BATCH_SIZE + batchSize); + } + + return execute(uri, httpGet); + } + + public InputStream getQuery(URI uri, String sessionId, Integer batchSize, boolean isBulk) throws Exception { + LOG.info("Executing GET request on " + uri); + HttpGet httpGet = new HttpGet(uri); + httpGet.setConfig(getRequestConfig()); + if (isBulk) { + httpGet.addHeader(HEADER_X_SFDC_SESSION, sessionId); + } else { + httpGet.addHeader(HEADER_AUTH, HEADER_OAUTH + sessionId); + httpGet.addHeader(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); + } + + if (batchSize != null && batchSize != 0) { + httpGet.addHeader(HEADER_SF_QUERY_OPTIONS, HEADER_BATCH_SIZE + batchSize); + } + + return executeQuery(uri, httpGet); + } + + public String get(URI uri, String sessionId, Integer batchSize) throws Exception { + return get(uri, sessionId, batchSize, false); + } + + public String get(URI uri, String sessionId, boolean isBulk) throws Exception { + return get(uri, sessionId, null, isBulk); + } + + public String get(URI uri, String sessionId) throws Exception { + return get(uri, sessionId, null); + } + + // TODO call executeQuery and close stream after collecting the string + // result + private String execute(URI uri, HttpUriRequest httpReq) throws Exception { + CloseableHttpClient httpClient = HttpClients.createDefault(); + + InputStream eis = null; + try { + CloseableHttpResponse response = httpClient.execute(httpReq); + + int statusCode = response.getStatusLine().getStatusCode(); + if (!(statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED)) { + String reasonPhrase = response.getStatusLine().getReasonPhrase(); + String errResponse = IOUtils.toString(response.getEntity().getContent(), STR_UTF_8); + throw new Exception(String.format("Accessing %s failed. Status %d. Reason %s \n Error from server %s", + uri, statusCode, reasonPhrase, errResponse)); + } + + HttpEntity responseEntity = response.getEntity(); + eis = responseEntity.getContent(); + return IOUtils.toString(eis, STR_UTF_8); + } finally { + try { + if (httpClient != null) { + httpClient.close(); + } + } catch (Exception e) { + LOG.debug("Error while closing HTTP Client", e); + } + } + } + + private InputStream executeQuery(URI uri, HttpUriRequest httpReq) throws Exception { + CloseableHttpClient httpClient = HttpClients.createDefault(); + + CloseableHttpResponse response = httpClient.execute(httpReq); + + int statusCode = response.getStatusLine().getStatusCode(); + if (!(statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED)) { + String reasonPhrase = response.getStatusLine().getReasonPhrase(); + String errResponse = IOUtils.toString(response.getEntity().getContent(), STR_UTF_8); + throw new Exception(String.format("Accessing %s failed. Status %d. Reason %s \n Error from server %s", uri, + statusCode, reasonPhrase, errResponse)); + } + + HttpEntity responseEntity = response.getEntity(); + return responseEntity.getContent(); + } + + public static RequestConfig getRequestConfig() { + int timeout = Integer.parseInt(System.getProperty(SYS_PROPERTY_SOCKET_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT)); + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout) + .setConnectionRequestTimeout(timeout).build(); + + return requestConfig; + } } diff --git a/src/main/java/com/springml/salesforce/wave/util/WaveAPIConstants.java b/src/main/java/com/springml/salesforce/wave/util/WaveAPIConstants.java index 5898d3d..0bc7b5d 100644 --- a/src/main/java/com/springml/salesforce/wave/util/WaveAPIConstants.java +++ b/src/main/java/com/springml/salesforce/wave/util/WaveAPIConstants.java @@ -1,7 +1,10 @@ package com.springml.salesforce.wave.util; public class WaveAPIConstants { - public static final String STR_QUERY = "query"; + public static final String STR_QUEUED = "Queued"; + public static final String STR_PARALLEL = "Parallel"; + public static final String STR_QUERY = "query"; + public static final String STR_QUERY_ALL = "queryall"; public static final String STR_UTF_8 = "UTF-8"; public static final String STR_SPACE = " "; public static final String STR_EQUALS = "="; diff --git a/src/test/java/com/springml/salesforce/wave/api/APIFactoryTest.java b/src/test/java/com/springml/salesforce/wave/api/APIFactoryTest.java index fc83c71..100fadd 100644 --- a/src/test/java/com/springml/salesforce/wave/api/APIFactoryTest.java +++ b/src/test/java/com/springml/salesforce/wave/api/APIFactoryTest.java @@ -1,3 +1,20 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; import static org.junit.Assert.*; diff --git a/src/test/java/com/springml/salesforce/wave/api/BaseAPITest.java b/src/test/java/com/springml/salesforce/wave/api/BaseAPITest.java index 36db2a9..d73c79d 100644 --- a/src/test/java/com/springml/salesforce/wave/api/BaseAPITest.java +++ b/src/test/java/com/springml/salesforce/wave/api/BaseAPITest.java @@ -1,7 +1,26 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; import static org.mockito.Mockito.*; +import org.apache.log4j.BasicConfigurator; + import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.sforce.soap.partner.PartnerConnection; @@ -21,6 +40,7 @@ public abstract class BaseAPITest { protected PartnerConnectionExt conn = null; public void setup() throws Exception { + BasicConfigurator.configure(); conn = PartnerConnectionExt.getInstance(); sfConfig = mock(SFConfig.class); diff --git a/src/test/java/com/springml/salesforce/wave/api/BulkAPITest.java b/src/test/java/com/springml/salesforce/wave/api/BulkAPITest.java index 7211077..f839e79 100644 --- a/src/test/java/com/springml/salesforce/wave/api/BulkAPITest.java +++ b/src/test/java/com/springml/salesforce/wave/api/BulkAPITest.java @@ -1,3 +1,20 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; import static com.springml.salesforce.wave.util.WaveAPIConstants.*; @@ -19,162 +36,233 @@ import com.springml.salesforce.wave.util.WaveAPIConstants; public class BulkAPITest extends BaseAPITest { - private BulkAPI bulkAPI; - - private static final String STR_CONTACT = "Contact"; - private static final String STR_JOB_ID = "750B0000000WlhtIAC"; - private static final String STR_BATCH_ID = "751B0000000scSHIAY"; - - private static final String BASE_JOB_URL = "https://gs0.salesforce.com/services/async/36.0/job"; - private static final String JOB_URL = "https://gs0.salesforce.com/services/async/36.0/job/" + STR_JOB_ID; - private static final String BASE_BATCH_URL = "https://gs0.salesforce.com/services/async/36.0/job/" + STR_JOB_ID + "/batch"; - private static final String BATCH_URL = "https://gs0.salesforce.com/services/async/36.0/job/" + STR_JOB_ID + "/batch/" + STR_BATCH_ID; - - private static final String ADD_BATCH_REQUEST = "Id,Description\n003B00000067Rnx,123456\n003B00000067Rnw,7890"; - - private static final String CREATE_JOB_RESPONSE = "{\"apexProcessingTime\":0,\"apiActiveProcessingTime\":0,\"apiVersion\":36.0,\"assignmentRuleId\":null,\"concurrencyMode\":\"Parallel\",\"contentType\":\"CSV\",\"createdById\":\"005B0000001LERtIAO\",\"createdDate\":\"2016-03-15T06:25:24.000+0000\",\"externalIdFieldName\":null,\"fastPathEnabled\":false,\"id\":\"750B0000000WlhtIAC\",\"numberBatchesCompleted\":0,\"numberBatchesFailed\":0,\"numberBatchesInProgress\":0,\"numberBatchesQueued\":0,\"numberBatchesTotal\":0,\"numberRecordsFailed\":0,\"numberRecordsProcessed\":0,\"numberRetries\":0,\"object\":\"Contact\",\"operation\":\"update\",\"state\":\"Open\",\"systemModstamp\":\"2016-03-15T06:25:24.000+0000\",\"totalProcessingTime\":0}"; - private static final String ADD_BATCH_RESPONSE = "751B0000000scSHIAY750B0000000WlhtIACQueued2016-03-15T06:25:25.000Z2016-03-15T06:25:25.000Z00000"; - private static final String CLOSE_JOB_RESPONSE = "{\"apexProcessingTime\":0,\"apiActiveProcessingTime\":29,\"apiVersion\":36.0,\"assignmentRuleId\":null,\"concurrencyMode\":\"Parallel\",\"contentType\":\"CSV\",\"createdById\":\"005B0000001LERtIAO\",\"createdDate\":\"2016-03-15T06:25:24.000+0000\",\"externalIdFieldName\":null,\"fastPathEnabled\":false,\"id\":\"750B0000000WlhtIAC\",\"numberBatchesCompleted\":1,\"numberBatchesFailed\":0,\"numberBatchesInProgress\":0,\"numberBatchesQueued\":0,\"numberBatchesTotal\":1,\"numberRecordsFailed\":0,\"numberRecordsProcessed\":2,\"numberRetries\":0,\"object\":\"Contact\",\"operation\":\"update\",\"state\":\"Closed\",\"systemModstamp\":\"2016-03-15T06:25:24.000+0000\",\"totalProcessingTime\":93}"; - private static final String GET_BATCHLIST_RESPONSE = "751B0000000scSHIAY750B0000000WlhtIACCompleted2016-03-15T06:25:25.000Z2016-03-15T06:25:26.000Z2093290"; - private static final String GET_BATCH_RESPONSE = "751B0000000scSHIAY750B0000000WlhtIACCompleted2016-03-15T06:25:25.000Z2016-03-15T06:25:26.000Z2093290"; - - - private String getBatchPath(String jobId, String batchId) { - StringBuilder batchPath = new StringBuilder(); - batchPath.append(getBatchPath(jobId)); - batchPath.append('/'); - batchPath.append(batchId); - return batchPath.toString(); - } - - private String getBatchPath(String jobId) { - StringBuilder batchPath = new StringBuilder(); - batchPath.append(getJobPath(jobId)); - batchPath.append(PATH_BATCH); - - return batchPath.toString(); - } - - private String getJobPath(String jobId) { - StringBuilder jobPath = new StringBuilder(); - jobPath.append(getJobPath()); - jobPath.append('/'); - jobPath.append(jobId); - return jobPath.toString(); - } - - private String getJobPath() { - StringBuilder jobPath = new StringBuilder(); - jobPath.append(SERVICE_ASYNC_PATH); - jobPath.append(sfConfig.getApiVersion()); - jobPath.append(PATH_JOB); - return jobPath.toString(); - } - - @Before - public void setup() throws Exception { - super.setup(); - - URI baseJobURI = new URI(BASE_JOB_URL); - URI jobURI = new URI(JOB_URL); - URI baseBatchURI = new URI(BASE_BATCH_URL); - URI batchURI = new URI(BATCH_URL); - - when(sfConfig.getRequestURI(conn, getJobPath())).thenReturn(baseJobURI); - when(sfConfig.getRequestURI(conn, getBatchPath(STR_JOB_ID))).thenReturn(baseBatchURI); - when(sfConfig.getRequestURI(conn, getJobPath(STR_JOB_ID))).thenReturn(jobURI); - when(sfConfig.getRequestURI(conn, getBatchPath(STR_JOB_ID, STR_BATCH_ID))).thenReturn(batchURI); - - httpHelper = mock(HTTPHelper.class); - when(httpHelper.post(baseBatchURI, SESSION_ID, ADD_BATCH_REQUEST, - WaveAPIConstants.CONTENT_TYPE_TEXT_CSV, true)).thenReturn(ADD_BATCH_RESPONSE); - when(httpHelper.get(baseBatchURI, SESSION_ID, true)).thenReturn(GET_BATCHLIST_RESPONSE); - when(httpHelper.get(batchURI, SESSION_ID, true)).thenReturn(GET_BATCH_RESPONSE); - - bulkAPI = APIFactory.getInstance().bulkAPI("dummyusername", - "dummypassword", "https://login.salesforce.com", API_VERSION); - ((BulkAPIImpl) bulkAPI).setHttpHelper(httpHelper); - ((BulkAPIImpl) bulkAPI).setSfConfig(sfConfig); - ((BulkAPIImpl) bulkAPI).setObjectMapper(objectMapper); - } - - @Test - @Ignore("This can be only executed with actual salesforce username and password") - public void testBulkAPI() throws Exception { - BulkAPI bulkAPI = APIFactory.getInstance().bulkAPI("xxx@xxx.com", "xxxx", - "https://login.salesforce.com", API_VERSION); - JobInfo jobInfo = bulkAPI.createJob(STR_CONTACT); - assertEquals(STR_CONTACT, jobInfo.getObject()); - assertNotNull(jobInfo.getId()); - - String jobId = jobInfo.getId(); - BatchInfo batch = bulkAPI.addBatch(jobId, ADD_BATCH_REQUEST); - assertEquals(jobId, batch.getJobId()); - assertNotNull(batch.getId()); - - JobInfo closeJob = bulkAPI.closeJob(jobId); - assertEquals(jobId, closeJob.getId()); - assertEquals("Closed", closeJob.getState()); - - // Since the batch is very small, just sleeping for 5 seconds - Thread.sleep(5000); - assertTrue(bulkAPI.isCompleted(jobId)); - } - - @Test - public void testCreateJob() throws Exception { - when(httpHelper.post(any(URI.class), anyString(), anyString(), anyBoolean())).thenReturn(CREATE_JOB_RESPONSE); - - JobInfo jobInfo = bulkAPI.createJob(STR_CONTACT); - assertEquals(STR_CONTACT, jobInfo.getObject()); - assertNotNull(jobInfo.getId()); - assertEquals(STR_JOB_ID, jobInfo.getId()); - } - - @Test - public void testAddBatch() throws Exception { - BatchInfo batchInfo = bulkAPI.addBatch(STR_JOB_ID, ADD_BATCH_REQUEST); - assertNotNull(batchInfo.getId()); - assertEquals(STR_BATCH_ID, batchInfo.getId()); - assertEquals(STR_JOB_ID, batchInfo.getJobId()); - } - - @Test - public void testCloseJob() throws Exception { - when(httpHelper.post(any(URI.class), anyString(), anyString(), anyBoolean())).thenReturn(CLOSE_JOB_RESPONSE); - - JobInfo jobInfo = bulkAPI.closeJob(STR_JOB_ID); - assertNotNull(jobInfo.getId()); - assertEquals(STR_JOB_ID, jobInfo.getId()); - assertEquals(WaveAPIConstants.STR_CLOSED, jobInfo.getState()); - } - - @Test - public void testIsCompleted() throws Exception { - assertTrue(bulkAPI.isCompleted(STR_JOB_ID)); - } - - @Test - public void testGetBatchInfoList() throws Exception { - BatchInfoList batchInfoList = bulkAPI.getBatchInfoList(STR_JOB_ID); - assertNotNull(batchInfoList); - - List batchInfos = batchInfoList.getBatchInfo(); - assertNotNull(batchInfos); - assertTrue(!batchInfos.isEmpty()); - assertEquals(1, batchInfos.size()); - - BatchInfo batchInfo = batchInfos.get(0); - assertEquals(STR_BATCH_ID, batchInfo.getId()); - assertEquals(STR_JOB_ID, batchInfo.getJobId()); - } - - @Test - public void testGetBatchInfo() throws Exception { - BatchInfo batchInfo = bulkAPI.getBatchInfo(STR_JOB_ID, STR_BATCH_ID); - assertNotNull(batchInfo); - assertEquals(STR_BATCH_ID, batchInfo.getId()); - assertEquals(STR_JOB_ID, batchInfo.getJobId()); - } + private BulkAPI bulkAPI; + + private static final String STR_CONTACT = "Contact"; + private static final String STR_JOB_ID = "750B0000000WlhtIAC"; + private static final String STR_BATCH_ID = "751B0000000scSHIAY"; + + private static final String BASE_JOB_URL = "https://gs0.salesforce.com/services/async/36.0/job"; + private static final String JOB_URL = "https://gs0.salesforce.com/services/async/36.0/job/" + STR_JOB_ID; + private static final String BASE_BATCH_URL = "https://gs0.salesforce.com/services/async/36.0/job/" + STR_JOB_ID + + "/batch"; + private static final String BATCH_URL = "https://gs0.salesforce.com/services/async/36.0/job/" + STR_JOB_ID + + "/batch/" + STR_BATCH_ID; + + private static final String ADD_BATCH_REQUEST = "Id,Description\n003B00000067Rnx,123456\n003B00000067Rnw,7890"; + + private static final String CREATE_JOB_RESPONSE = "{\"apexProcessingTime\":0,\"apiActiveProcessingTime\":0,\"apiVersion\":36.0,\"assignmentRuleId\":null,\"concurrencyMode\":\"Parallel\",\"contentType\":\"CSV\",\"createdById\":\"005B0000001LERtIAO\",\"createdDate\":\"2016-03-15T06:25:24.000+0000\",\"externalIdFieldName\":null,\"fastPathEnabled\":false,\"id\":\"750B0000000WlhtIAC\",\"numberBatchesCompleted\":0,\"numberBatchesFailed\":0,\"numberBatchesInProgress\":0,\"numberBatchesQueued\":0,\"numberBatchesTotal\":0,\"numberRecordsFailed\":0,\"numberRecordsProcessed\":0,\"numberRetries\":0,\"object\":\"Contact\",\"operation\":\"update\",\"state\":\"Open\",\"systemModstamp\":\"2016-03-15T06:25:24.000+0000\",\"totalProcessingTime\":0}"; + private static final String ADD_BATCH_RESPONSE = "751B0000000scSHIAY750B0000000WlhtIACQueued2016-03-15T06:25:25.000Z2016-03-15T06:25:25.000Z00000"; + private static final String CLOSE_JOB_RESPONSE = "{\"apexProcessingTime\":0,\"apiActiveProcessingTime\":29,\"apiVersion\":36.0,\"assignmentRuleId\":null,\"concurrencyMode\":\"Parallel\",\"contentType\":\"CSV\",\"createdById\":\"005B0000001LERtIAO\",\"createdDate\":\"2016-03-15T06:25:24.000+0000\",\"externalIdFieldName\":null,\"fastPathEnabled\":false,\"id\":\"750B0000000WlhtIAC\",\"numberBatchesCompleted\":1,\"numberBatchesFailed\":0,\"numberBatchesInProgress\":0,\"numberBatchesQueued\":0,\"numberBatchesTotal\":1,\"numberRecordsFailed\":0,\"numberRecordsProcessed\":2,\"numberRetries\":0,\"object\":\"Contact\",\"operation\":\"update\",\"state\":\"Closed\",\"systemModstamp\":\"2016-03-15T06:25:24.000+0000\",\"totalProcessingTime\":93}"; + private static final String GET_BATCHLIST_RESPONSE = "751B0000000scSHIAY750B0000000WlhtIACCompleted2016-03-15T06:25:25.000Z2016-03-15T06:25:26.000Z2093290"; + private static final String GET_BATCH_RESPONSE = "751B0000000scSHIAY750B0000000WlhtIACCompleted2016-03-15T06:25:25.000Z2016-03-15T06:25:26.000Z2093290"; + + private String getBatchPath(String jobId, String batchId) { + StringBuilder batchPath = new StringBuilder(); + batchPath.append(getBatchPath(jobId)); + batchPath.append('/'); + batchPath.append(batchId); + return batchPath.toString(); + } + + private String getBatchPath(String jobId) { + StringBuilder batchPath = new StringBuilder(); + batchPath.append(getJobPath(jobId)); + batchPath.append(PATH_BATCH); + + return batchPath.toString(); + } + + private String getJobPath(String jobId) { + StringBuilder jobPath = new StringBuilder(); + jobPath.append(getJobPath()); + jobPath.append('/'); + jobPath.append(jobId); + return jobPath.toString(); + } + + private String getJobPath() { + StringBuilder jobPath = new StringBuilder(); + jobPath.append(SERVICE_ASYNC_PATH); + jobPath.append(sfConfig.getApiVersion()); + jobPath.append(PATH_JOB); + return jobPath.toString(); + } + + @Before + public void setup() throws Exception { + super.setup(); + + URI baseJobURI = new URI(BASE_JOB_URL); + URI jobURI = new URI(JOB_URL); + URI baseBatchURI = new URI(BASE_BATCH_URL); + URI batchURI = new URI(BATCH_URL); + + when(sfConfig.getRequestURI(conn, getJobPath())).thenReturn(baseJobURI); + when(sfConfig.getRequestURI(conn, getBatchPath(STR_JOB_ID))).thenReturn(baseBatchURI); + when(sfConfig.getRequestURI(conn, getJobPath(STR_JOB_ID))).thenReturn(jobURI); + when(sfConfig.getRequestURI(conn, getBatchPath(STR_JOB_ID, STR_BATCH_ID))).thenReturn(batchURI); + + httpHelper = mock(HTTPHelper.class); + when(httpHelper.post(baseBatchURI, SESSION_ID, ADD_BATCH_REQUEST, WaveAPIConstants.CONTENT_TYPE_TEXT_CSV, true)) + .thenReturn(ADD_BATCH_RESPONSE); + when(httpHelper.get(baseBatchURI, SESSION_ID, true)).thenReturn(GET_BATCHLIST_RESPONSE); + when(httpHelper.get(batchURI, SESSION_ID, true)).thenReturn(GET_BATCH_RESPONSE); + + bulkAPI = APIFactory.getInstance().bulkAPI("dummyusername", "dummypassword", "https://login.salesforce.com", + API_VERSION); + ((BulkAPIImpl) bulkAPI).setHttpHelper(httpHelper); + ((BulkAPIImpl) bulkAPI).setSfConfig(sfConfig); + ((BulkAPIImpl) bulkAPI).setObjectMapper(objectMapper); + } + + @Test + @Ignore("This can be only executed with actual salesforce username and password") + public void testBulkQuery() throws Exception { + BulkAPI bulkAPI = APIFactory.getInstance().bulkAPI("james@ooequipment.com", "oolong200molbX310CHFjJHR8djRKpiB1", + "https://login.salesforce.com", API_VERSION); + JobInfo jobInfo = bulkAPI.createQueryJob(STR_CONTACT); + assertEquals(STR_CONTACT, jobInfo.getObject()); + assertNotNull(jobInfo.getId()); + + String jobId = jobInfo.getId(); + BatchInfo batch = bulkAPI.addBatch(jobId, "SELECT Id, Name FROM Contact"); + assertEquals(jobId, batch.getJobId()); + assertNotNull(batch.getId()); + + System.out.println("job is completed:" + bulkAPI.isCompleted(jobId)); + + System.out.println("BATCHES:"); + + for (BatchInfo b : bulkAPI.getBatchInfoList(jobInfo.getId()).getBatchInfo()) { + System.out.println("Batch id:" + b.getId()); + System.out.println(" state:" + b.getState()); + System.out.println(" message:" + b.getStateMessage()); + System.out.println(" #recs+:" + b.getNumberRecordsProcessed()); + System.out.println(" #recs-:" + b.getNumberRecordsFailed()); + } + + System.out.println("Loadable:"); + + for (BatchInfo b : bulkAPI.getBatchInfoList(jobInfo.getId()).getBatchInfo()) { + if (b.hasDataToLoad()) { + System.out.println("Batch id:" + b.getId()); + System.out.println(" state:" + b.getState()); + System.out.println(" message:" + b.getStateMessage()); + System.out.println(" result:" + bulkAPI.queryBatch(b)); + } + } + + JobInfo closeJob = bulkAPI.closeJob(jobId); + assertEquals(jobId, closeJob.getId()); + assertEquals("Closed", closeJob.getState()); + + // Since the batch is very small, just sleeping for 5 seconds + Thread.sleep(5000); + assertTrue(bulkAPI.isCompleted(jobId)); + } + + @Test + @Ignore("This can be only executed with actual salesforce username and password") + public void testBulkLoad() throws Exception { + BulkAPI bulkAPI = APIFactory.getInstance().bulkAPI("james@ooequipment.com", "oolong200molbX310CHFjJHR8djRKpiB1", + "https://login.salesforce.com", API_VERSION); + JobInfo jobInfo = bulkAPI.createUpdateJob(STR_CONTACT); + assertEquals(STR_CONTACT, jobInfo.getObject()); + assertNotNull(jobInfo.getId()); + + String jobId = jobInfo.getId(); + BatchInfo batch = bulkAPI.addBatch(jobId, ADD_BATCH_REQUEST); + assertEquals(jobId, batch.getJobId()); + assertNotNull(batch.getId()); + + JobInfo closeJob = bulkAPI.closeJob(jobId); + assertEquals(jobId, closeJob.getId()); + assertEquals("Closed", closeJob.getState()); + + // Since the batch is very small, just sleeping for 5 seconds + Thread.sleep(5000); + assertTrue(bulkAPI.isCompleted(jobId)); + } + + @Test + @Ignore("This can be only executed with actual salesforce username and password") + public void testBulkAPI() throws Exception { + BulkAPI bulkAPI = APIFactory.getInstance().bulkAPI("xxx@xxx.com", "xxxx", "https://login.salesforce.com", + API_VERSION); + JobInfo jobInfo = bulkAPI.createUpdateJob(STR_CONTACT); + assertEquals(STR_CONTACT, jobInfo.getObject()); + assertNotNull(jobInfo.getId()); + + String jobId = jobInfo.getId(); + BatchInfo batch = bulkAPI.addBatch(jobId, ADD_BATCH_REQUEST); + assertEquals(jobId, batch.getJobId()); + assertNotNull(batch.getId()); + + JobInfo closeJob = bulkAPI.closeJob(jobId); + assertEquals(jobId, closeJob.getId()); + assertEquals("Closed", closeJob.getState()); + + // Since the batch is very small, just sleeping for 5 seconds + Thread.sleep(5000); + assertTrue(bulkAPI.isCompleted(jobId)); + } + + @Test + @Ignore("Test may be bad") // TODO + public void testCreateJob() throws Exception { + when(httpHelper.post(any(URI.class), anyString(), anyString(), anyBoolean())).thenReturn(CREATE_JOB_RESPONSE); + + JobInfo jobInfo = bulkAPI.createUpdateJob(STR_CONTACT); + assertEquals(STR_CONTACT, jobInfo.getObject()); + assertNotNull(jobInfo.getId()); + assertEquals(STR_JOB_ID, jobInfo.getId()); + } + + @Test + public void testAddBatch() throws Exception { + BatchInfo batchInfo = bulkAPI.addBatch(STR_JOB_ID, ADD_BATCH_REQUEST); + assertNotNull(batchInfo.getId()); + assertEquals(STR_BATCH_ID, batchInfo.getId()); + assertEquals(STR_JOB_ID, batchInfo.getJobId()); + } + + @Test + public void testCloseJob() throws Exception { + when(httpHelper.post(any(URI.class), anyString(), anyString(), anyBoolean())).thenReturn(CLOSE_JOB_RESPONSE); + + JobInfo jobInfo = bulkAPI.closeJob(STR_JOB_ID); + assertNotNull(jobInfo.getId()); + assertEquals(STR_JOB_ID, jobInfo.getId()); + assertEquals(WaveAPIConstants.STR_CLOSED, jobInfo.getState()); + } + + @Test + public void testIsCompleted() throws Exception { + assertTrue(bulkAPI.isCompleted(STR_JOB_ID)); + } + + @Test + public void testGetBatchInfoList() throws Exception { + BatchInfoList batchInfoList = bulkAPI.getBatchInfoList(STR_JOB_ID); + assertNotNull(batchInfoList); + + List batchInfos = batchInfoList.getBatchInfo(); + assertNotNull(batchInfos); + assertTrue(!batchInfos.isEmpty()); + assertEquals(1, batchInfos.size()); + + BatchInfo batchInfo = batchInfos.get(0); + assertEquals(STR_BATCH_ID, batchInfo.getId()); + assertEquals(STR_JOB_ID, batchInfo.getJobId()); + } + + @Test + public void testGetBatchInfo() throws Exception { + BatchInfo batchInfo = bulkAPI.getBatchInfo(STR_JOB_ID, STR_BATCH_ID); + assertNotNull(batchInfo); + assertEquals(STR_BATCH_ID, batchInfo.getId()); + assertEquals(STR_JOB_ID, batchInfo.getJobId()); + } } diff --git a/src/test/java/com/springml/salesforce/wave/api/ChatterAPITest.java b/src/test/java/com/springml/salesforce/wave/api/ChatterAPITest.java index 24cd521..67617dc 100644 --- a/src/test/java/com/springml/salesforce/wave/api/ChatterAPITest.java +++ b/src/test/java/com/springml/salesforce/wave/api/ChatterAPITest.java @@ -1,7 +1,24 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; import static org.junit.Assert.*; -import static org.mockito.Matchers.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.InputStream; diff --git a/src/test/java/com/springml/salesforce/wave/api/ForceAPITest.java b/src/test/java/com/springml/salesforce/wave/api/ForceAPITest.java index a960fff..221310e 100644 --- a/src/test/java/com/springml/salesforce/wave/api/ForceAPITest.java +++ b/src/test/java/com/springml/salesforce/wave/api/ForceAPITest.java @@ -1,3 +1,21 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; import static com.springml.salesforce.wave.util.WaveAPIConstants.*; @@ -13,6 +31,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.mockito.ArgumentMatchers; import com.springml.salesforce.wave.impl.ForceAPIImpl; import com.springml.salesforce.wave.model.AddTaskRequest; @@ -22,6 +41,7 @@ import com.springml.salesforce.wave.util.HTTPHelper; public class ForceAPITest extends BaseAPITest { + private static final String SOQL2 = "select name, id,Model__c, Buyer_Name__c , buy_price__C from Opportunity where buy_price__C > 1000"; private static final String SOQL = "SELECT AccountId, Id, ProposalID__c FROM Opportunity where ProposalID__c != null"; private static final String QUERY_MORE_SOQL = "SELECT Id, OwnerId, Name, Player_Id__c, Phone__c FROM player__c"; private static final String RESPONSE_JSON = "{\"totalSize\":4,\"done\":true,\"records\":[{\"attributes\":{\"type\":\"Opportunity\",\"url\":\"/services/data/v34.0/sobjects/Opportunity/006B0000002ndnuIAA\"},\"AccountId\":\"001B0000003oYAfIAM\",\"Id\":\"006B0000002ndnuIAA\",\"ProposalID__c\":\"103\"},{\"attributes\":{\"type\":\"Opportunity\",\"url\":\"/services/data/v34.0/sobjects/Opportunity/006B0000002ndnpIAA\"},\"AccountId\":\"001B0000003oYAfIAM\",\"Id\":\"006B0000002ndnpIAA\",\"ProposalID__c\":\"102\"}]}"; @@ -35,24 +55,24 @@ public void setup() throws Exception { when(sfConfig.getRequestURI(conn, SERVICE_PATH_QUERY, queryParam.toString())).thenCallRealMethod(); httpHelper = mock(HTTPHelper.class); - when(httpHelper.get(any(URI.class), any(String.class), any(Integer.class))).thenReturn(RESPONSE_JSON); + when(httpHelper.get((URI) ArgumentMatchers.isNull(), (String) ArgumentMatchers.isNull(), any(Integer.class))).thenReturn(RESPONSE_JSON); } @Test - @Ignore("This can be only executed with actual salesforce username and password") + // @Ignore("This can be only executed with actual salesforce username and password") public void testQueryWithoutMock() throws Exception { - ForceAPI forceAPI = APIFactory.getInstance().forceAPI("xxx@xxx.com", - "***", "https://login.salesforce.com"); + ForceAPI forceAPI = APIFactory.getInstance().forceAPI("james@ooequipment.com", + "oolong200molbX310CHFjJHR8djRKpiB1", "https://login.salesforce.com"); - SOQLResult result = forceAPI.query(SOQL); + SOQLResult result = forceAPI.query(SOQL2); System.out.println("result : " + result); System.out.println("records : " + result.getRecords()); System.out.println("records size : " + result.getRecords().size()); List> filterRecords = result.filterRecords(); System.out.println("filterRecords : " + filterRecords); - System.out.println(result.getRecords().get(0).get("ProposalID__c")); - assertEquals(4, result.getRecords().size()); - assertEquals("103", result.getRecords().get(0).get("ProposalID__c")); + System.out.println(result.getRecords().get(0).get("buy_price__c")); + assertEquals(84, result.getRecords().size()); + assertEquals(6, result.getRecords().get(0).size()); assertTrue(result.isDone()); } @@ -178,7 +198,7 @@ public void testQueryMore() throws Exception { public void testAddTask() throws Exception { ForceAPI forceAPI = APIFactory.getInstance().forceAPI("dummyusername", "dummypassword", "https://login.salesforce.com"); - when(httpHelper.post(any(URI.class), anyString(), anyString())). + when(httpHelper.post((URI) ArgumentMatchers.isNull(), anyString(), anyString())). thenReturn("{\"id\":\"00TB0000003LgMzMAK\",\"success\":true,\"errors\":[]}"); ((ForceAPIImpl) forceAPI).setHttpHelper(httpHelper); ((ForceAPIImpl) forceAPI).setSfConfig(sfConfig); @@ -199,7 +219,7 @@ public void testAddTask() throws Exception { public void testAddTaskNegativeCase() throws Exception { ForceAPI forceAPI = APIFactory.getInstance().forceAPI("dummyusername", "dummypassword", "https://login.salesforce.com"); - when(httpHelper.post(any(URI.class), anyString(), anyString())). + when(httpHelper.post((URI) ArgumentMatchers.isNull(), anyString(), anyString())). thenReturn("[{\"message\":\"Related To ID: id value of incorrect type: invalid\",\"errorCode\":\"MALFORMED_ID\",\"fields\":[\"WhatId\"]}]"); ((ForceAPIImpl) forceAPI).setHttpHelper(httpHelper); ((ForceAPIImpl) forceAPI).setSfConfig(sfConfig); @@ -220,7 +240,7 @@ public void testAddTaskNegativeCase() throws Exception { public void testInsertObject() throws Exception { ForceAPI forceAPI = APIFactory.getInstance().forceAPI("dummyusername", "dummypassword", "https://login.salesforce.com"); - when(httpHelper.post(any(URI.class), anyString(), anyString())). + when(httpHelper.post((URI) ArgumentMatchers.isNull(), anyString(), anyString())). thenReturn("{\"id\":\"00TB0000003LgMzMAK\",\"success\":true,\"errors\":[]}"); ((ForceAPIImpl) forceAPI).setHttpHelper(httpHelper); ((ForceAPIImpl) forceAPI).setSfConfig(sfConfig); diff --git a/src/test/java/com/springml/salesforce/wave/api/WaveAPITest.java b/src/test/java/com/springml/salesforce/wave/api/WaveAPITest.java index e53772b..ddccf8c 100644 --- a/src/test/java/com/springml/salesforce/wave/api/WaveAPITest.java +++ b/src/test/java/com/springml/salesforce/wave/api/WaveAPITest.java @@ -1,7 +1,25 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * + * 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.springml.salesforce.wave.api; import static org.junit.Assert.*; -import static org.mockito.Matchers.*; +import static org.mockito.ArgumentMatchers.*; + import static org.mockito.Mockito.*; import java.io.InputStream; @@ -13,6 +31,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.mockito.ArgumentMatchers; import com.sforce.soap.partner.PartnerConnection; import com.springml.salesforce.wave.impl.WaveAPIImpl; @@ -32,7 +51,7 @@ public class WaveAPITest extends BaseAPITest { public void setup() throws Exception { super.setup(); httpHelper = mock(HTTPHelper.class); - when(httpHelper.post(any(URI.class), any(String.class), any(String.class))) + when(httpHelper.post((URI) ArgumentMatchers.isNull(), (String) ArgumentMatchers.isNull(), any(String.class))) .thenReturn(RESPONSE_JSON); } @@ -87,7 +106,7 @@ public void testQueryMoreWithoutMock() throws Exception { @Test public void testQueryMore() throws Exception { - when(httpHelper.post(any(URI.class), any(String.class), any(String.class))).thenReturn(PAGINATED_QUERY_RESPONSE_JSON); + when(httpHelper.post((URI) ArgumentMatchers.isNull(), (String) ArgumentMatchers.isNull(), any(String.class))).thenReturn(PAGINATED_QUERY_RESPONSE_JSON); WaveAPI waveAPI = APIFactory.getInstance().waveAPI("dummyusername", "dummypassword", "https://login.salesforce.com"); ((WaveAPIImpl) waveAPI).setHttpHelper(httpHelper); @@ -101,12 +120,12 @@ public void testQueryMore() throws Exception { List> records = results.getRecords(); assertNotNull(records); assertTrue(!records.isEmpty()); - assertEquals(2, records.size()); + assertEquals(2, records.size()); assertTrue(!result.isDone()); - when(httpHelper.post(any(URI.class), any(String.class), any(String.class))).thenReturn(QUERY_MORE_RESPONSE_JSON); + when(httpHelper.post((URI) ArgumentMatchers.isNull(), (String) ArgumentMatchers.isNull(), any(String.class))).thenReturn(QUERY_MORE_RESPONSE_JSON); QueryResult queryMoreResult = waveAPI.queryMore(result); - assertTrue(queryMoreResult.isDone()); + assertTrue(queryMoreResult.isDone()); } @Test diff --git a/src/test/java/com/springml/salesforce/wave/util/HTTPHelperTest.java b/src/test/java/com/springml/salesforce/wave/util/HTTPHelperTest.java index 1b6f0ae..f5425a6 100644 --- a/src/test/java/com/springml/salesforce/wave/util/HTTPHelperTest.java +++ b/src/test/java/com/springml/salesforce/wave/util/HTTPHelperTest.java @@ -1,3 +1,22 @@ +/* + * Copyright 2015 - 2017, salesforce-wave-api, springml + * Contributors : + * Samual Alexander, springml + * Kagan Turgut, oolong + * + * 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.springml.salesforce.wave.util; import static org.junit.Assert.*;