Skip to content

Commit 582c6c4

Browse files
Merge pull request #21 from BorderTech/refactor-submodules
Check Serializable Exceptions
2 parents 9d945ec + 965b353 commit 582c6c4

File tree

6 files changed

+91
-31
lines changed

6 files changed

+91
-31
lines changed

taskmaster-service-helper/src/main/java/com/github/bordertech/taskmaster/service/CallType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.github.bordertech.taskmaster.service;
22

33
/**
4-
* The service call type to invoke.
4+
* The cached service call type to invoke.
55
*
66
* @author Jonathan Austin
77
* @since 1.0.0
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.github.bordertech.taskmaster.service;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.ObjectOutputStream;
5+
6+
/**
7+
* Exception Helper Util.
8+
*/
9+
public final class ExceptionUtil {
10+
11+
/**
12+
* Private constructor.
13+
*/
14+
private ExceptionUtil() {
15+
// Do nothing
16+
}
17+
18+
/**
19+
* Check the exception is Serializable (sometimes they arent).
20+
*
21+
* @param excp the original exception to check
22+
* @return the original exception if Serializable or a ServiceException with the original exception message
23+
*/
24+
public static Exception getSerializableException(final Exception excp) {
25+
if (isSerializableException(excp)) {
26+
return excp;
27+
}
28+
// Wrap exception as a Service Exception
29+
return new ServiceException(excp.getMessage() + " Original exception [" + excp.getClass().getName() + "] not Serializable.");
30+
}
31+
32+
/**
33+
*
34+
* Determine if the Exception is Serializable (as sometimes they arent).
35+
*
36+
* @param excp the Exception to check is serializable
37+
* @return true if Exception is serializable
38+
*/
39+
public static boolean isSerializableException(final Exception excp) {
40+
try {
41+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
42+
ObjectOutputStream os = new ObjectOutputStream(bos);
43+
os.writeObject(excp);
44+
bos.toByteArray();
45+
// Serializable
46+
return true;
47+
} catch (Exception ex) {
48+
// Not Serializable
49+
return false;
50+
}
51+
}
52+
53+
}

taskmaster-service-helper/src/main/java/com/github/bordertech/taskmaster/service/ResultHolder.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* @author Jonathan Austin
1414
* @since 1.0.0
1515
*/
16-
public class ResultHolder<M, T> implements Serializable {
16+
public class ResultHolder<M extends Serializable, T extends Serializable> implements Serializable {
1717

1818
private final M metaData;
1919
private final T result;
@@ -38,6 +38,10 @@ public ResultHolder(final M metaData, final T result) {
3838
* @param exception the exception that occurred
3939
*/
4040
public ResultHolder(final M metaData, final Exception exception) {
41+
// Exception must be provided
42+
if (exception == null) {
43+
throw new IllegalArgumentException("An exception must be provided.");
44+
}
4145
this.metaData = metaData;
4246
this.result = null;
4347
this.exception = exception;

taskmaster-service-helper/src/main/java/com/github/bordertech/taskmaster/service/ServiceAction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.github.bordertech.taskmaster.service;
22

3+
import java.io.Serializable;
4+
35
/**
46
* Invoke a service interface.
57
*
@@ -8,7 +10,7 @@
810
* @author Jonathan Austin
911
* @since 1.0.0
1012
*/
11-
public interface ServiceAction<S, T> {
13+
public interface ServiceAction<S extends Serializable, T extends Serializable> {
1214

1315
/**
1416
* Invoke service call.

taskmaster-service-helper/src/main/java/com/github/bordertech/taskmaster/service/ServiceHelper.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.bordertech.taskmaster.service;
22

33
import com.github.bordertech.taskmaster.RejectedTaskException;
4+
import java.io.Serializable;
45
import javax.cache.Cache;
56
import javax.cache.expiry.Duration;
67

@@ -23,7 +24,7 @@ public interface ServiceHelper {
2324
* @param <T> the service response
2425
* @return the result or null if still processing
2526
*/
26-
<S, T> ResultHolder<S, T> checkASyncResult(final Cache<String, ResultHolder> cache, final String cacheKey);
27+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> checkASyncResult(final Cache<String, ResultHolder> cache, final String cacheKey);
2728

2829
/**
2930
* Provide a default result holder cache with the default duration.
@@ -61,11 +62,11 @@ public interface ServiceHelper {
6162
* @return the result or null if still processing
6263
* @throws RejectedTaskException if the task cannot be scheduled for execution
6364
*/
64-
<S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache, final String cacheKey,
65+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache, final String cacheKey,
6566
final S criteria, final ServiceAction<S, T> action) throws RejectedTaskException;
6667

6768
/**
68-
* Handle an async service call.
69+
* Handle an async service call with a designated thread pool.
6970
*
7071
* @param cache the result holder cache
7172
* @param cacheKey the key for the result holder
@@ -77,7 +78,7 @@ <S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolde
7778
* @return the result or null if still processing
7879
* @throws RejectedTaskException if the task cannot be scheduled for execution
7980
*/
80-
<S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache, final String cacheKey,
81+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache, final String cacheKey,
8182
final S criteria, final ServiceAction<S, T> action, final String pool) throws RejectedTaskException;
8283

8384
/**
@@ -92,7 +93,7 @@ <S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolde
9293
* @param <T> the service response
9394
* @return the result
9495
*/
95-
<S, T> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, ResultHolder> cache, final String cacheKey,
96+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, ResultHolder> cache, final String cacheKey,
9697
final S criteria, final ServiceAction<S, T> action);
9798

9899
/**
@@ -104,11 +105,11 @@ <S, T> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, ResultHold
104105
* @param <T> the service response
105106
* @return the result
106107
*/
107-
<S, T> ResultHolder<S, T> handleServiceCall(final S criteria, final ServiceAction<S, T> action);
108+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> handleServiceCall(final S criteria, final ServiceAction<S, T> action);
108109

109110
/**
110111
*
111-
* Handle a cached service call.
112+
* Handle a cached service call with a particular call type.
112113
*
113114
* @param cache the result holder cache
114115
* @param cacheKey the key for the result holder
@@ -120,12 +121,12 @@ <S, T> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, ResultHold
120121
* @return the result or null if still processing an async call
121122
* @throws RejectedTaskException if the task cannot be scheduled for execution
122123
*/
123-
<S, T> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache, final String cacheKey,
124+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache, final String cacheKey,
124125
final S criteria, final ServiceAction<S, T> action, final CallType callType) throws RejectedTaskException;
125126

126127
/**
127128
*
128-
* Handle a cached service call.
129+
* Handle a cached service call with a particular call type and predefined pool.
129130
*
130131
* @param cache the result holder cache
131132
* @param cacheKey the key for the result holder
@@ -138,7 +139,7 @@ <S, T> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder
138139
* @return the result or null if still processing an async call
139140
* @throws RejectedTaskException if the task cannot be scheduled for execution
140141
*/
141-
<S, T> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache, final String cacheKey,
142+
<S extends Serializable, T extends Serializable> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache, final String cacheKey,
142143
final S criteria, final ServiceAction<S, T> action, final CallType callType, final String pool) throws RejectedTaskException;
143144

144145
}

taskmaster-service-helper/src/main/java/com/github/bordertech/taskmaster/service/impl/ServiceHelperDefault.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.github.bordertech.taskmaster.TaskMasterException;
99
import com.github.bordertech.taskmaster.cache.CacheHelper;
1010
import com.github.bordertech.taskmaster.service.CallType;
11+
import com.github.bordertech.taskmaster.service.ExceptionUtil;
1112
import com.github.bordertech.taskmaster.service.ResultHolder;
1213
import com.github.bordertech.taskmaster.service.ServiceAction;
1314
import com.github.bordertech.taskmaster.service.ServiceException;
@@ -46,7 +47,7 @@ public final class ServiceHelperDefault implements ServiceHelper {
4647
private static final Duration DEFAULT_PROCESSING_DURATION = new Duration(TimeUnit.SECONDS, DEFAULT_PROCESSING_DURATION_SECONDS);
4748

4849
@Override
49-
public <S, T> ResultHolder<S, T> handleServiceCall(final S criteria, final ServiceAction<S, T> action) {
50+
public <S extends Serializable, T extends Serializable> ResultHolder<S, T> handleServiceCall(final S criteria, final ServiceAction<S, T> action) {
5051
// Check action provided
5152
if (action == null) {
5253
throw new IllegalArgumentException("No service action has been provided. ");
@@ -55,22 +56,21 @@ public <S, T> ResultHolder<S, T> handleServiceCall(final S criteria, final Servi
5556
// Do service call
5657
try {
5758
T resp = action.service(criteria);
58-
return new ResultHolder<>(criteria, resp);
59+
return new ResultHolder(criteria, resp);
5960
} catch (Exception e) {
60-
ServiceException excp = new ServiceException("Error calling service." + e.getMessage(), e);
61-
return new ResultHolder<>(criteria, excp);
61+
return new ResultHolder(criteria, ExceptionUtil.getSerializableException(e));
6262
}
6363
}
6464

6565
@Override
66-
public <S, T> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache,
66+
public <S extends Serializable, T extends Serializable> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache,
6767
final String cacheKey, final S criteria, final ServiceAction<S, T> action, final CallType callType)
6868
throws RejectedTaskException {
6969
return handleServiceCallType(cache, cacheKey, criteria, action, callType, null);
7070
}
7171

7272
@Override
73-
public <S, T> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache,
73+
public <S extends Serializable, T extends Serializable> ResultHolder<S, T> handleServiceCallType(final Cache<String, ResultHolder> cache,
7474
final String cacheKey, final S criteria, final ServiceAction<S, T> action, final CallType callType, final String pool)
7575
throws RejectedTaskException {
7676
if (callType == null) {
@@ -90,7 +90,7 @@ public <S, T> ResultHolder<S, T> handleServiceCallType(final Cache<String, Resul
9090
}
9191

9292
@Override
93-
public <S, T> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, ResultHolder> cache,
93+
public <S extends Serializable, T extends Serializable> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, ResultHolder> cache,
9494
final String cacheKey, final S criteria, final ServiceAction<S, T> action) {
9595

9696
// Check cache and cache key provided
@@ -115,13 +115,13 @@ public <S, T> ResultHolder<S, T> handleCachedServiceCall(final Cache<String, Res
115115
}
116116

117117
@Override
118-
public <S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache,
118+
public <S extends Serializable, T extends Serializable> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache,
119119
final String cacheKey, final S criteria, final ServiceAction<S, T> action) throws RejectedTaskException {
120120
return handleAsyncServiceCall(cache, cacheKey, criteria, action, null);
121121
}
122122

123123
@Override
124-
public <S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache,
124+
public <S extends Serializable, T extends Serializable> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, ResultHolder> cache,
125125
final String cacheKey, final S criteria, final ServiceAction<S, T> action, final String pool) throws RejectedTaskException {
126126

127127
// Check cache and cache key provided
@@ -151,16 +151,16 @@ public <S, T> ResultHolder<S, T> handleAsyncServiceCall(final Cache<String, Resu
151151
}
152152

153153
// Setup the bean to hold the service result
154-
final ProcessingServiceResult<S, T> result = new ProcessingServiceResult(cacheKey);
154+
final ProcessingMutableResult<S, T> result = new ProcessingMutableResult(cacheKey);
155155
Runnable task = new Runnable() {
156156
@Override
157157
public void run() {
158158
try {
159159
T resp = action.service(criteria);
160160
result.setResult(resp);
161161
} catch (Exception e) {
162-
ServiceException excp = new ServiceException("Error calling service." + e.getMessage(), e);
163-
result.setException(excp);
162+
// Check exception is serializable to be held in the cache (sometimes they arent)
163+
result.setException(ExceptionUtil.getSerializableException(e));
164164
}
165165
}
166166
};
@@ -177,7 +177,7 @@ public void run() {
177177
}
178178

179179
@Override
180-
public synchronized <S, T> ResultHolder<S, T> checkASyncResult(final Cache<String, ResultHolder> cache,
180+
public synchronized <S extends Serializable, T extends Serializable> ResultHolder<S, T> checkASyncResult(final Cache<String, ResultHolder> cache,
181181
final String cacheKey) {
182182

183183
// Check cache and cache key provided
@@ -191,7 +191,7 @@ public synchronized <S, T> ResultHolder<S, T> checkASyncResult(final Cache<Strin
191191
String processingKey = getProcessingKey(cache.getName(), cacheKey);
192192

193193
// Get the future
194-
TaskFuture<ProcessingServiceResult> future = getProcessingCache().get(processingKey);
194+
TaskFuture<ProcessingMutableResult> future = getProcessingCache().get(processingKey);
195195

196196
// Future has expired or been removed from the Cache
197197
if (future == null) {
@@ -220,7 +220,7 @@ public synchronized <S, T> ResultHolder<S, T> checkASyncResult(final Cache<Strin
220220

221221
// Done, so Extract the result
222222
try {
223-
ProcessingServiceResult serviceResult = future.get();
223+
ProcessingMutableResult serviceResult = future.get();
224224
ResultHolder result;
225225
if (serviceResult.isException()) {
226226
result = new ResultHolder(serviceResult.getMetaData(), serviceResult.getException());
@@ -288,12 +288,12 @@ protected String getProcessingKey(final String cacheName, final String cacheKey)
288288
}
289289

290290
/**
291-
* Used to hold the service result with the ASync processing.
291+
* Used to hold the service result with the ASync processing cache.
292292
*
293293
* @param <M> the meta data type
294294
* @param <T> the result type
295295
*/
296-
public static final class ProcessingServiceResult<M, T> implements Serializable {
296+
public static final class ProcessingMutableResult<M extends Serializable, T extends Serializable> implements Serializable {
297297

298298
private final M metaData;
299299
private T result;
@@ -302,7 +302,7 @@ public static final class ProcessingServiceResult<M, T> implements Serializable
302302
/**
303303
* @param metaData the meta data
304304
*/
305-
public ProcessingServiceResult(final M metaData) {
305+
public ProcessingMutableResult(final M metaData) {
306306
this.metaData = metaData;
307307
}
308308

0 commit comments

Comments
 (0)