Skip to content

Commit 63b72b0

Browse files
[MODGOBI-231] Upgrade module to Vert.x 5.0
1 parent c593869 commit 63b72b0

File tree

10 files changed

+122
-100
lines changed

10 files changed

+122
-100
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5858

5959
<!--Dependency Properties-->
60-
<raml-module-builder.version>35.4.0</raml-module-builder.version>
61-
<vertx.version>4.5.13</vertx.version>
60+
<raml-module-builder.version>36.0.0-SNAPSHOT</raml-module-builder.version>
61+
<vertx.version>5.0.5</vertx.version>
6262
<log4j.version>2.24.3</log4j.version>
6363
<aspectj.version>1.9.22.1</aspectj.version>
6464
<jackson-bom.version>2.18.2</jackson-bom.version>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package org.folio.rest.core;
2+
3+
import static java.util.stream.Collectors.toList;
4+
import static org.folio.gobi.exceptions.ErrorCodes.GENERIC_ERROR_CODE;
5+
6+
import java.util.Collections;
7+
import java.util.List;
8+
9+
import org.folio.gobi.exceptions.HttpException;
10+
import org.folio.rest.jaxrs.model.Error;
11+
import org.folio.rest.jaxrs.model.Errors;
12+
13+
import io.vertx.core.json.DecodeException;
14+
import io.vertx.core.json.JsonObject;
15+
import lombok.experimental.UtilityClass;
16+
17+
@UtilityClass
18+
public class ExceptionUtil {
19+
20+
private static final String ERROR_CAUSE = "cause";
21+
22+
public static Errors convertToErrors(Throwable throwable) {
23+
final Throwable cause = throwable.getCause() == null ? throwable : throwable.getCause();
24+
Errors errors;
25+
26+
if (cause instanceof HttpException) {
27+
errors = ((HttpException) cause).getErrors();
28+
List<Error> errorList = errors.getErrors()
29+
.stream()
30+
.map(ExceptionUtil::getError)
31+
.collect(toList());
32+
33+
errors.setErrors(errorList);
34+
errors.setTotalRecords(errorList.size());
35+
} else {
36+
errors = new Errors().withErrors(Collections.singletonList(GENERIC_ERROR_CODE.toError()
37+
.withAdditionalProperty(ERROR_CAUSE, cause.getMessage())))
38+
.withTotalRecords(1);
39+
}
40+
return errors;
41+
}
42+
43+
public static HttpException getHttpException(int statusCode, String error) {
44+
if (isErrorMessageJson(error)) {
45+
return new HttpException(statusCode, new JsonObject(error).mapTo(Errors.class));
46+
}
47+
return new HttpException(statusCode, error);
48+
}
49+
50+
private static Error getError(Error error) {
51+
if (isErrorMessageJson(error.getMessage())) {
52+
return new JsonObject(error.getMessage()).mapTo(Error.class);
53+
}
54+
return error;
55+
}
56+
57+
private static boolean isErrorMessageJson(String errorMessage) {
58+
try {
59+
new JsonObject(errorMessage);
60+
return true;
61+
} catch (DecodeException e) {
62+
return false;
63+
}
64+
}
65+
66+
}

src/main/java/org/folio/rest/core/RestClient.java

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,30 @@
22

33
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
44
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
5+
import static org.folio.rest.core.ExceptionUtil.getHttpException;
56
import java.util.Map;
6-
import org.apache.logging.log4j.LogManager;
7-
import org.apache.logging.log4j.Logger;
8-
import org.folio.gobi.exceptions.HttpException;
97
import org.folio.okapi.common.WebClientFactory;
108
import org.folio.rest.RestVerticle;
119
import org.folio.rest.tools.utils.TenantTool;
1210

1311
import io.vertx.core.Context;
1412
import io.vertx.core.Future;
1513
import io.vertx.core.MultiMap;
14+
import io.vertx.core.http.HttpResponseExpectation;
1615
import io.vertx.core.json.JsonObject;
1716
import io.vertx.ext.web.client.HttpResponse;
1817
import io.vertx.ext.web.client.WebClient;
19-
import io.vertx.ext.web.client.predicate.ErrorConverter;
20-
import io.vertx.ext.web.client.predicate.ResponsePredicate;
18+
import lombok.extern.log4j.Log4j2;
2119

20+
@Log4j2
2221
public class RestClient {
23-
private static final Logger logger = LogManager.getLogger(RestClient.class);
22+
2423
private final WebClient webClient;
2524
private final Context ctx;
2625
private final MultiMap okapiHeaders;
2726
private final String okapiURL;
2827
private final String tenantId;
2928
public static final String X_OKAPI_URL = "X-Okapi-Url";
30-
private static final ErrorConverter ERROR_CONVERTER = ErrorConverter.createFullBody(
31-
result -> new HttpException(result.response().statusCode(), result.response().bodyAsString()));
32-
private static final ResponsePredicate SUCCESS_RESPONSE_PREDICATE =
33-
ResponsePredicate.create(ResponsePredicate.SC_SUCCESS, ERROR_CONVERTER);
3429

3530
public RestClient(Map<String, String> okapiHeaders, Context ctx) {
3631
okapiURL = okapiHeaders.getOrDefault(X_OKAPI_URL, "");
@@ -49,41 +44,52 @@ public String getTenantId() {
4944
}
5045

5146
public Future<JsonObject> handleGetRequest(String endpoint) {
52-
logger.debug("Trying to get '{}' object", endpoint);
47+
log.debug("Trying to get '{}' object", endpoint);
5348
return webClient.getAbs(okapiURL + endpoint).putHeaders(okapiHeaders)
54-
.expect(SUCCESS_RESPONSE_PREDICATE).send()
55-
.map(HttpResponse::bodyAsJsonObject);
49+
.send()
50+
.compose(RestClient::convertHttpResponse)
51+
.map(HttpResponse::bodyAsJsonObject);
5652
}
5753

5854
/**
5955
* A common method to update an entry
6056
*
6157
* @param recordData json to use for update operation
62-
* @param endpoint endpoint
58+
* @param endpoint endpoint
6359
*/
6460
public Future<Void> handlePutRequest(String endpoint, JsonObject recordData) {
65-
if (logger.isDebugEnabled()) {
66-
logger.debug("Trying to put '{}' object with data: {}", endpoint, recordData.encodePrettily());
61+
if (log.isDebugEnabled()) {
62+
log.debug("Trying to put '{}' object with data: {}", endpoint, recordData.encodePrettily());
6763
}
6864
return webClient.putAbs(okapiURL + endpoint).putHeaders(okapiHeaders)
69-
.expect(SUCCESS_RESPONSE_PREDICATE).sendJsonObject(recordData)
70-
.mapEmpty();
65+
.sendJsonObject(recordData)
66+
.compose(RestClient::convertHttpResponse)
67+
.mapEmpty();
7168
}
7269

7370
public Future<JsonObject> post(String endpoint, JsonObject recordData) {
74-
if (logger.isDebugEnabled()) {
75-
logger.debug("Trying to post '{}' object with body: {}", endpoint, recordData.encodePrettily());
71+
if (log.isDebugEnabled()) {
72+
log.debug("Trying to post '{}' object with body: {}", endpoint, recordData.encodePrettily());
7673
}
7774
return webClient.postAbs(okapiURL + endpoint).putHeaders(okapiHeaders)
78-
.expect(SUCCESS_RESPONSE_PREDICATE).sendJsonObject(recordData)
79-
.map(HttpResponse::bodyAsJsonObject);
75+
.sendJsonObject(recordData)
76+
.compose(RestClient::convertHttpResponse)
77+
.map(HttpResponse::bodyAsJsonObject);
8078
}
8179

8280
public Future<Void> delete(String endpointById) {
83-
logger.debug("Tying to delete with using endpoint: {}", endpointById);
81+
log.debug("Tying to delete with using endpoint: {}", endpointById);
8482
return webClient.deleteAbs(okapiURL + endpointById)
85-
.putHeaders(okapiHeaders).putHeader("Accept", APPLICATION_JSON + ", " + TEXT_PLAIN)
86-
.expect(SUCCESS_RESPONSE_PREDICATE).send()
87-
.mapEmpty();
83+
.putHeaders(okapiHeaders).putHeader("Accept", APPLICATION_JSON + ", " + TEXT_PLAIN)
84+
.send()
85+
.compose(RestClient::convertHttpResponse)
86+
.mapEmpty();
87+
}
88+
89+
protected static <T> Future<HttpResponse<T>> convertHttpResponse(HttpResponse<T> response) {
90+
return HttpResponseExpectation.SC_SUCCESS.test(response)
91+
? Future.succeededFuture(response)
92+
: Future.failedFuture(getHttpException(response.statusCode(), response.bodyAsString()));
8893
}
94+
8995
}

src/main/java/org/folio/rest/impl/BaseApi.java

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,26 @@
11
package org.folio.rest.impl;
22

33
import static io.vertx.core.Future.succeededFuture;
4-
import static java.util.stream.Collectors.toList;
54
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
65
import static javax.ws.rs.core.HttpHeaders.LOCATION;
76
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
87
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
9-
import static org.folio.gobi.exceptions.ErrorCodes.GENERIC_ERROR_CODE;
8+
import static org.folio.rest.core.ExceptionUtil.convertToErrors;
109

1110
import java.net.URI;
1211
import java.net.URISyntaxException;
13-
import java.util.Collections;
14-
import java.util.List;
15-
1612
import javax.ws.rs.core.Response;
1713

1814
import org.apache.logging.log4j.LogManager;
1915
import org.apache.logging.log4j.Logger;
2016
import org.folio.gobi.exceptions.HttpException;
21-
import org.folio.rest.jaxrs.model.Error;
2217
import org.folio.rest.jaxrs.model.Errors;
2318

2419
import io.vertx.core.AsyncResult;
2520
import io.vertx.core.Handler;
26-
import io.vertx.core.json.DecodeException;
27-
import io.vertx.core.json.JsonObject;
2821

2922
public class BaseApi {
3023
private final Logger logger = LogManager.getLogger(this.getClass());
31-
private static final String ERROR_CAUSE = "cause";
3224

3325
public Response buildOkResponse(Object body) {
3426
return Response.ok(body, APPLICATION_JSON)
@@ -96,42 +88,4 @@ private javax.ws.rs.core.Response.ResponseBuilder createResponseBuilder(int code
9688
return responseBuilder;
9789
}
9890

99-
public Errors convertToErrors(Throwable throwable) {
100-
final Throwable cause = throwable.getCause() == null ? throwable : throwable.getCause();
101-
Errors errors;
102-
103-
if (cause instanceof HttpException) {
104-
errors = ((HttpException) cause).getErrors();
105-
List<Error> errorList = errors.getErrors()
106-
.stream()
107-
.map(this::mapToError)
108-
.collect(toList());
109-
110-
errors.setErrors(errorList);
111-
errors.setTotalRecords(errorList.size());
112-
} else {
113-
errors = new Errors().withErrors(Collections.singletonList(GENERIC_ERROR_CODE.toError()
114-
.withAdditionalProperty(ERROR_CAUSE, cause.getMessage())))
115-
.withTotalRecords(1);
116-
}
117-
return errors;
118-
}
119-
120-
public boolean isErrorMessageJson(String errorMessage) {
121-
try {
122-
new JsonObject(errorMessage);
123-
return true;
124-
}
125-
catch (DecodeException e) {
126-
return false;
127-
}
128-
}
129-
130-
private Error mapToError(Error error) {
131-
if (isErrorMessageJson(error.getMessage())) {
132-
return new JsonObject(error.getMessage()).mapTo(Error.class);
133-
}
134-
return error;
135-
}
136-
13791
}

src/main/resources/log4j2-json.properties

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ appender.console.layout.includeTimeMillis = true
2020
## Folio fields
2121
appender.console.layout.requestId.type = KeyValuePair
2222
appender.console.layout.requestId.key = requestId
23-
appender.console.layout.requestId.value = $${FolioLoggingContext:requestid}
23+
appender.console.layout.requestId.value = $${FolioLoggingContext:requestId}
2424

2525
appender.console.layout.tenantId.type = KeyValuePair
2626
appender.console.layout.tenantId.key = tenantId
27-
appender.console.layout.tenantId.value = $${FolioLoggingContext:tenantid}
27+
appender.console.layout.tenantId.value = $${FolioLoggingContext:tenantId}
2828

2929
appender.console.layout.userId.type = KeyValuePair
3030
appender.console.layout.userId.key = userId
31-
appender.console.layout.userId.value = $${FolioLoggingContext:userid}
31+
appender.console.layout.userId.value = $${FolioLoggingContext:userId}
3232

3333
appender.console.layout.moduleId.type = KeyValuePair
3434
appender.console.layout.moduleId.key = moduleId
35-
appender.console.layout.moduleId.value = $${FolioLoggingContext:moduleid}
35+
appender.console.layout.moduleId.value = $${FolioLoggingContext:moduleId}
3636

3737
rootLogger.level = info
3838
rootLogger.appenderRefs = info

src/main/resources/log4j2.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ appenders = console
1212
appender.console.type = Console
1313
appender.console.name = STDOUT
1414
appender.console.layout.type = PatternLayout
15-
appender.console.layout.pattern = %d{HH:mm:ss} [$${FolioLoggingContext:requestid}] [$${FolioLoggingContext:tenantid}] [$${FolioLoggingContext:userid}] [$${FolioLoggingContext:moduleid}] %-5p %-20.40C{1} %m%n
15+
appender.console.layout.pattern = %d{HH:mm:ss} [$${FolioLoggingContext:requestId}] [$${FolioLoggingContext:tenantId}] [$${FolioLoggingContext:userId}] [$${FolioLoggingContext:moduleId}] %-5p %-20.40C{1} %m%n
1616

1717
rootLogger.level = info
1818
rootLogger.appenderRefs = info

src/test/java/org/folio/rest/impl/BaseIntegrationTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public static void beforeAll(Vertx vertx, VertxTestContext context) {
5757

5858
final DeploymentOptions opt = new DeploymentOptions().setConfig(conf);
5959

60-
vertx.deployVerticle(RestVerticle.class.getName(), opt, context.succeeding(id -> {
60+
vertx.deployVerticle(RestVerticle.class.getName(), opt).onComplete(id -> {
6161
String tenantJobId = RestAssured
6262
.given()
6363
.header(OKAPI_HEADER_TENANT, TENANT_ID)
@@ -80,7 +80,7 @@ public static void beforeAll(Vertx vertx, VertxTestContext context) {
8080
.body(not(hasKey("error")));
8181

8282
context.completeNow();
83-
}));
83+
});
8484
}
8585

8686
@AfterAll

src/test/java/org/folio/rest/impl/GOBIIntegrationServiceResourceImplTest.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ public class GOBIIntegrationServiceResourceImplTest extends BaseIntegrationTest
105105
private final String PO_LISTED_ELECTRONIC_MONOGRAPH_BAD_DATA_PATH = MOCK_DATA_ROOT_PATH + "/po_listed_electronic_monograph_bad_data.xml";
106106

107107
private static final String CUSTOM_LISTED_ELECTRONIC_SERIAL_MAPPING = "MappingHelper/Custom_ListedElectronicSerial.json";
108-
private static final String VENDOR_MOCK_DATA = "MockData/GOBI_organization.json";
109-
private static final String ORDER_MOCK_DATA = "MockData/purchaseOrders.json";
110-
private static final String COMPOSITE_ORDER_MOCK_DATA = "MockData/compositePurchaseOrder.json";
111-
private static final String VALID_EXPENSE_CLASS = "PostGobiOrdersHelper/valid_expenseClasses.json";
112-
private static final String VALID_ACQUISITION_METHOD = "PostGobiOrdersHelper/valid_acquisition_methods.json";
113-
private static final String VALID_ACQUISITION_UNITS = "PostGobiOrdersHelper/acquisitions_units.json";
108+
private static final String VENDOR_MOCK_DATA = "MockData/GOBI_organization.json";
109+
private static final String ORDER_MOCK_DATA = "MockData/purchaseOrders.json";
110+
private static final String COMPOSITE_ORDER_MOCK_DATA = "MockData/compositePurchaseOrder.json";
111+
private static final String VALID_EXPENSE_CLASS = "PostGobiOrdersHelper/valid_expenseClasses.json";
112+
private static final String VALID_ACQUISITION_METHOD = "PostGobiOrdersHelper/valid_acquisition_methods.json";
113+
private static final String VALID_ACQUISITION_UNITS = "PostGobiOrdersHelper/acquisitions_units.json";
114114

115115
private static final String LOCATION = "LOCATION";
116116
private static final String FUNDS = "FUNDS";
@@ -998,7 +998,7 @@ public MockServer(int port) {
998998
}
999999

10001000
public void close() {
1001-
vertx.close(res -> {
1001+
vertx.close().onComplete(res -> {
10021002
if (res.failed()) {
10031003
logger.error("Failed to shut down mock server", res.cause());
10041004
} else {
@@ -1054,14 +1054,14 @@ public void start(io.vertx.core.Handler<io.vertx.core.AsyncResult<HttpServer>> l
10541054
// Setup Mock Server...
10551055
HttpServer server = vertx.createHttpServer();
10561056

1057-
server.requestHandler(defineRoutes()).listen(port, listeningHandler);
1057+
server.requestHandler(defineRoutes()).listen(port).onComplete(listeningHandler);
10581058

10591059
}
10601060

10611061
private void handlePostPurchaseOrder(RoutingContext ctx) {
1062-
logger.info("Handle Post Purchase Order got: {}", ctx.getBodyAsString());
1062+
logger.info("Handle Post Purchase Order got: {}", ctx.body().asString());
10631063

1064-
JsonObject compPO = ctx.getBodyAsJson();
1064+
JsonObject compPO = ctx.body().asJsonObject();
10651065

10661066
compPO.put(ID, randomUUID().toString());
10671067
String poNumber = "PO_" + randomDigits(10);
@@ -1255,7 +1255,7 @@ private void handlePutOrderById(RoutingContext ctx) {
12551255
.path());
12561256
String putInstruction = ctx.request()
12571257
.getHeader(MOCK_OKAPI_PUT_ORDER_HEADER);
1258-
addServerRqRsData(HttpMethod.PUT, COMPOSITE_PURCHASE_ORDER, ctx.getBodyAsJson());
1258+
addServerRqRsData(HttpMethod.PUT, COMPOSITE_PURCHASE_ORDER, ctx.body().asJsonObject());
12591259

12601260
if (putInstruction.equals(MOCK_INSTRUCTION_PUT_FAIL)) {
12611261
ctx.response()

src/test/java/org/folio/rest/impl/MappingApiTest.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ public static void setUpOnce(VertxTestContext context) throws Throwable {
4040
conf.put("http.port", OKAPI_PORT);
4141

4242
final DeploymentOptions opt = new DeploymentOptions().setConfig(conf);
43-
vertx.deployVerticle(RestVerticle.class.getName(), opt, (f)->{
44-
context.completeNow();
45-
});
43+
vertx.deployVerticle(RestVerticle.class.getName(), opt).onComplete(f -> context.completeNow());
4644
checkVertxContextCompletion(context);
4745
RestAssured.port = OKAPI_PORT;
4846
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
@@ -52,9 +50,7 @@ public static void setUpOnce(VertxTestContext context) throws Throwable {
5250
@AfterAll
5351
public static void tearDownOnce(VertxTestContext context) throws Throwable {
5452
logger.info("GOBI Integration Service Testing Complete");
55-
vertx.close(v -> {
56-
context.completeNow();
57-
});
53+
vertx.close().onComplete(v -> context.completeNow());
5854
TestUtils.checkVertxContextCompletion(context);
5955
}
6056

0 commit comments

Comments
 (0)