Skip to content

Commit

Permalink
Code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdpopov authored May 3, 2020
1 parent 30911d0 commit 6c0c64c
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 98 deletions.
94 changes: 42 additions & 52 deletions src/main/java/org/folio/edge/oaipmh/OaiPmhHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
import org.openarchives.oai._2.RequestType;
import org.openarchives.oai._2.VerbType;

import com.google.common.collect.Iterables;

import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpClientResponse;
import io.vertx.core.http.HttpHeaders;
Expand All @@ -71,54 +69,48 @@ public OaiPmhHandler(SecureStore secureStore, OkapiClientFactory ocf, Configurat

protected void handle(RoutingContext ctx) {
HttpServerRequest request = ctx.request();
log.debug(request.method() + " " + request.absoluteURI());
log.debug("Client request parameters: " + Iterables.toString(request.params()));
log.debug("Client request headers: " + Iterables.toString(request.headers()));
log.debug("Client request: {} {}", request.method(), request.absoluteURI());
log.debug("Client request parameters: " + request.params());
log.debug("Client request headers: " + request.headers());

if (!supportedAcceptHeaders(request)) {
notAcceptableResponse(ctx, request);
return;
}

getOkapiClient(ctx, (okapiClient, param) -> configurationService.getEnableOaiServiceConfigSetting(okapiClient)
.setHandler(oaiPmhEnabled -> {
if (oaiPmhEnabled.failed()) {
oaiPmhFailureHandler(ctx, oaiPmhEnabled.cause());
} else {
if (!oaiPmhEnabled.result()) {
serviceUnavailableResponse(ctx);
return;
}
configurationService.associateErrorsWith200Status(okapiClient)
.setHandler(responseStatusShouldBe200 -> {
if (responseStatusShouldBe200.failed()) {
oaiPmhFailureHandler(ctx, responseStatusShouldBe200.cause());
} else {
ctx.put(ERRORS_PROCESSING_KEY, responseStatusShouldBe200.result());
Verb verb = Verb.fromName(request.getParam(VERB));
if (verb == null) {
badRequest(ctx, "Bad verb. Verb '" + request.getParam(VERB) + "' is not implemented", null, BAD_VERB);
return;
}
List<OAIPMHerrorType> errors = verb.validate(ctx);
if (!errors.isEmpty()) {
badRequest(ctx, verb.toString(), errors);
return;
}
String[] requiredParams;
if (verb.getExclusiveParam() != null && request.getParam(verb.getExclusiveParam()) != null) {
requiredParams = new String[] { verb.getExclusiveParam() };
} else {
requiredParams = verb.getRequiredParams()
.toArray(new String[0]);
}
super.handleCommon(ctx, requiredParams, verb.getOptionalParams()
.toArray(new String[0]), (client, params) -> {
final OaiPmhOkapiClient oaiPmhClient = new OaiPmhOkapiClient(client);
oaiPmhClient.call(request.params(), request.headers(), response -> handleProxyResponse(ctx, response),
t -> oaiPmhFailureHandler(ctx, t));
});
}
});
if (!oaiPmhEnabled.result()) {
serviceUnavailableResponse(ctx);
return;
}
configurationService.associateErrorsWith200Status(okapiClient)
.setHandler(responseStatusShouldBe200 -> {
ctx.put(ERRORS_PROCESSING_KEY, responseStatusShouldBe200.result());
Verb verb = Verb.fromName(request.getParam(VERB));
if (verb == null) {
badRequest(ctx, String.format("Bad verb. Verb '%s' is not implemented", request.getParam(VERB)), null, BAD_VERB);
return;
}
List<OAIPMHerrorType> errors = verb.validate(ctx);
if (!errors.isEmpty()) {
badRequest(ctx, verb.toString(), errors);
return;
}
String[] requiredParams;
if (verb.getExclusiveParam() != null && request.getParam(verb.getExclusiveParam()) != null) {
requiredParams = new String[] { verb.getExclusiveParam() };
} else {
requiredParams = verb.getRequiredParams()
.toArray(new String[0]);
}
super.handleCommon(ctx, requiredParams, verb.getOptionalParams()
.toArray(new String[0]), (client, params) -> {
final OaiPmhOkapiClient oaiPmhClient = new OaiPmhOkapiClient(client);
oaiPmhClient.call(request.params(), request.headers(), response -> handleProxyResponse(ctx, response),
t -> oaiPmhFailureHandler(ctx, t));
});
});
}));
}

Expand Down Expand Up @@ -170,12 +162,10 @@ protected void handleProxyResponse(RoutingContext ctx, HttpClientResponse respon
*/
response.bodyHandler(buffer -> {
edgeResponse.end(buffer);
if (!encodingHeader.isPresent()) {
log.debug("Repository response body: " + buffer);
}
log.debug("Edge response headers:");
edgeResponse.headers()
.forEach(header -> log.debug(String.format("< %s: %s", header.getKey(), header.getValue())));
if (!encodingHeader.isPresent()) {
log.debug("Response from oai-pmh response:{} \n {}",response.headers(), buffer);
}
log.debug("Edge response headers: {}", edgeResponse.headers());
});
} else {
log.error(String.format("Error in the response from repository: (%d)", httpStatusCode));
Expand Down Expand Up @@ -247,7 +237,7 @@ private void getOkapiClient(RoutingContext ctx, Handler.TwoParamVoidFunction<Oka
public void oaiPmhFailureHandler(RoutingContext ctx, Throwable t) {
log.error("Exception in calling OKAPI", t);
if (t instanceof TimeoutException) {
requestTimeout(ctx, t != null? t.getMessage(): "");
requestTimeout(ctx, t.getMessage());
} else {
internalServerError(ctx, t != null? t.getMessage(): "");
}
Expand All @@ -261,9 +251,9 @@ private void writeResponse(RoutingContext ctx, OAIPMH respBody) {
} catch (Exception e) {
log.error("Exception marshalling XML", e);
}
final int i = getErrorsProcessingConfigSetting(ctx) ? SC_OK : SC_BAD_REQUEST;
final int responseStatusCode = getErrorsProcessingConfigSetting(ctx) ? SC_OK : SC_BAD_REQUEST;
ctx.response()
.setStatusCode(i);
.setStatusCode(responseStatusCode);

if (xml != null) {
log.warn("The request was invalid. The response returned with errors: " + xml);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.folio.edge.core.utils.OkapiClient;
import org.folio.edge.oaipmh.domain.Verb;
import org.folio.edge.oaipmh.utils.Constants;
Expand All @@ -21,6 +20,7 @@
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
import lombok.extern.slf4j.Slf4j;

Expand All @@ -29,7 +29,6 @@ public class OaiPmhOkapiClient extends OkapiClient {

private static final String URL_ENCODING_TYPE = "UTF-8";

private static Logger logger = Logger.getLogger(OaiPmhOkapiClient.class);
private static Map<String, String> endpointsMap = new HashMap<>();

static {
Expand Down Expand Up @@ -69,9 +68,6 @@ public void call(MultiMap parameters, MultiMap headers,
Handler<HttpClientResponse> responseHandler,
Handler<Throwable> exceptionHandler) {
String url = getUrlByVerb(parameters);

log.debug("Requesting {}. call request headers: {}", url, headers);

// "Content-Length" header appearing from POST request to edge-oai-pmh API should be removed as unnecessary
// for GET request to mod-oai-pmh
headers.remove(CONTENT_LENGTH);
Expand All @@ -81,11 +77,30 @@ public void call(MultiMap parameters, MultiMap headers,
get(
url,
tenant,
combineHeadersWithDefaults(headers),
headers,
responseHandler,
exceptionHandler);
}

@Override
public void get(String url, String tenant, MultiMap headers, Handler<HttpClientResponse> responseHandler,
Handler<Throwable> exceptionHandler) {
HttpClientRequest request = this.client.getAbs(url);
if (headers != null) {
request.headers()
.setAll(this.combineHeadersWithDefaults(headers));
} else {
request.headers()
.setAll(this.defaultHeaders);
}
log.info("Requesting {}. call request headers: {}", url, headers);

request.handler(responseHandler)
.exceptionHandler(exceptionHandler)
.setTimeout(this.reqTimeout)
.end();
}

/**
* This method resolves endpoint for 'verb' from {@link VerbType} based on 'verb' value extracted
* from HTTP GET parameters multimap
Expand All @@ -103,7 +118,7 @@ private String getEndpoint(MultiMap parameters) {
endpoint = endpoint + "/" + URLEncoder.encode(identifier, URL_ENCODING_TYPE);
parameters.remove(Constants.IDENTIFIER);
} catch (UnsupportedEncodingException e) {
logger.error(String.format("Error in identifier encoding: %s", e.getMessage()));
log.error("Error in identifier encoding", e);
}
}
return endpoint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

import io.vertx.core.Future;
import io.vertx.core.json.JsonObject;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;

@Log4j
@Slf4j
public class ModConfigurationService implements ConfigurationService {

private static final String MODULE_NAME = "OAIPMH";
Expand All @@ -21,12 +21,12 @@ public class ModConfigurationService implements ConfigurationService {
private static final String CONFIG_ASSOSIATE_ERRORS_WITH_200 = "200";

public Future<Boolean> getEnableOaiServiceConfigSetting(OkapiClient client) {
return getConfigSettingValue(client, MODULE_NAME, GENERAL_CONFIG, ENABLE_OAI_SERVICE).map(Boolean::parseBoolean)
return getConfigSettingValue(client, GENERAL_CONFIG, ENABLE_OAI_SERVICE).map(Boolean::parseBoolean)
.otherwise(Boolean.TRUE);
}

public Future<Boolean> associateErrorsWith200Status(OkapiClient client) {
return getConfigSettingValue(client, MODULE_NAME, BEHAVIOR_CONFIG, ERRORS_PROCESSING)
return getConfigSettingValue(client, BEHAVIOR_CONFIG, ERRORS_PROCESSING)
.map(setting -> StringUtils.isNotBlank(setting) && setting.equals(CONFIG_ASSOSIATE_ERRORS_WITH_200))
.otherwise(Boolean.FALSE);
}
Expand All @@ -35,21 +35,20 @@ public Future<Boolean> associateErrorsWith200Status(OkapiClient client) {
* This method make request to mod-configuration module and receive config setting
*
* @param okapiClient okapi client
* @param moduleName name of module
* @param configName name of configuration (currently available general and behavior)
* @param value name of configuration setting in value section (currently available enableOaiService and errorsProcessing)
* @return value of configuration setting
*/
private Future<String> getConfigSettingValue(OkapiClient okapiClient, String moduleName, String configName, String value) {
private Future<String> getConfigSettingValue(OkapiClient okapiClient, String configName, String value) {

final ConfigurationsClient configurationsClient = new ConfigurationsClient(okapiClient.okapiURL, okapiClient.tenant,
okapiClient.getToken());
Future<String> future = Future.future();
final String s = buildQuery(moduleName, configName);
final String s = buildQuery(configName);

try {
final String msg = String.format("%s in tenant %s: Getting configuration: MODULE_NAME:%s, configName: %s, configValue: %s",
okapiClient.okapiURL, okapiClient.tenant, moduleName, configName, value);
okapiClient.okapiURL, okapiClient.tenant, MODULE_NAME, configName, value);
log.debug(msg);
configurationsClient.getConfigurationsEntries(s, 0, 3, null, null, response -> response.bodyHandler(body -> {
if (response.statusCode() != 200) {
Expand All @@ -71,7 +70,7 @@ private Future<String> getConfigSettingValue(OkapiClient okapiClient, String mod
return future;
}

private String buildQuery(String module, String configName) {
return String.format("module=%s and configName=%s", module, configName);
private String buildQuery(String configName) {
return String.format("module=%s and configName=%s", MODULE_NAME, configName);
}
}
62 changes: 33 additions & 29 deletions src/test/java/org/folio/edge/oaipmh/utils/OaiPmhMockOkapi.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.nio.file.Paths;
import java.util.List;

import org.apache.log4j.Logger;
import org.folio.edge.core.utils.test.MockOkapi;

import io.vertx.core.http.HttpHeaders;
Expand All @@ -21,7 +20,9 @@
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class OaiPmhMockOkapi extends MockOkapi {

public static final String PATH_TO_GET_RECORDS_MOCK
Expand All @@ -37,8 +38,6 @@ public class OaiPmhMockOkapi extends MockOkapi {

public static final long REQUEST_TIMEOUT_MS = 1000L;

private static Logger logger = Logger.getLogger(OaiPmhMockOkapi.class);

private String modConfigurationErrorsProcessing;
private String modConfigurationEnableOaiService;

Expand All @@ -51,7 +50,7 @@ public static String getOaiPmhResponseAsXml(Path pathToXmlFile) {
try {
xml = new String(Files.readAllBytes(pathToXmlFile));
} catch (IOException e) {
logger.error("Error in file reading: " + e.getMessage());
log.error("Error in file reading: " + e.getMessage());
}
return xml;
}
Expand All @@ -66,7 +65,7 @@ public void start(TestContext context) {
final Async async = context.async();
server.requestHandler(defineRoutes()::accept).listen(okapiPort, result -> {
if (result.failed()) {
logger.warn(result.cause());
log.warn(result.cause().toString());
}
context.assertTrue(result.succeeded());
async.complete();
Expand All @@ -90,7 +89,7 @@ private void oaiPmhHandler(RoutingContext ctx) {

if(accept != null &&
!accept.equals(MOD_OAI_PMH_ACCEPTED_TYPES)) {
logger.debug("Unsupported MIME type requested: " + accept);
log.debug("Unsupported MIME type requested: " + accept);
ctx.response()
.setStatusCode(400)
.putHeader(HttpHeaders.CONTENT_TYPE, "text/plain")
Expand Down Expand Up @@ -129,35 +128,40 @@ private void oaiPmhHandler(RoutingContext ctx) {
.end(getOaiPmhResponseAsXml(Paths.get(PATH_TO_GET_RECORDS_ERROR_MOCK)));
} else if (path.startsWith("/oai/records/")
&& path.contains("exception")) {
logger.debug("Starting OKAPI exception...");
log.debug("Starting OKAPI exception...");
throw new NullPointerException("NPE OKAPI mock emulation");
} else if (path.contains("TimeoutException")) {
vertx.setTimer(REQUEST_TIMEOUT_MS + 1L, event -> logger.debug("OKAPI client should throw TimeoutException"));
vertx.setTimer(REQUEST_TIMEOUT_MS + 1L, event -> log.debug("OKAPI client should throw TimeoutException"));
}
}

private void handleConfigurationModuleResponse(RoutingContext ctx){
if (ctx.request().absoluteURI().contains("behavior")) {
if (modConfigurationErrorsProcessing.equals("200")) {
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end(getJsonObjectFromFile(Paths.get(PATH_TO_ERROR_PROCESSING_CONFIG_SETTING_500)).replace("500", "200"));
} else if (modConfigurationErrorsProcessing.equals("500")) {
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end(getJsonObjectFromFile(Paths.get(PATH_TO_ERROR_PROCESSING_CONFIG_SETTING_500)));
} else if (modConfigurationErrorsProcessing.equals("emptyBody")) {
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end();
} else {
ctx.response()
.setStatusCode(404)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end();
switch (modConfigurationErrorsProcessing) {
case "200":
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end(getJsonObjectFromFile(Paths.get(PATH_TO_ERROR_PROCESSING_CONFIG_SETTING_500)).replace("500", "200"));
break;
case "500":
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end(getJsonObjectFromFile(Paths.get(PATH_TO_ERROR_PROCESSING_CONFIG_SETTING_500)));
break;
case "emptyBody":
ctx.response()
.setStatusCode(200)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end();
break;
default:
ctx.response()
.setStatusCode(404)
.putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
.end();
break;
}
} else {
if (modConfigurationEnableOaiService.equals("true")) {
Expand All @@ -179,7 +183,7 @@ private String getJsonObjectFromFile(Path path) {
try {
json = new String(Files.readAllBytes(path));
} catch (IOException e) {
logger.error("Unexpected error", e);
log.error("Unexpected error", e);
}
return json;
}
Expand Down

0 comments on commit 6c0c64c

Please sign in to comment.