Skip to content

Commit

Permalink
moved exception handler to common controller, improved error
Browse files Browse the repository at this point in the history
messages #EA-3567
  • Loading branch information
gsergiu committed Oct 13, 2023
1 parent 94b909a commit c87482a
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 158 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
package eu.europeana.api.translation.web.exception;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.NoHandlerFoundException;
import eu.europeana.api.commons.config.i18n.I18nService;
import eu.europeana.api.commons.error.EuropeanaApiErrorResponse;
import eu.europeana.api.commons.error.EuropeanaApiException;
import eu.europeana.api.commons.error.EuropeanaI18nApiException;
import eu.europeana.api.commons.web.exception.EuropeanaGlobalExceptionHandler;
import eu.europeana.api.commons.web.exception.HttpException;
import eu.europeana.api.translation.config.BeanNames;
import eu.europeana.api.translation.web.service.RequestPathMethodService;

Expand All @@ -37,90 +26,9 @@ public GlobalExceptionHandler(RequestPathMethodService requestPathMethodService,
this.requestPathMethodService = requestPathMethodService;
this.i18nService = i18nService;
}

protected I18nService getI18nService() {
return i18nService;
}


/**
* Default handler for EuropeanaI18nApiException types
*
* @param e caught exception
* @param httpRequest the http request
* @return api response entity
*/
@ExceptionHandler(EuropeanaI18nApiException.class)
public ResponseEntity<EuropeanaApiErrorResponse> handleEuropeanaApiException(
EuropeanaI18nApiException e, HttpServletRequest httpRequest) {

return buildApiErrorResponse(e, httpRequest, e.getI18nKey(), e.getI18nParams());
}

private ResponseEntity<EuropeanaApiErrorResponse> buildApiErrorResponse(EuropeanaApiException e,
HttpServletRequest httpRequest, String i18nKey, String[] i18NParams) {
EuropeanaApiErrorResponse response =
new EuropeanaApiErrorResponse.Builder(httpRequest, e, stackTraceEnabled())
.setStatus(e.getResponseStatus().value())
.setError(e.getResponseStatus().getReasonPhrase())
.setMessage(e.doExposeMessage() ? buildResponseMessage(e, i18nKey, i18NParams) : null)
// code only included in JSON if a value is set in exception
.setCode(e.getErrorCode())
.setSeeAlso(getSeeAlso())
.build();
return ResponseEntity.status(e.getResponseStatus()).headers(createHttpHeaders(httpRequest))
.body(response);
}

private String buildResponseMessage(Exception e, String i18nKey, String[] i18nParams) {
if (StringUtils.isBlank(i18nKey)) {
return e.getMessage();
} else {
return i18nService.getMessage(i18nKey, i18nParams);
}
}


/**
* Default handler for EuropeanaI18nApiException types
*
* @param e caught exception
* @param httpRequest the http request
* @return api response entity
*/
@ExceptionHandler(HttpException.class)
public ResponseEntity<EuropeanaApiErrorResponse> handleCommonHttpException(
HttpException e, HttpServletRequest httpRequest) {
EuropeanaApiErrorResponse response =
new EuropeanaApiErrorResponse.Builder(httpRequest, e, stackTraceEnabled())
.setStatus(e.getStatus().value())
.setError(e.getStatus().getReasonPhrase())
.setMessage( i18nService.getMessage(e.getI18nKey(), e.getI18nParams()))
// code only included in JSON if a value is set in exception
.setCode(e.getI18nKey())
.setSeeAlso(getSeeAlso())
.build();
return ResponseEntity.status(e.getStatus()).headers(createHttpHeaders(httpRequest))
.body(response);
}

/**
* mapping for resource not found errors
* @param e exception to handle
* @param httpRequest the http request
*/
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<EuropeanaApiErrorResponse> handleNoHandlerFoundException(
NoHandlerFoundException e, HttpServletRequest httpRequest) {
EuropeanaApiErrorResponse response =
new EuropeanaApiErrorResponse.Builder(httpRequest, e, stackTraceEnabled())
.setStatus(HttpStatus.NOT_FOUND.value())
.setError(HttpStatus.NOT_FOUND.getReasonPhrase())
.setMessage(e.getMessage())
.setSeeAlso(getSeeAlso())
.build();
return ResponseEntity.status(HttpStatus.NOT_FOUND.value())
.contentType(MediaType.APPLICATION_JSON).body(response);
public I18nService getI18nService() {
return i18nService;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,58 +24,61 @@ public class LangDetectionWebService extends BaseWebService {

@Autowired
private TranslationServiceProvider translationServiceProvider;

private final Logger logger = LogManager.getLogger(getClass());

public LangDetectResponse detectLang(LangDetectRequest langDetectRequest) throws EuropeanaI18nApiException {

public LangDetectResponse detectLang(LangDetectRequest langDetectRequest)
throws EuropeanaI18nApiException {
LanguageDetectionService langDetectService = getLangDetectService(langDetectRequest);
LanguageDetectionService fallback = getFallbackService(langDetectRequest);
LanguageDetectionService fallback = getFallbackService(langDetectRequest);
List<String> langs = null;
String serviceId = null;
try {
langs = langDetectService.detectLang(langDetectRequest.getText(), langDetectRequest.getLang());
langs =
langDetectService.detectLang(langDetectRequest.getText(), langDetectRequest.getLang());
serviceId = langDetectService.getServiceId();
}
catch (LanguageDetectionException originalError) {
//check if fallback is available
if(fallback == null) {
} catch (LanguageDetectionException originalError) {
// check if fallback is available
if (fallback == null) {
throwApiException(originalError);
}
else {
} else {
try {
langs = fallback.detectLang(langDetectRequest.getText(), langDetectRequest.getLang());
serviceId = fallback.getServiceId();
} catch (LanguageDetectionException e) {
if(logger.isDebugEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Error when calling default service. ", e);
}
throwApiException(originalError);
}
}
}

return new LangDetectResponse(langs, serviceId);
}

private LanguageDetectionService getFallbackService(LangDetectRequest langDetectRequest)
throws ParamValidationException {
//only if indicated in request
if(langDetectRequest.getFallback() == null) {
// only if indicated in request
if (langDetectRequest.getFallback() == null) {
return null;
}
//call the fallback service in case of failed lang detection (non 200 response by remote service)
// call the fallback service in case of failed lang detection (non 200 response by remote
// service)
return getServiceInstance(langDetectRequest.getFallback(), langDetectRequest.getLang(), true);
}
}

private LanguageDetectionService getLangDetectService(LangDetectRequest langDetectRequest) throws ParamValidationException {
private LanguageDetectionService getLangDetectService(LangDetectRequest langDetectRequest)
throws ParamValidationException {
final String requestedServiceId = langDetectRequest.getService();
final String languageHint = langDetectRequest.getLang();
if(requestedServiceId != null) {

if (requestedServiceId != null) {
return getServiceInstance(requestedServiceId, languageHint);
}else {
final String defaultServiceId = translationServiceProvider.getTranslationServicesConfig().getLangDetectConfig().getDefaultServiceId();
return getServiceInstance(defaultServiceId, languageHint);
} else {
final String defaultServiceId = translationServiceProvider.getTranslationServicesConfig()
.getLangDetectConfig().getDefaultServiceId();
return getServiceInstance(defaultServiceId, languageHint);
}
}

Expand All @@ -86,15 +89,22 @@ private LanguageDetectionService getServiceInstance(final String requestedServic

private LanguageDetectionService getServiceInstance(final String requestedServiceId,
final String languageHint, boolean isFallbackService) throws ParamValidationException {
LanguageDetectionService detectService = translationServiceProvider.getLangDetectServices().get(requestedServiceId);
if(detectService==null) {
final String paramName = isFallbackService? TranslationAppConstants.FALLBACK: TranslationAppConstants.SERVICE;
final String availableServices = translationServiceProvider.getLangDetectServices().keySet().toString();
throw new ParamValidationException(null, null, ERROR_INVALID_PARAM_VALUE, new String[] {paramName, requestedServiceId + " (available services: " + availableServices + ")"});
LanguageDetectionService detectService =
translationServiceProvider.getLangDetectServices().get(requestedServiceId);
if (detectService == null) {
final String paramName =
isFallbackService ? TranslationAppConstants.FALLBACK : TranslationAppConstants.SERVICE;
final String availableServices =
translationServiceProvider.getLangDetectServices().keySet().toString();
throw new ParamValidationException("Requested service is invalid:" + requestedServiceId,
ERROR_INVALID_PARAM_VALUE, ERROR_INVALID_PARAM_VALUE, new String[] {paramName,
requestedServiceId + " (available services: " + availableServices + ")"});
}
//check if the "lang" is supported
if(languageHint!=null && !detectService.isSupported(languageHint)) {
throw new ParamValidationException(null, null, ERROR_UNSUPPORTED_LANG, new String[] {TranslationAppConstants.LANG, requestedServiceId});
// check if the "lang" is supported
if (languageHint != null && !detectService.isSupported(languageHint)) {
throw new ParamValidationException("Language hint not supported:" + languageHint,
ERROR_INVALID_PARAM_VALUE, ERROR_UNSUPPORTED_LANG,
new String[] {TranslationAppConstants.LANG, requestedServiceId});
}
return detectService;
}
Expand All @@ -103,13 +113,14 @@ public boolean isLangDetectionSupported(@NotNull String lang) {
return translationServiceProvider.getTranslationServicesConfig().getLangDetectConfig()
.getSupported().contains(lang.toLowerCase(Locale.ENGLISH));
}

@PreDestroy
public void close() {
//call close method of all detection services
for (LanguageDetectionService service : translationServiceProvider.getLangDetectServices().values()) {
service.close();
// call close method of all detection services
for (LanguageDetectionService service : translationServiceProvider.getLangDetectServices()
.values()) {
service.close();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,40 @@ public class TranslationWebService extends BaseWebService {

@Autowired
private TranslationServiceProvider translationServiceProvider;

private final Logger logger = LogManager.getLogger(getClass());

public TranslationResponse translate(TranslationRequest translationRequest) throws EuropeanaI18nApiException {

public TranslationResponse translate(TranslationRequest translationRequest)
throws EuropeanaI18nApiException {
LanguagePair languagePair =
new LanguagePair(translationRequest.getSource(), translationRequest.getTarget());
TranslationService translationService = selectTranslationService(translationRequest, languagePair);
TranslationService translationService =
selectTranslationService(translationRequest, languagePair);
TranslationService fallback = null;
if(translationRequest.getFallback() != null) {
if (translationRequest.getFallback() != null) {
fallback = getTranslationService(translationRequest.getFallback(), languagePair, true);
}

List<String> translations = null;
String serviceId = null;
try {
translations = translationService.translate(translationRequest.getText(), translationRequest.getTarget(), translationRequest.getSource());
translations = translationService.translate(translationRequest.getText(),
translationRequest.getTarget(), translationRequest.getSource());
serviceId = translationService.getServiceId();
} catch (TranslationException originalError) {
// call the fallback service in case of failed translation
if (fallback == null) {
throwApiException(originalError);
}
else {
} else {
try {
translations = fallback.translate(translationRequest.getText(), translationRequest.getTarget(), translationRequest.getSource());
translations = fallback.translate(translationRequest.getText(),
translationRequest.getTarget(), translationRequest.getSource());
serviceId = fallback.getServiceId();
} catch(TranslationException e) {
if(logger.isDebugEnabled()) {
} catch (TranslationException e) {
if (logger.isDebugEnabled()) {
logger.debug("Error when calling default service. ", e);
}
//return original exception
// return original exception
throwApiException(originalError);
}
}
Expand All @@ -64,9 +67,9 @@ public TranslationResponse translate(TranslationRequest translationRequest) thro
result.setService(serviceId);
return result;
}
private TranslationService selectTranslationService(TranslationRequest translationRequest, LanguagePair languagePair)
throws ParamValidationException {

private TranslationService selectTranslationService(TranslationRequest translationRequest,
LanguagePair languagePair) throws ParamValidationException {


final String serviceId = translationRequest.getService();
Expand All @@ -88,25 +91,34 @@ private TranslationService selectTranslationService(TranslationRequest translati
return getTranslationService(defaultServiceId, languagePair);
}

private TranslationService selectFromLanguageMappings(LanguagePair languagePair){
final String key = LanguagePair.generateKey(languagePair.getSrcLang(), languagePair.getTargetLang());
return translationServiceProvider.getLangMappings4TranslateServices().getOrDefault(key, null);
private TranslationService selectFromLanguageMappings(LanguagePair languagePair) {
final String key =
LanguagePair.generateKey(languagePair.getSrcLang(), languagePair.getTargetLang());
return translationServiceProvider.getLangMappings4TranslateServices().getOrDefault(key, null);
}

private TranslationService getTranslationService(final String serviceId,
LanguagePair languagePair) throws ParamValidationException{
LanguagePair languagePair) throws ParamValidationException {
return getTranslationService(serviceId, languagePair, false);
}

private TranslationService getTranslationService(final String serviceId,
LanguagePair languagePair, boolean fallback) throws ParamValidationException {
TranslationService result =
translationServiceProvider.getTranslationServices().get(serviceId);
TranslationService result = translationServiceProvider.getTranslationServices().get(serviceId);
String param = fallback ? TranslationAppConstants.FALLBACK : TranslationAppConstants.SERVICE;
if (result == null) {
throw new ParamValidationException(null, null, ERROR_INVALID_PARAM_VALUE, new String[] {param, serviceId + " (available services: " + String.join(", ", translationServiceProvider.getTranslationServices().keySet()) + ")"});
throw new ParamValidationException("Requested service id is invalid" + serviceId,
ERROR_INVALID_PARAM_VALUE, ERROR_INVALID_PARAM_VALUE,
new String[] {param,
serviceId + " (available services: "
+ String.join(", ", translationServiceProvider.getTranslationServices().keySet())
+ ")"});
}
if (!result.isSupported(languagePair.getSrcLang(), languagePair.getTargetLang())) {
throw new ParamValidationException(null, null, ERROR_INVALID_PARAM_VALUE, new String[] {LanguagePair.generateKey(TranslationAppConstants.SOURCE_LANG, TranslationAppConstants.TARGET_LANG) , languagePair.toString()});
throw new ParamValidationException("Language pair not supported:" + languagePair,
ERROR_INVALID_PARAM_VALUE, ERROR_INVALID_PARAM_VALUE,
new String[] {LanguagePair.generateKey(TranslationAppConstants.SOURCE_LANG,
TranslationAppConstants.TARGET_LANG), languagePair.toString()});
}
return result;
}
Expand Down Expand Up @@ -141,12 +153,13 @@ private boolean isTargetInList(String targetLang, List<TranslationLangPairCfg> l
}
return false;
}

@PreDestroy
public void close() {
//call close method of all translation services
for (TranslationService service : translationServiceProvider.getTranslationServices().values()) {
service.close();
// call close method of all translation services
for (TranslationService service : translationServiceProvider.getTranslationServices()
.values()) {
service.close();
}
}
}

0 comments on commit c87482a

Please sign in to comment.