Skip to content

Commit 32cefb3

Browse files
authored
Merge pull request #58 from mahendya/future
RetryPattern config for http client
2 parents 7b90412 + 8c6e4df commit 32cefb3

File tree

12 files changed

+162
-102
lines changed

12 files changed

+162
-102
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ You do not need to download and build the source to use the SDK but if you want
8686
8787
h. "serverURL" config parameter will take precedence over sendToProduction and sendToAkamai config parameters. By default the "serverURL" configuration is commented out.
8888

89-
i. Set allowRetry config parameter to "true/false" to enable retry mechanism. By default, allowRetry is set to true.
90-
Set integer values for config parameter numberOfRetries & retryInterval to configure the retry behavior. Refer to the "Retry Pattern" section below.
89+
i. "allowRetry" config parameter will only work for HttpClient. Set allowRetry config parameter to "true" to enable retry mechanism and set merchant specific values for the retry.
90+
Set integer values for config parameter numberOfRetries & retryInterval. Retry Interval is time delay for next retry in seconds. number of retry parameter should be set between
91+
1 to 5 any other value will throw an Error Message. Refer to the "Retry Pattern" section below.
9192
9293
j. Please refer to the accompanying documentation for the other optional properties that you may wish to specify.
9394

@@ -180,10 +181,12 @@ We have two ways to test, One is using maven tool and other is to download the z
180181

181182
##RETRY PATTERN
182183

183-
Retry Pattern Allows to retry sending a failed request. To Enable or disable retry mechanism set the allowRetry config parameter to "true or false".
184-
By default, allowRetry is set to true. The system will retry the failed request multiple times as configured in the config parameter 'numberOfRetries'.
185-
numberOfRetries (Number of retries) should be set between 1 to 3. By default numberOfRetries will be set to 1. User can set a delay in between the retry
186-
attempts using the config parameter 'retryInterval'. The default value for this parameter is 10 which means a delay of 10 seconds between the retry attempts.
184+
Retry Pattern Allows to retry sending a failed request and it will only work with useHttpClient=true, allowRetry flag enables the retry mechanism.
185+
set the value of allowRetry parameter to "TRUE/FALSE". Then the system will retry the failed request as many times as configured by the merchant
186+
in the config parameter 'numberOfRetries'.
187+
188+
numberOfRetries parameter value should be set between 0 to 5. By default the value for numberOfRetries will be 5. User can set a delay in between the retry attempts.
189+
Config parameter for this property is 'retryInterval' in cybs.property file. The default value for 'retryInterval' parameter is 5 which means a delay of 5 seconds.
187190

188191
##Third Party jars
189192
1.) org.apache.ws.security.wss4j:1.6.19

java/src/main/java/com/cybersource/ws/client/Client.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,11 @@ private static Document soapWrapAndSign(
180180
boolean logSignedData = mc.getLogSignedData();
181181
if (!logSignedData) {
182182
logger.log(
183-
Logger.LT_REQUEST,
184-
mapToString(request, true, PCI.REQUEST));
183+
Logger.LT_REQUEST,
184+
"UUID > "+(mc.getUniqueKey()).toString() + "\n" +
185+
"Input request is" + "\n" +
186+
"======================================= \n"
187+
+ mapToString(request, true, PCI.REQUEST));
185188
}
186189

187190
Document wrappedDoc = soapWrap(request, mc, builder,logger);

java/src/main/java/com/cybersource/ws/client/Connection.java

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,22 @@ abstract InputStream getResponseErrorStream()
9191
*/
9292
public Document post(Document request)
9393
throws ClientException, FaultException {
94-
for (int i=0; i<=mc.getNumberOfRetries(); i++) {
95-
try {
96-
postDocument(request);
97-
break;
98-
} catch (IOException e) {
99-
logger.log(Logger.LT_INFO, "Attempt to post document failed. Number of retry attempts made " + i);
100-
if(i==mc.getNumberOfRetries()) throw new ClientException(e, isRequestSent(), logger);
101-
try {
102-
Thread.sleep((long) mc.getRetryInterval());
103-
}catch (InterruptedException ex) {
104-
logger.log(Logger.LT_INFO, "Waiting for the next attempt to made after " +mc.getRetryInterval() );
105-
}
106-
} catch (TransformerConfigurationException e) {
107-
throw new ClientException(e, isRequestSent(), logger);
108-
} catch (TransformerException e) {
109-
throw new ClientException(e, isRequestSent(), logger);
110-
}
111-
112-
}
113-
checkForFault();
114-
try {
115-
return parseReceivedDocument();
116-
}catch (IOException e) {
117-
throw new ClientException(e, isRequestSent(), logger);
118-
}catch (SAXException e) {
119-
throw new ClientException(e, isRequestSent(), logger);
120-
}}
94+
try {
95+
postDocument(request);
96+
checkForFault();
97+
return (parseReceivedDocument());
98+
} catch (IOException e) {
99+
throw new ClientException(e, isRequestSent(), logger);
100+
} catch (TransformerConfigurationException e) {
101+
throw new ClientException(e, isRequestSent(), logger);
102+
} catch (TransformerException e) {
103+
throw new ClientException(e, isRequestSent(), logger);
104+
} catch (SAXException e) {
105+
throw new ClientException(e, isRequestSent(), logger);
106+
}
107+
108+
}
109+
121110

122111
/**
123112
* Validate the Http response for any faults returned from the server.

java/src/main/java/com/cybersource/ws/client/HttpClientConnection.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ private static String documentToString(Document doc)
189189
*/
190190
private class MyRetryHandler implements HttpMethodRetryHandler {
191191

192-
//
192+
long retryWaitInterval=mc.getRetryInterval();
193+
int maxRetries= mc.getNumberOfRetries();
194+
193195
// I copied this code from
194196
// http://jakarta.apache.org/commons/httpclient/exception-handling.html#HTTP%20transport%20safety
195197
// and changed the NoHttpResponseException case to
@@ -198,7 +200,7 @@ public boolean retryMethod(
198200
final HttpMethod method,
199201
final IOException exception,
200202
int executionCount) {
201-
if (executionCount > 5) {
203+
if (executionCount > maxRetries) {
202204
// Do not retry if over max retry count
203205
return false;
204206
}
@@ -210,6 +212,13 @@ public boolean retryMethod(
210212
if (!method.isRequestSent()) {
211213
// Retry if the request has not been sent fully or
212214
// if it's OK to retry methods that have been sent
215+
try {
216+
Thread.sleep(retryWaitInterval);
217+
logger.log( Logger.LT_INFO+" Retrying Request -- ",mc.getUniqueKey().toString()+ " Retry Count -- "+executionCount);
218+
} catch (InterruptedException e) {
219+
// TODO Auto-generated catch block
220+
e.printStackTrace();
221+
}
213222
return true;
214223
}
215224
// otherwise do not retry

java/src/main/java/com/cybersource/ws/client/MerchantConfig.java

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.File;
2222
import java.text.MessageFormat;
2323
import java.util.Properties;
24+
import java.util.UUID;
2425

2526
/**
2627
* An internal class used by the clients to hold and derive the properties
@@ -34,7 +35,8 @@ public class MerchantConfig {
3435

3536
private final static int DEFAULT_TIMEOUT = 130;
3637
private final static int DEFAULT_PROXY_PORT = 8080;
37-
38+
private UUID uniqueKey=UUID.randomUUID();
39+
3840
private final Properties props;
3941

4042
private final String merchantID;
@@ -66,10 +68,10 @@ public class MerchantConfig {
6668
private String effectivePassword;
6769
private boolean useSignAndEncrypted;
6870

69-
// Retry configuration
70-
private int numberOfRetries = 0 ;
71-
//In milliseconds
72-
private int retryInterval= 10 * 1000;
71+
//Retry Pattern
72+
private int numberOfRetries = 0;
73+
private long retryInterval = 0;
74+
private boolean allowRetry=true;
7375

7476

7577
// getter methods
@@ -300,13 +302,14 @@ public MerchantConfig(Properties _props, String _merchantID)
300302

301303
useSignAndEncrypted = getBooleanProperty(merchantID, "useSignAndEncrypted", false);
302304

303-
boolean allowRetry = getBooleanProperty(merchantID, "allowRetry", true);
304-
if(allowRetry){
305-
numberOfRetries = getIntegerProperty(merchantID, "numberOfRetries", 1);
306-
retryInterval = getIntegerProperty(merchantID, "retryInterval", 10) * 1000;
307-
if( numberOfRetries < 1 || numberOfRetries > 3 || retryInterval <= 0){
308-
throw new ConfigException("Invalid value of numberOfRetries and/or retryInterval");
309-
}
305+
allowRetry = getBooleanProperty(merchantID, "allowRetry", true);
306+
if (useHttpClient && allowRetry) {
307+
numberOfRetries = getIntegerProperty(merchantID, "numberOfRetries", 5);
308+
if(numberOfRetries>0)
309+
retryInterval = getIntegerProperty(merchantID, "retryInterval", 5) *1000;
310+
if( numberOfRetries < 1 || numberOfRetries > 5 || retryInterval < 0){
311+
throw new ConfigException("Invalid value of numberOfRetries and/or retryInterval");
312+
}
310313
}
311314
}
312315

@@ -458,6 +461,11 @@ public String getLogString() {
458461
appendPair(sb, "logFilename", logFilename);
459462
appendPair(sb, "logMaximumSize", logMaximumSize);
460463
appendPair(sb, "useHttpClient", useHttpClient);
464+
if(useHttpClient){
465+
appendPair(sb, "allowRetry", allowRetry);
466+
appendPair(sb, "RetryCount", numberOfRetries);
467+
appendPair(sb, "RetryInterval", retryInterval);
468+
}
461469
appendPair(sb, "timeout", timeout);
462470
if (proxyHost != null) {
463471
appendPair(sb, "proxyHost", proxyHost);
@@ -470,11 +478,14 @@ public String getLogString() {
470478
}
471479
}
472480
appendPair(sb, "useSignAndEncrypted", useSignAndEncrypted);
473-
appendPair(sb, "numberOfRetries", numberOfRetries);
474-
appendPair(sb, "retryInterval", retryInterval);
475481
return (sb.toString());
476482
}
477483

484+
private void appendPair(StringBuffer sb, String key, long retryInterval2) {
485+
appendPair(sb, key, String.valueOf(retryInterval2));
486+
487+
}
488+
478489
private static void appendPair(StringBuffer sb, String key, boolean value) {
479490
appendPair(sb, key, String.valueOf(value));
480491
}
@@ -522,12 +533,24 @@ private int getIntegerProperty(
522533
}
523534
}
524535

525-
public int getNumberOfRetries() {
536+
public UUID getUniqueKey() {
537+
return uniqueKey;
538+
}
539+
540+
public int getNumberOfRetries() {
526541
return numberOfRetries;
527542
}
528543

529-
public int getRetryInterval() {
544+
public long getRetryInterval() {
530545
return retryInterval;
531546
}
532547

548+
public boolean isAllowRetry() {
549+
return allowRetry;
550+
}
551+
552+
public void setAllowRetry(boolean allowRetry) {
553+
this.allowRetry = allowRetry;
554+
}
555+
533556
}

java/src/main/java/com/cybersource/ws/client/XMLClient.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,10 @@ private static Document soapWrapAndSign(
330330

331331
if (!logSignedData) {
332332
logger.log(Logger.LT_REQUEST,
333-
Utility.nodeToString(doc, PCI.REQUEST));
333+
"UUID > "+(mc.getUniqueKey()).toString() + "\n" +
334+
"Input request is" + "\n" +
335+
"======================================= \n"
336+
+ Utility.nodeToString(doc, PCI.REQUEST));
334337
}
335338

336339
Document wrappedDoc = soapWrap(doc, mc, builder, logger);

java/src/main/resources/cybs.properties

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ sendToAkamai=<-- Set it to true for Akamai -->
1515

1616
#useHttpClient=false
1717

18+
# Following configure parameters will only work with useHttpClient=true
19+
# "allow retry" property toggle value "true/false" to turn on /off the auto request retry.
20+
# Number of retries is the number of attempts made to send the request.
21+
# Retry interval is the wait time in between the attempts to send the request.
22+
# Retry count configuration, interval unit is in seconds.
23+
# Default values are for allowRetry=true, numberOfRetries=5 and retryInterval=5 seconds.
24+
allowRetry=true
25+
numberOfRetries=5
26+
retryInterval=5
27+
1828
# Mechanism to differentiate whether Payload is encrypted or not
1929
useSignAndEncrypted=<-- Set it to true for MLE[MessageLevelEncryption] -->
2030

2131
timeout=1000
2232

23-
# allowRetry flag can be set to true to enable retry. numberOfRetries is the number of attempts made to send
24-
# the request. retryInterval is the wait time in between the attempts to send the request.
25-
# Retry count configuration, interval unit is in seconds.
26-
# Default values for allowRetry=true, numberOfRetries=1 and retryInterval=10seconds.
27-
allowRetry=true
28-
numberOfRetries=1
29-
retryInterval=10
30-
3133
# logging should normally be disabled in production as it would slow down the
3234
# processing. Enable it only when troubleshooting an issue.
3335
enableLog=true

java/src/test/java/com/cybersource/ws/client/RetryIT.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
public class RetryIT{
1414

1515
private static final String SERVER_URL = "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor";
16+
private static final String WRONG_SERVER_URL = "https://ics2wstest123.ic3.com/commerce/1.x/transactionProcessor";
1617
private MerchantConfig mc;
1718
private Properties props;
1819

@@ -32,15 +33,17 @@ public void setUp() throws Exception
3233
mc = new MerchantConfig(props, null);
3334

3435
}
35-
36+
3637
@Test
37-
public void checkRetry() throws Exception
38+
public void checkRetryConfigValuesForHttpClient() throws Exception
3839
{
3940
String errMsg="Invalid value of numberOfRetries and/or retryInterval";
4041
// request fails as number of retry value is incorrect
42+
props.setProperty("useHttpClient", "true");
4143
props.setProperty("allowRetry", "true");
4244
props.setProperty("numberOfRetries", "10");
4345
props.setProperty("retryInterval", "10");
46+
props.setProperty("serverURL",SERVER_URL);
4447
// request 1 Should fail as the number of retry attempt is exceeding 3
4548
try{
4649
Client.runTransaction(new HashMap(), props);
@@ -52,10 +55,31 @@ public void checkRetry() throws Exception
5255
}
5356

5457
@Test
55-
public void checkNegative() throws Exception
58+
public void checkRetryConfigValuesForNonHttpClient() throws Exception
59+
{
60+
// In this case retry should not be active as it is non http client. transaction should be successful.
61+
String errMsg="Invalid value of numberOfRetries and/or retryInterval";
62+
props.setProperty("useHttpClient", "false");
63+
props.setProperty("allowRetry", "true");
64+
props.setProperty("numberOfRetries", "10");
65+
props.setProperty("retryInterval", "10");
66+
props.setProperty("serverURL",WRONG_SERVER_URL);
67+
68+
try{
69+
Map<String, String> replyMap = Client.runTransaction(new HashMap(), props);
70+
}
71+
catch(ClientException e){
72+
assertNotEquals(errMsg, e.getMessage());
73+
}
74+
75+
}
76+
77+
@Test
78+
public void checkNegativeForHttp() throws Exception
5679
{
5780
String errMsg="Invalid value of numberOfRetries and/or retryInterval";
5881
// request fails as number of retry and retry interval values are in negative
82+
props.setProperty("useHttpClient", "true");
5983
props.setProperty("allowRetry", "true");
6084
props.setProperty("numberOfRetries", "-10");
6185
props.setProperty("retryInterval", "-10");
@@ -68,21 +92,16 @@ public void checkNegative() throws Exception
6892
assertEquals(errMsg, e.getMessage());
6993
}
7094
}
95+
7196
@Test
7297
public void retryDisabled() throws Exception{
7398
// request should work as the Allow Retry is set to false other values will be ignored
99+
props.setProperty("useHttpClient", "true");
74100
props.setProperty("allowRetry", "false");
75101
props.setProperty("numberOfRetries", "-10");
76102
props.setProperty("retryInterval", "-10");
77103
Map reply = Client.runTransaction(new HashMap(), props);
78104
assertNotNull(reply.get("requestID"));
79105

80106
}
81-
82-
@Test
83-
public void checkDefaultRetryValueIfRetryEnabled() throws Exception{
84-
assertEquals(1, mc.getNumberOfRetries());
85-
assertEquals(10*1000, mc.getRetryInterval());
86-
}
87-
88107
}

java/src/test/resources/test_cybs.properties

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ sendToAkamai=true
1515

1616
#useHttpClient=false
1717

18+
# Following configure parameters will only work with useHttpClient=true
19+
# "allow retry" property toggle value "true/false" to turn on /off the auto request retry.
20+
# Number of retries is the number of attempts made to send the request.
21+
# Retry interval is the wait time in between the attempts to send the request.
22+
# Retry count configuration, interval unit is in seconds.
23+
# Default values are for allowRetry=true, numberOfRetries=5 and retryInterval=5 seconds.
24+
allowRetry=true
25+
numberOfRetries=5
26+
retryInterval=5
27+
1828
# Mechanism to differentiate whether Payload is encrypted or not
1929
useSignAndEncrypted=false
2030

2131
timeout=1000
2232

23-
# allowRetry flag can be set to true to enable retry. numberOfRetries is the number of attempts made to send
24-
# the request. retryInterval is the wait time in between the attempts to send the request.
25-
# Retry count configuration, interval unit is in seconds.
26-
# Default values for allowRetry=true, numberOfRetries=1 and retryInterval=10seconds.
27-
allowRetry=true
28-
numberOfRetries=1
29-
retryInterval=10
30-
3133
# logging should normally be disabled in production as it would slow down the
3234
# processing. Enable it only when troubleshooting an issue.
3335
enableLog=true

0 commit comments

Comments
 (0)