Skip to content

Commit 08ecece

Browse files
committed
Merge branch 'release/1.6.0'
2 parents 711028b + aed2d55 commit 08ecece

File tree

11 files changed

+1966
-1300
lines changed

11 files changed

+1966
-1300
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
language: java
22
sudo: false
33
install: true
4+
dist: trusty
45
addons:
56
sonarcloud:
67
organization: channelape-github

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.channelape</groupId>
66
<artifactId>shopify-sdk</artifactId>
7-
<version>1.5.0</version>
7+
<version>1.6.0</version>
88

99
<name>Shopify SDK</name>
1010
<description>Java SDK for Shopify REST API.</description>

src/main/java/com/shopify/ShopifySdk.java

Lines changed: 85 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
import com.shopify.model.ShopifyCustomerRoot;
4949
import com.shopify.model.ShopifyCustomerUpdateRequest;
5050
import com.shopify.model.ShopifyCustomerUpdateRoot;
51+
import com.shopify.model.ShopifyCustomersRoot;
5152
import com.shopify.model.ShopifyFulfillment;
5253
import com.shopify.model.ShopifyFulfillmentCreationRequest;
5354
import com.shopify.model.ShopifyFulfillmentRoot;
5455
import com.shopify.model.ShopifyFulfillmentUpdateRequest;
56+
import com.shopify.model.ShopifyGetCustomersRequest;
5557
import com.shopify.model.ShopifyGiftCard;
5658
import com.shopify.model.ShopifyGiftCardCreationRequest;
5759
import com.shopify.model.ShopifyGiftCardRoot;
@@ -92,6 +94,10 @@
9294

9395
public class ShopifySdk {
9496

97+
private static final String EMPTY_STRING = "";
98+
99+
static final String RETRY_AFTER_HEADER = "Retry-After";
100+
95101
private static final String MINIMUM_REQUEST_RETRY_DELAY_CANNOT_BE_LARGER_THAN_MAXIMUM_REQUEST_RETRY_DELAY_MESSAGE = "Maximum request retry delay must be larger than minimum request retry delay.";
96102

97103
private static final String INVALID_MAXIMUM_REQUEST_RETRY_TIMEOUT_MESSAGE = "Maximum request retry timeout cannot be set lower than 2 seconds.";
@@ -131,7 +137,12 @@ public class ShopifySdk {
131137
static final String ANY_STATUSES = "any";
132138
static final String CREATED_AT_MIN_QUERY_PARAMETER = "created_at_min";
133139
static final String CREATED_AT_MAX_QUERY_PARAMETER = "created_at_max";
140+
static final String UPDATED_AT_MIN_QUERY_PARAMETER = "updated_at_min";
141+
static final String UPDATED_AT_MAX_QUERY_PARAMETER = "updated_at_max";
134142
static final String ATTRIBUTION_APP_ID_QUERY_PARAMETER = "attribution_app_id";
143+
static final String IDS_QUERY_PARAMETER = "ids";
144+
static final String SINCE_ID_QUERY_PARAMETER = "since_id";
145+
static final String QUERY_QUERY_PARAMETER = "query";
135146
static final String CALCULATE = "calculate";
136147
static final String REFUNDS = "refunds";
137148
static final String TRANSACTIONS = "transactions";
@@ -171,19 +182,20 @@ public class ShopifySdk {
171182
private long minimumRequestRetryRandomDelayMilliseconds;
172183
private long maximumRequestRetryRandomDelayMilliseconds;
173184
private long maximumRequestRetryTimeoutMilliseconds;
174-
private final ShopifySdkRetryListener shopifySdkRetryListener = new ShopifySdkRetryListener();
175185

176186
private static final Client CLIENT = buildClient();
177187

178188
private static final String CUSTOMERS = "customers";
189+
private static final String SEARCH = "search";
179190

180191
public static interface OptionalsStep {
181192

182193
/**
183-
* The Shopify SDK uses random waits in between retry attempts. Minimum duration
184-
* time to wait before retrying a failed request. Value must also be less than
185-
* {@link #withMaximumRequestRetryRandomDelay(int, TimeUnit) Maximum Request
186-
* Retry Random Delay}.<br>
194+
* The Shopify SDK uses random waits in between retry attempts. Minimum
195+
* duration time to wait before retrying a failed request. Value must
196+
* also be less than
197+
* {@link #withMaximumRequestRetryRandomDelay(int, TimeUnit) Maximum
198+
* Request Retry Random Delay}.<br>
187199
* Default value is: 1 second.
188200
*
189201
* @param duration
@@ -193,10 +205,11 @@ public static interface OptionalsStep {
193205
OptionalsStep withMinimumRequestRetryRandomDelay(int duration, TimeUnit timeUnit);
194206

195207
/**
196-
* The Shopify SDK uses random waits in between retry attempts. Maximum duration
197-
* time to wait before retrying a failed request. Value must also be more than
198-
* {@link #withMinimumRequestRetryRandomDelay(int, TimeUnit) Minimum Request
199-
* Retry Random Delay}.<br>
208+
* The Shopify SDK uses random waits in between retry attempts. Maximum
209+
* duration time to wait before retrying a failed request. Value must
210+
* also be more than
211+
* {@link #withMinimumRequestRetryRandomDelay(int, TimeUnit) Minimum
212+
* Request Retry Random Delay}.<br>
200213
* Default value is: 5 seconds.
201214
*
202215
* @param duration
@@ -569,6 +582,18 @@ public List<ShopifyOrder> getOrders(final DateTime mininumCreationDate, final Da
569582
return getOrders(mininumCreationDate, maximumCreationDate, page, DEFAULT_REQUEST_LIMIT);
570583
}
571584

585+
public List<ShopifyOrder> getUpdatedOrdersCreatedBefore(final DateTime minimumUpdatedAtDate,
586+
final DateTime maximumUpdatedAtDate, final DateTime maximumCreatedAtDate, final int page,
587+
final int pageSize) {
588+
final Response response = get(getWebTarget().path(ORDERS).queryParam(STATUS_QUERY_PARAMETER, ANY_STATUSES)
589+
.queryParam(LIMIT_QUERY_PARAMETER, pageSize)
590+
.queryParam(UPDATED_AT_MIN_QUERY_PARAMETER, minimumUpdatedAtDate.toString())
591+
.queryParam(UPDATED_AT_MAX_QUERY_PARAMETER, maximumUpdatedAtDate.toString())
592+
.queryParam(CREATED_AT_MAX_QUERY_PARAMETER, maximumCreatedAtDate.toString())
593+
.queryParam(PAGE_QUERY_PARAMETER, page));
594+
return getOrders(response);
595+
}
596+
572597
public List<ShopifyOrder> getOrders(final DateTime mininumCreationDate, final DateTime maximumCreationDate,
573598
final int page, final int pageSize) {
574599
final Response response = get(getWebTarget().path(ORDERS).queryParam(STATUS_QUERY_PARAMETER, ANY_STATUSES)
@@ -645,6 +670,44 @@ public ShopifyCustomer updateCustomer(final ShopifyCustomerUpdateRequest shopify
645670
return shopifyCustomerRootResponse.getCustomer();
646671
}
647672

673+
public ShopifyCustomer getCustomer(final String customerId) {
674+
final Response response = get(getWebTarget().path(CUSTOMERS).path(customerId));
675+
final ShopifyCustomerRoot shopifyCustomerRootResponse = response.readEntity(ShopifyCustomerRoot.class);
676+
return shopifyCustomerRootResponse.getCustomer();
677+
}
678+
679+
public List<ShopifyCustomer> getCustomers(final ShopifyGetCustomersRequest shopifyGetCustomersRequest) {
680+
WebTarget target = getWebTarget().path(CUSTOMERS);
681+
if (shopifyGetCustomersRequest.getPage() != 0) {
682+
target = target.queryParam(PAGE_QUERY_PARAMETER, shopifyGetCustomersRequest.getPage());
683+
}
684+
if (shopifyGetCustomersRequest.getLimit() != 0) {
685+
target = target.queryParam(LIMIT_QUERY_PARAMETER, shopifyGetCustomersRequest.getLimit());
686+
} else {
687+
target = target.queryParam(LIMIT_QUERY_PARAMETER, DEFAULT_REQUEST_LIMIT);
688+
}
689+
if (shopifyGetCustomersRequest.getIds() != null) {
690+
target = target.queryParam(IDS_QUERY_PARAMETER, String.join(",", shopifyGetCustomersRequest.getIds()));
691+
}
692+
if (shopifyGetCustomersRequest.getSinceId() != null) {
693+
target = target.queryParam(SINCE_ID_QUERY_PARAMETER, shopifyGetCustomersRequest.getSinceId());
694+
}
695+
if (shopifyGetCustomersRequest.getCreatedAtMin() != null) {
696+
target = target.queryParam(CREATED_AT_MIN_QUERY_PARAMETER, shopifyGetCustomersRequest.getCreatedAtMin());
697+
}
698+
if (shopifyGetCustomersRequest.getCreatedAtMax() != null) {
699+
target = target.queryParam(CREATED_AT_MAX_QUERY_PARAMETER, shopifyGetCustomersRequest.getCreatedAtMax());
700+
}
701+
final Response response = get(target);
702+
return getCustomers(response);
703+
}
704+
705+
public List<ShopifyCustomer> searchCustomers(final String query) {
706+
final Response response = get(getWebTarget().path(CUSTOMERS).path(SEARCH)
707+
.queryParam(QUERY_QUERY_PARAMETER, query).queryParam(LIMIT_QUERY_PARAMETER, DEFAULT_REQUEST_LIMIT));
708+
return getCustomers(response);
709+
}
710+
648711
public ShopifyFulfillment cancelFulfillment(final String orderId, final String fulfillmentId) {
649712
final Response response = post(
650713
getWebTarget().path(ORDERS).path(orderId).path(FULFILLMENTS).path(fulfillmentId).path(CANCEL),
@@ -759,6 +822,11 @@ public String getAccessToken() {
759822
return accessToken;
760823
}
761824

825+
private List<ShopifyCustomer> getCustomers(final Response response) {
826+
final ShopifyCustomersRoot shopifyCustomersRootResponse = response.readEntity(ShopifyCustomersRoot.class);
827+
return shopifyCustomersRootResponse.getCustomers();
828+
}
829+
762830
private ShopifyRefund calculateRefund(final ShopifyRefundCreationRequest shopifyRefundCreationRequest) {
763831
final ShopifyRefundRoot shopifyRefundRoot = new ShopifyRefundRoot();
764832

@@ -844,7 +912,7 @@ private Response handleResponse(final Response response, final Status... expecte
844912
return response;
845913
}
846914

847-
throw new ShopifyErrorResponseException(response, shopifySdkRetryListener.getResponseBody());
915+
throw new ShopifyErrorResponseException(response);
848916
}
849917

850918
private List<Integer> getExpectedStatusCodes(final Status... expectedStatus) {
@@ -861,20 +929,21 @@ private Response invokeResponseCallable(final Callable<Response> responseCallabl
861929
}
862930

863931
private Retryer<Response> buildResponseRetyer() {
864-
return RetryerBuilder.<Response>newBuilder().retryIfResult(ShopifySdk::shouldRetryResponse).retryIfException()
932+
return RetryerBuilder.<Response> newBuilder().retryIfResult(ShopifySdk::shouldRetryResponse).retryIfException()
865933
.withWaitStrategy(WaitStrategies.randomWait(minimumRequestRetryRandomDelayMilliseconds,
866934
TimeUnit.MILLISECONDS, maximumRequestRetryRandomDelayMilliseconds, TimeUnit.MILLISECONDS))
867935
.withStopStrategy(
868936
StopStrategies.stopAfterDelay(maximumRequestRetryTimeoutMilliseconds, TimeUnit.MILLISECONDS))
869-
.withRetryListener(shopifySdkRetryListener).build();
937+
.withRetryListener(new ShopifySdkRetryListener()).build();
870938
}
871939

872940
private static boolean shouldRetryResponse(final Response response) {
873941
return isServerError(response) || hasExceededRateLimit(response) || hasNotBeenSaved(response);
874942
}
875943

876944
private static boolean hasExceededRateLimit(final Response response) {
877-
return TOO_MANY_REQUESTS_STATUS_CODE == response.getStatus();
945+
return TOO_MANY_REQUESTS_STATUS_CODE == response.getStatus()
946+
&& response.getHeaders().containsKey(RETRY_AFTER_HEADER);
878947
}
879948

880949
private static boolean isServerError(final Response response) {
@@ -895,7 +964,7 @@ private static boolean hasNotBeenSaved(final Response response) {
895964
private String generateToken() {
896965
try {
897966

898-
final Entity<String> entity = Entity.entity("", MediaType.APPLICATION_JSON);
967+
final Entity<String> entity = Entity.entity(EMPTY_STRING, MediaType.APPLICATION_JSON);
899968
final Response response = this.webTarget.path(OAUTH).path(ACCESS_TOKEN).queryParam(CLIENT_ID, this.clientId)
900969
.queryParam(CLIENT_SECRET, this.clientSecret)
901970
.queryParam(AUTHORIZATION_CODE, this.authorizationToken).request(MediaType.APPLICATION_JSON)
@@ -946,23 +1015,21 @@ public class ShopifySdkRetryListener implements RetryListener {
9461015
private static final String RETRY_EXCEPTION_ATTEMPT_MESSAGE = "An exception occurred while making an API call to shopify: {} on attempt number {} and {} seconds since first attempt";
9471016
private static final String RETRY_INVALID_RESPONSE_ATTEMPT_MESSAGE = "Waited {} seconds since first retry attempt. This is attempt {}. Please review the following failed request information.\nRequest Location of {}\nResponse Status Code of {}\nResponse Headers of:\n{}\nResponse Body of:\n{}";
9481017

949-
private String responseBody;
950-
9511018
@Override
9521019
public <V> void onRetry(final Attempt<V> attempt) {
9531020
if (attempt.hasResult()) {
9541021
final Response response = (Response) attempt.getResult();
9551022

9561023
response.bufferEntity();
957-
this.responseBody = response.readEntity(String.class);
1024+
final String responseBody = response.readEntity(String.class);
9581025

9591026
if (LOGGER.isWarnEnabled() && !hasExceededRateLimit(response) && shouldRetryResponse(response)) {
9601027

9611028
final long delaySinceFirstAttemptInSeconds = convertMillisecondsToSeconds(
9621029
attempt.getDelaySinceFirstAttempt());
9631030
LOGGER.warn(RETRY_INVALID_RESPONSE_ATTEMPT_MESSAGE, delaySinceFirstAttemptInSeconds,
9641031
attempt.getAttemptNumber(), response.getLocation(), response.getStatus(),
965-
response.getStringHeaders(), this.responseBody);
1032+
response.getStringHeaders(), responseBody);
9661033

9671034
}
9681035

@@ -975,10 +1042,6 @@ public <V> void onRetry(final Attempt<V> attempt) {
9751042
}
9761043
}
9771044

978-
public String getResponseBody() {
979-
return responseBody;
980-
}
981-
9821045
private long convertMillisecondsToSeconds(final long milliiseconds) {
9831046
return TimeUnit.SECONDS.convert(milliiseconds, TimeUnit.MILLISECONDS);
9841047
}

src/main/java/com/shopify/exceptions/ShopifyErrorResponseException.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,10 @@ public ShopifyErrorResponseException(final Response response) {
2020
this.statusCode = response.getStatus();
2121
}
2222

23-
public ShopifyErrorResponseException(final Response response, final String responseBody) {
24-
super(buildMessage(response, responseBody));
25-
response.bufferEntity();
26-
27-
this.responseBody = responseBody;
28-
this.shopifyErrorCodes = ShopifyErrorCodeFactory.create(responseBody);
29-
this.statusCode = response.getStatus();
30-
}
31-
32-
private static String buildMessage(final Response response, final String responseBody) {
33-
response.bufferEntity();
34-
return String.format(MESSAGE, response.getStatus(), response.getStringHeaders(), responseBody);
35-
}
36-
3723
private static String buildMessage(final Response response) {
3824
response.bufferEntity();
39-
return String.format(MESSAGE, response.getStatus(), response.getStringHeaders(),
40-
response.readEntity(String.class));
25+
final String readEntity = response.readEntity(String.class);
26+
return String.format(MESSAGE, response.getStatus(), response.getStringHeaders(), readEntity);
4127
}
4228

4329
public int getStatusCode() {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.shopify.model;
2+
3+
import javax.xml.bind.annotation.XmlRootElement;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
7+
@XmlRootElement
8+
public class ShopifyCustomersRoot {
9+
public List<ShopifyCustomer> getCustomers() {
10+
return customers;
11+
}
12+
13+
public void setCustomers(List<ShopifyCustomer> customers) {
14+
this.customers = customers;
15+
}
16+
17+
private List<ShopifyCustomer> customers = new LinkedList<>();
18+
19+
}

0 commit comments

Comments
 (0)