Skip to content

Commit

Permalink
[BP] INSPIRE Validator - exception handling improvements (#7519)
Browse files Browse the repository at this point in the history
Refactor of the INSPIRE Validator backend code to improve the exception handling.

Previously some exceptions were not reported properly to the user. For example, if the upload of a file to validate returned an error, due to the validator not working properly (for example, returning an error 503), the user got an unclear error message.
Additionally this commit contains some fixes to Sonarlint warnings
  • Loading branch information
josegar74 authored and juanluisrp committed Dec 7, 2023
1 parent 5c185e5 commit d5d43fd
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 172 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.fao.geonet.exceptions.ServiceNotAllowedEx;
import org.fao.geonet.exceptions.UserNotFoundEx;
import org.fao.geonet.exceptions.XSDValidationErrorEx;
import org.fao.geonet.inspire.validator.InspireValidatorException;
import org.fao.geonet.utils.Log;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -164,6 +165,7 @@ public ApiError maxFileExceededHandler(final Exception exception) {
@ExceptionHandler({
HttpMessageNotReadableException.class,
Exception.class,
InspireValidatorException.class,
RuntimeException.class
})
public ApiError runtimeExceptionHandler(final Exception exception, final HttpServletRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2016 Food and Agriculture Organization of the
* Copyright (C) 2001-2023 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
Expand Down Expand Up @@ -37,12 +37,13 @@
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.processing.report.SimpleMetadataProcessingReport;
import org.fao.geonet.api.processing.report.registry.IProcessingReportRegistry;
import org.fao.geonet.api.records.editing.InspireValidatorUtils;
import org.fao.geonet.inspire.validator.InspireValidatorUtils;
import org.fao.geonet.domain.AbstractMetadata;
import org.fao.geonet.domain.MetadataValidation;
import org.fao.geonet.domain.Pair;
import org.fao.geonet.domain.SchematronRequirement;
import org.fao.geonet.events.history.RecordValidationTriggeredEvent;
import org.fao.geonet.inspire.validator.MInspireEtfValidateProcess;
import org.fao.geonet.kernel.AccessManager;
import org.fao.geonet.kernel.DataManager;
import org.fao.geonet.kernel.SchemaManager;
Expand All @@ -55,7 +56,6 @@
import org.fao.geonet.utils.Xml;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Text;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2016 Food and Agriculture Organization of the
* Copyright (C) 2001-2023 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
Expand Down Expand Up @@ -33,11 +33,11 @@
import org.apache.http.HttpStatus;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.NodeInfo;
import org.fao.geonet.api.API;
import org.fao.geonet.api.ApiParams;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.exception.ResourceNotFoundException;
import org.fao.geonet.api.records.editing.InspireValidatorUtils;
import org.fao.geonet.inspire.validator.InspireValidationRunnable;
import org.fao.geonet.inspire.validator.InspireValidatorUtils;
import org.fao.geonet.api.records.formatters.FormatType;
import org.fao.geonet.api.records.formatters.FormatterApi;
import org.fao.geonet.api.records.formatters.FormatterWidth;
Expand All @@ -52,7 +52,6 @@
import org.fao.geonet.kernel.SchemaManager;
import org.fao.geonet.kernel.setting.SettingManager;
import org.fao.geonet.kernel.setting.Settings;
import org.fao.geonet.repository.MetadataValidationRepository;
import org.fao.geonet.repository.SourceRepository;
import org.fao.geonet.schema.iso19139.ISO19139Namespaces;
import org.fao.geonet.util.ThreadPool;
Expand Down Expand Up @@ -126,8 +125,7 @@ public class InspireValidationApi {
@io.swagger.v3.oas.annotations.Operation(
summary = "Get test suites available.",
description = "TG13, TG2, ...")
@RequestMapping(value = "/{metadataUuid}/validate/inspire/testsuites",
method = RequestMethod.GET,
@GetMapping(value = "/{metadataUuid}/validate/inspire/testsuites",
produces = {
MediaType.APPLICATION_JSON_VALUE
})
Expand All @@ -154,8 +152,7 @@ Map<String, String[]> getTestSuites(
+ "An INSPIRE endpoint must be configured in Settings. "
+ "This activates an asyncronous process, this method does not return any report. "
+ "This method returns an id to be used to get the report.")
@RequestMapping(value = "/{metadataUuid}/validate/inspire",
method = RequestMethod.PUT,
@PutMapping(value = "/{metadataUuid}/validate/inspire",
produces = {
MediaType.TEXT_PLAIN_VALUE
})
Expand Down Expand Up @@ -205,16 +202,16 @@ String validateRecordForInspire(
String schema = metadata.getDataInfo().getSchemaId();
if (!schema.matches(supportedSchemaRegex)) {
response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
return String.format("INSPIRE validator does not support records in schema '%'. Schema must match expression '%' and have an ISO19139 formatter.",
return String.format("INSPIRE validator does not support records in schema '%s'. Schema must match expression '%s' and have an ISO19139 formatter.",
schema, supportedSchemaRegex);
}

String id = String.valueOf(metadata.getId());

String URL = settingManager.getValue(Settings.SYSTEM_INSPIRE_REMOTE_VALIDATION_URL);
String URL_QUERY = settingManager.getValue(Settings.SYSTEM_INSPIRE_REMOTE_VALIDATION_URL_QUERY);
if (StringUtils.isEmpty(URL_QUERY)) {
URL_QUERY = URL;
String inspireValidatorUrl = settingManager.getValue(Settings.SYSTEM_INSPIRE_REMOTE_VALIDATION_URL);
String inspireValidatorQueryUrl = settingManager.getValue(Settings.SYSTEM_INSPIRE_REMOTE_VALIDATION_URL_QUERY);
if (StringUtils.isEmpty(inspireValidatorQueryUrl)) {
inspireValidatorQueryUrl = inspireValidatorUrl;
}

ServiceContext context = ApiUtils.createServiceContext(request);
Expand Down Expand Up @@ -268,7 +265,7 @@ String validateRecordForInspire(


InputStream metadataToTest = convertElement2InputStream(md);
testId = inspireValidatorUtils.submitFile(context, URL, URL_QUERY, metadataToTest, testsuite, metadata.getUuid());
testId = inspireValidatorUtils.submitFile(context, inspireValidatorUrl, inspireValidatorQueryUrl, metadataToTest, testsuite, metadata.getUuid());
} else {
String portal = NodeInfo.DEFAULT_NODE;
if (!NodeInfo.DEFAULT_NODE.equals(mode)) {
Expand All @@ -288,10 +285,10 @@ String validateRecordForInspire(
portal,
ISO19139Namespaces.GMD.getURI(),
metadataUuid);
testId = inspireValidatorUtils.submitUrl(context, URL, URL_QUERY, getRecordByIdUrl, testsuite, metadata.getUuid());
testId = inspireValidatorUtils.submitUrl(context, inspireValidatorUrl, inspireValidatorQueryUrl, getRecordByIdUrl, testsuite, metadata.getUuid());
}

threadPool.runTask(new InspireValidationRunnable(context, URL, testId, metadata.getId()));
threadPool.runTask(new InspireValidationRunnable(context, inspireValidatorUrl, testId, metadata.getId()));

return testId;
}
Expand All @@ -313,8 +310,7 @@ private InputStream convertElement2InputStream(Element md)
description = "User MUST be able to edit the record to validate it. "
+ "An INSPIRE endpoint must be configured in Settings. "
+ "If the process is complete an object with status is returned. ")
@RequestMapping(value = "/{testId}/validate/inspire",
method = RequestMethod.GET,
@GetMapping(value = "/{testId}/validate/inspire",
produces = {
MediaType.APPLICATION_JSON_VALUE
}
Expand All @@ -341,15 +337,15 @@ Map<String, String> checkValidation(
HttpSession session
) throws Exception {

String URL = settingManager.getValue(Settings.SYSTEM_INSPIRE_REMOTE_VALIDATION_URL);
String inspireValidatorUrl = settingManager.getValue(Settings.SYSTEM_INSPIRE_REMOTE_VALIDATION_URL);
ServiceContext context = ApiUtils.createServiceContext(request);

try {
if (inspireValidatorUtils.isReady(context, URL, testId)) {
if (inspireValidatorUtils.isReady(context, inspireValidatorUrl, testId)) {
Map<String, String> values = new HashMap<>();

values.put("status", inspireValidatorUtils.isPassed(context, URL, testId));
values.put("report", inspireValidatorUtils.getReportUrl(URL, testId));
values.put("status", inspireValidatorUtils.isPassed(context, inspireValidatorUrl, testId));
values.put("report", inspireValidatorUtils.getReportUrl(inspireValidatorUrl, testId));
response.setStatus(HttpStatus.SC_OK);

return values;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
package org.fao.geonet.api.records;
/*
* Copyright (C) 2001-2023 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
* Rome - Italy. email: geonetwork@osgeo.org
*/
package org.fao.geonet.inspire.validator;

import jeeves.server.context.ServiceContext;
import jeeves.transaction.TransactionManager;
import jeeves.transaction.TransactionTask;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.api.records.editing.InspireValidatorUtils;
import org.fao.geonet.inspire.validator.InspireValidatorUtils;
import org.fao.geonet.domain.MetadataValidation;
import org.fao.geonet.domain.MetadataValidationId;
import org.fao.geonet.domain.MetadataValidationStatus;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2001-2023 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
* Rome - Italy. email: geonetwork@osgeo.org
*/

package org.fao.geonet.inspire.validator;

import org.fao.geonet.exceptions.LocalizedException;

import java.util.Locale;

public class InspireValidatorException extends LocalizedException {
public InspireValidatorException() {
super();
}

public InspireValidatorException(String message) {
super(message);
}

public InspireValidatorException(String message, Throwable cause) {
super(message, cause);
}

public InspireValidatorException(Throwable cause) {
super(cause);
}

protected String getResourceBundleBeanQualifier() {
return "apiMessages";
}

@Override
public InspireValidatorException withMessageKey(String messageKey) {
super.withMessageKey(messageKey);
return this;
}

@Override
public InspireValidatorException withMessageKey(String messageKey, Object[] messageKeyArgs) {
super.withMessageKey(messageKey, messageKeyArgs);
return this;
}

@Override
public InspireValidatorException withDescriptionKey(String descriptionKey) {
super.withDescriptionKey(descriptionKey);
return this;
}

@Override
public InspireValidatorException withDescriptionKey(String descriptionKey, Object[] descriptionKeyArgs) {
super.withDescriptionKey(descriptionKey, descriptionKeyArgs);
return this;
}

@Override
public InspireValidatorException withLocale(Locale locale) {
super.withLocale(locale);
return this;
}
}

0 comments on commit d5d43fd

Please sign in to comment.