Skip to content

Commit d370782

Browse files
committed
Added an option to change object mapper
1 parent 29987a4 commit d370782

File tree

10 files changed

+53
-95
lines changed

10 files changed

+53
-95
lines changed

src/main/java/com/taboola/rest/api/RestAPIClient.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
import org.apache.logging.log4j.LogManager;
1010
import org.apache.logging.log4j.Logger;
1111

12+
import com.fasterxml.jackson.databind.ObjectMapper;
1213
import com.taboola.rest.api.exceptions.factories.DefaultExceptionFactory;
1314
import com.taboola.rest.api.exceptions.factories.ExceptionFactory;
1415
import com.taboola.rest.api.internal.CommunicationFactory;
1516
import com.taboola.rest.api.internal.config.CommunicationConfig;
1617
import com.taboola.rest.api.internal.config.SerializationConfig;
1718
import com.taboola.rest.api.internal.config.UserAgentHeader;
19+
import com.taboola.rest.api.internal.serialization.SerializationMapperCreator;
1820
import com.taboola.rest.api.model.RequestHeader;
1921

2022
/**
@@ -66,6 +68,7 @@ public static class RestAPIClientBuilder {
6668
private String userAgentSuffix;
6769
private String restAPIVersion;
6870
private ExceptionFactory exceptionFactory;
71+
private ObjectMapper objectMapper;
6972

7073
public RestAPIClientBuilder setBaseUrl(String baseUrl) {
7174
this.baseUrl = baseUrl;
@@ -132,13 +135,18 @@ public RestAPIClientBuilder setExceptionFactory(ExceptionFactory exceptionFactor
132135
return this;
133136
}
134137

138+
public RestAPIClientBuilder setObjectMapper(ObjectMapper objectMapper) {
139+
this.objectMapper = objectMapper;
140+
return this;
141+
}
142+
135143
public RestAPIClient build() {
136144
organizeState();
137145
String finalUserAgent = String.format("%s/%s/%s (%s)", userAgentPrefix, restAPIVersion, VERSION, userAgentSuffix);
138146
Collection<RequestHeader> headers = getAllHeaders(this.headers, finalUserAgent);
139147
CommunicationConfig config = new CommunicationConfig(baseUrl, connectionTimeoutMillis, readTimeoutMillis, writeTimeoutMillis, maxIdleConnections,
140-
keepAliveDurationMillis, headers, debug, exceptionFactory);
141-
return new RestAPIClient(new CommunicationFactory(config, serializationConfig));
148+
keepAliveDurationMillis, headers, debug, exceptionFactory, objectMapper);
149+
return new RestAPIClient(new CommunicationFactory(config));
142150
}
143151

144152
private Collection<RequestHeader> getAllHeaders(Collection<RequestHeader> clientHeaders, String finalUserAgent) {
@@ -200,6 +208,10 @@ private void organizeState() {
200208
if(exceptionFactory == null) {
201209
exceptionFactory = DEFAULT_EXCEPTION_FACTORY;
202210
}
211+
212+
if(objectMapper == null) {
213+
objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);
214+
}
203215
}
204216
}
205217

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.taboola.rest.api.exceptions;
22

3-
import com.taboola.rest.api.model.APIError;
4-
53
/**
64
* Created by vladi
75
* Date: 9/13/2017
@@ -10,35 +8,11 @@
108
*/
119
public abstract class RestAPIException extends RuntimeException {
1210

13-
private APIError error = APIError.EMPTY;
14-
1511
public RestAPIException(Throwable cause, String message, Object ... params) {
1612
super(String.format(message, params), cause);
1713
}
1814

1915
public RestAPIException(String message, Object ... params) {
2016
super(String.format(message, params));
2117
}
22-
23-
public RestAPIException(APIError error, String message, Object ... params) {
24-
super(String.format(message + parseError(error), params));
25-
this.error = error;
26-
}
27-
28-
public RestAPIException(APIError error, String message, Throwable t, Object ... params) {
29-
super(String.format(message + parseError(error), params), t);
30-
this.error = error;
31-
}
32-
33-
private static String parseError(APIError error) {
34-
if(error == null || APIError.EMPTY.equals(error)) {
35-
return "";
36-
}
37-
38-
return String.format(". Response payload status [%s], message [%s], offending field [%s], message code [%s]", error.getHttpStatus(), error.getMessage(), error.getOffendingField(), error.getMessageCode());
39-
}
40-
41-
public APIError getError() {
42-
return error;
43-
}
4418
}

src/main/java/com/taboola/rest/api/exceptions/RestAPIRequestException.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.taboola.rest.api.exceptions;
22

3-
import com.taboola.rest.api.model.APIError;
4-
53
/**
64
* Created by vladi
75
* Date: 10/30/2017
@@ -14,7 +12,7 @@ public RestAPIRequestException(String message, Object ... params) {
1412
super(message, params);
1513
}
1614

17-
public RestAPIRequestException(int responseCode, APIError error) {
18-
super(error, "Failed to perform API call with response code [%d]", responseCode);
15+
public RestAPIRequestException(int responseCode) {
16+
super("Failed to perform API call with response code [%d]", responseCode);
1917
}
2018
}

src/main/java/com/taboola/rest/api/exceptions/factories/DefaultExceptionFactory.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.taboola.rest.api.exceptions.RestAPIConnectivityException;
44
import com.taboola.rest.api.exceptions.RestAPIRequestException;
55
import com.taboola.rest.api.exceptions.RestAPIUnauthorizedException;
6-
import com.taboola.rest.api.model.APIError;
76

87
/**
98
* Created by vladi.m
@@ -19,8 +18,8 @@ public void handleAndThrowUnauthorizedException(Throwable cause) {
1918
}
2019

2120
@Override
22-
public void handleAndThrowRequestException(int responseCode, APIError error) {
23-
throw new RestAPIRequestException(responseCode, error);
21+
public void handleAndThrowRequestException(int responseCode, byte[] errorPayloadBytes, String message) {
22+
throw new RestAPIRequestException("message: %s, responseCode: %s", message, responseCode);
2423
}
2524

2625
@Override

src/main/java/com/taboola/rest/api/exceptions/factories/ExceptionFactory.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.taboola.rest.api.exceptions.factories;
22

3-
import com.taboola.rest.api.model.APIError;
4-
53
/**
64
* Created by vladi.m
75
* Date 28/06/2021
@@ -12,7 +10,7 @@ public interface ExceptionFactory {
1210

1311
void handleAndThrowUnauthorizedException(Throwable cause);
1412

15-
void handleAndThrowRequestException(int responseCode, APIError error);
13+
void handleAndThrowRequestException(int responseCode, byte[] errorBytes, String message);
1614

1715
void handleAndThrowConnectivityException(Throwable cause, int responseCode);
1816

src/main/java/com/taboola/rest/api/internal/CommunicationFactory.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
import java.util.concurrent.TimeUnit;
44

5-
import com.fasterxml.jackson.databind.ObjectMapper;
65
import com.taboola.rest.api.internal.config.CommunicationConfig;
7-
import com.taboola.rest.api.internal.config.SerializationConfig;
86
import com.taboola.rest.api.internal.interceptors.CommunicationInterceptor;
97
import com.taboola.rest.api.internal.interceptors.HeadersInterceptor;
10-
import com.taboola.rest.api.internal.serialization.SerializationMapperCreator;
118

129
import okhttp3.ConnectionPool;
1310
import okhttp3.OkHttpClient;
@@ -23,11 +20,9 @@
2320
*/
2421
public final class CommunicationFactory {
2522

26-
private final ObjectMapper objectMapper;
2723
private final Retrofit retrofit;
2824

29-
public CommunicationFactory(CommunicationConfig communicationConfig, SerializationConfig serializationConfig) {
30-
this.objectMapper = SerializationMapperCreator.createObjectMapper(serializationConfig);
25+
public CommunicationFactory(CommunicationConfig communicationConfig) {
3126
Retrofit.Builder retrofitBuilder = createRetrofitBuilder(communicationConfig);
3227

3328
this.retrofit = retrofitBuilder.baseUrl(communicationConfig.getBaseUrl()).build();
@@ -49,8 +44,8 @@ private HttpLoggingInterceptor createLoggingInterceptor(CommunicationConfig conf
4944
private Retrofit.Builder createRetrofitBuilder(CommunicationConfig config) {
5045
return new Retrofit.Builder()
5146
.addConverterFactory(StringConverterFactory.create())
52-
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
53-
.addCallAdapterFactory(SynchronousCallAdapterFactory.create(objectMapper, config.getExceptionFactory()))
47+
.addConverterFactory(JacksonConverterFactory.create(config.getObjectMapper()))
48+
.addCallAdapterFactory(SynchronousCallAdapterFactory.create(config.getExceptionFactory()))
5449
.client(createOkHttpClient(config));
5550
}
5651

src/main/java/com/taboola/rest/api/internal/SynchronousCallAdapterFactory.java

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
package com.taboola.rest.api.internal;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
43
import com.taboola.rest.api.exceptions.RestAPIConnectivityException;
5-
import com.taboola.rest.api.exceptions.RestAPIRequestException;
6-
import com.taboola.rest.api.exceptions.RestAPIUnauthorizedException;
74
import com.taboola.rest.api.exceptions.factories.ExceptionFactory;
8-
import com.taboola.rest.api.model.APIError;
95

10-
import okhttp3.ResponseBody;
116
import org.apache.logging.log4j.LogManager;
127
import org.apache.logging.log4j.Logger;
138
import retrofit2.Call;
@@ -32,15 +27,13 @@ public class SynchronousCallAdapterFactory extends CallAdapter.Factory {
3227
private static final int BAD_REQUEST_HTTP_STATUS_CODE = 400;
3328
private static final int INTERNAL_SERVER_ERROR_HTTP_STATUS_CODE = 500;
3429

35-
private final ObjectMapper objectMapper;
3630
private final ExceptionFactory exceptionFactory;
3731

38-
public static SynchronousCallAdapterFactory create(ObjectMapper objectMapper, ExceptionFactory exceptionFactory) {
39-
return new SynchronousCallAdapterFactory(objectMapper, exceptionFactory);
32+
public static SynchronousCallAdapterFactory create(ExceptionFactory exceptionFactory) {
33+
return new SynchronousCallAdapterFactory(exceptionFactory);
4034
}
4135

42-
private SynchronousCallAdapterFactory(ObjectMapper objectMapper, ExceptionFactory exceptionFactory) {
43-
this.objectMapper = objectMapper;
36+
private SynchronousCallAdapterFactory(ExceptionFactory exceptionFactory) {
4437
this.exceptionFactory = exceptionFactory;
4538
}
4639

@@ -71,7 +64,7 @@ public Object adapt(Call<Object> call) {
7164
exceptionFactory.handleAndThrowUnauthorizedException(safeCreateCauseException(response));
7265

7366
} else if(responseCode >= BAD_REQUEST_HTTP_STATUS_CODE && responseCode < INTERNAL_SERVER_ERROR_HTTP_STATUS_CODE) {
74-
exceptionFactory.handleAndThrowRequestException(responseCode, normalizeError(parseError(response)));
67+
exceptionFactory.handleAndThrowRequestException(responseCode, safeGetErrorPayloadBytes(response), normalizeErrorMsg(response.message()));
7568
}
7669

7770
exceptionFactory.handleAndThrowConnectivityException(safeCreateCauseException(response), responseCode);
@@ -91,6 +84,15 @@ public Object adapt(Call<Object> call) {
9184
};
9285
}
9386

87+
private byte[] safeGetErrorPayloadBytes(Response<Object> response) throws IOException {
88+
try {
89+
return response.errorBody().bytes();
90+
} catch(Throwable t) {
91+
logger.warn("Failed to extract byte[] from response error body", t);
92+
throw new RestAPIConnectivityException();
93+
}
94+
}
95+
9496
private IOException safeCreateCauseException(Response<Object> response) {
9597
try {
9698
return new IOException(response.errorBody().string());
@@ -100,22 +102,11 @@ private IOException safeCreateCauseException(Response<Object> response) {
100102
}
101103
}
102104

103-
private APIError parseError(Response errorResponse) {
104-
ResponseBody errorBody = errorResponse.errorBody();
105-
try {
106-
return objectMapper.readValue(errorBody.bytes(), APIError.class);
107-
} catch (Throwable e) {
108-
logger.warn("Failed to parse API error response object [{}]", errorResponse.message());
109-
return new APIError(errorResponse.message(), errorResponse.code());
110-
}
111-
}
112-
113-
APIError normalizeError(APIError error) {
114-
String message = error.getMessage();
105+
private String normalizeErrorMsg(String message) {
115106
if(message != null) {
116-
error.setMessage(message.replaceAll("%", "%%"));
107+
return message.replaceAll("%", "%%");
117108
}
118109

119-
return error;
110+
return "";
120111
}
121112
}

src/main/java/com/taboola/rest/api/internal/config/CommunicationConfig.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Collection;
44

5+
import com.fasterxml.jackson.databind.ObjectMapper;
56
import com.taboola.rest.api.exceptions.factories.ExceptionFactory;
67
import com.taboola.rest.api.model.RequestHeader;
78

@@ -22,10 +23,11 @@ public class CommunicationConfig {
2223
private final boolean debug;
2324
private final Collection<RequestHeader> headers;
2425
private final ExceptionFactory exceptionFactory;
26+
private final ObjectMapper objectMapper;
2527

2628
public CommunicationConfig(String baseUrl, Long connectionTimeoutMillis, Long readTimeoutMillis,
2729
Long writeTimeoutMillis, Integer maxIdleConnections, Long keepAliveDurationMillis,
28-
Collection<RequestHeader> headers, boolean debug, ExceptionFactory exceptionFactory) {
30+
Collection<RequestHeader> headers, boolean debug, ExceptionFactory exceptionFactory, ObjectMapper objectMapper) {
2931
this.baseUrl = baseUrl;
3032
this.connectionTimeoutMillis = connectionTimeoutMillis;
3133
this.readTimeoutMillis = readTimeoutMillis;
@@ -35,6 +37,7 @@ public CommunicationConfig(String baseUrl, Long connectionTimeoutMillis, Long re
3537
this.headers = headers;
3638
this.debug = debug;
3739
this.exceptionFactory = exceptionFactory;
40+
this.objectMapper = objectMapper;
3841
}
3942

4043
public String getBaseUrl() {
@@ -73,6 +76,10 @@ public ExceptionFactory getExceptionFactory() {
7376
return exceptionFactory;
7477
}
7578

79+
public ObjectMapper getObjectMapper() {
80+
return objectMapper;
81+
}
82+
7683
@Override
7784
public String toString() {
7885
return "CommunicationConfig{" +
@@ -85,6 +92,7 @@ public String toString() {
8592
", debug=" + debug +
8693
", headers=" + headers +
8794
", exceptionFactory=" + exceptionFactory +
95+
", objectMapper=" + objectMapper +
8896
'}';
8997
}
9098
}

src/test/java/com/taboola/rest/api/internal/CommunicationFactoryTest.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import org.junit.Before;
1111
import org.junit.Test;
1212

13+
import com.fasterxml.jackson.databind.ObjectMapper;
1314
import com.taboola.rest.api.exceptions.RestAPIException;
1415
import com.taboola.rest.api.exceptions.factories.DefaultExceptionFactory;
1516
import com.taboola.rest.api.internal.config.CommunicationConfig;
16-
import com.taboola.rest.api.internal.config.SerializationConfig;
1717
import com.taboola.rest.api.internal.config.UserAgentHeader;
1818

1919
/**
@@ -36,9 +36,8 @@ public interface TestEndpoint {
3636
public void beforeTest() {
3737
CommunicationConfig communicationConfig = new CommunicationConfig("http://localhost",
3838
1L, 1L, 1L, 1, 60L,
39-
Collections.singleton(new UserAgentHeader("Dummy-Agent")),true, new DefaultExceptionFactory());
40-
SerializationConfig serializationConfig = new SerializationConfig();
41-
testInstance = new CommunicationFactory(communicationConfig, serializationConfig);
39+
Collections.singleton(new UserAgentHeader("Dummy-Agent")),true, new DefaultExceptionFactory(), new ObjectMapper());
40+
testInstance = new CommunicationFactory(communicationConfig);
4241
}
4342

4443
@Test

0 commit comments

Comments
 (0)