From ca8a33bd2d53272a84b483be27dfd8cb1b414104 Mon Sep 17 00:00:00 2001 From: SrdjanStevanetic Date: Wed, 15 May 2024 11:27:25 +0200 Subject: [PATCH 1/2] eTransl error callback --- .../ETranslationTranslationService.java | 17 ++++++++---- .../etranslation/RedisMessageListener.java | 25 ++++++++++------- .../tests/web/TranslationRestIT.java | 2 +- .../config/TranslationApiAutoconfig.java | 3 ++- .../translation/config/TranslationConfig.java | 7 +++++ .../web/ETranslationCallbackController.java | 27 ++++++++++++++++--- .../translation.user.properties.template | 1 + 7 files changed, 62 insertions(+), 20 deletions(-) diff --git a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java index 1c4ee90f..9c82f50a 100644 --- a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java +++ b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java @@ -40,6 +40,7 @@ public class ETranslationTranslationService extends AbstractTranslationService { private final String domain; //this is the base url of the translation api (without the request handler (or the controller) endpoint) private final String callbackUrl; + private final String callbackErrorUrl; private final String credentialUsername; private final String credentialPwd; private final int maxWaitMillisec; @@ -47,23 +48,25 @@ public class ETranslationTranslationService extends AbstractTranslationService { public static final String baseUrlTests="base-url-for-testing"; public static final String markupDelimiter="\ndeenPVsaOg\n";//base64 encoded string (as in generateRedisKey()) with new lines public static final String markupDelimiterWithoutNewline="deenPVsaOg"; + public static final String eTranslationErrorCallbackIndicator="eTranslationErrorCallback"; - public ETranslationTranslationService(String baseUrl, String domain, String callbackUrl, int maxWaitMillisec, + public ETranslationTranslationService(String baseUrl, String domain, String callbackUrl, String callbackErrorUrl, int maxWaitMillisec, String username, String password, RedisMessageListenerContainer redisMessageListenerContainer) throws TranslationException { if(!baseUrlTests.equals(baseUrl)) { - validateETranslConfigParams(baseUrl, domain, callbackUrl, maxWaitMillisec, username, password); + validateETranslConfigParams(baseUrl, domain, callbackUrl, callbackErrorUrl, maxWaitMillisec, username, password); } this.baseUrl = baseUrl; this.domain = domain; this.callbackUrl=callbackUrl; + this.callbackErrorUrl=callbackErrorUrl; this.maxWaitMillisec=maxWaitMillisec; this.credentialUsername=username; this.credentialPwd=password; this.redisMessageListenerContainer=redisMessageListenerContainer; } - private void validateETranslConfigParams(String baseUrl, String domain, String callbackUrl, - int maxWaitMillisec, String username, String password) throws TranslationException { + private void validateETranslConfigParams(String baseUrl, String domain, String callbackUrl, + String callbackErrorUrl, int maxWaitMillisec, String username, String password) throws TranslationException { List missingParams= new ArrayList<>(6); if(StringUtils.isBlank(baseUrl)) { missingParams.add("baseUrl"); @@ -74,6 +77,9 @@ private void validateETranslConfigParams(String baseUrl, String domain, String c if(StringUtils.isBlank(callbackUrl)) { missingParams.add("callbackUrl"); } + if(StringUtils.isBlank(callbackErrorUrl)) { + missingParams.add("callbackErrorUrl"); + } if(maxWaitMillisec<=0) { missingParams.add("maxWaitMillisec (must be >0)"); } @@ -240,6 +246,7 @@ private String generateJointStringForTranslation(List translatio private String createTranslationBodyWithPlainText(String text, String sourceLang, String targetLang, String externalReference) throws JSONException { JSONObject jsonBody = new JSONObject().put("priority", 0) .put("requesterCallback", callbackUrl) + .put("errorCallback", callbackErrorUrl) .put("externalReference", externalReference) .put("callerInformation", new JSONObject().put("application", credentialUsername).put("username", credentialUsername)) .put("sourceLanguage", sourceLang.toUpperCase(Locale.ENGLISH)) @@ -272,7 +279,7 @@ private String createTranslationBodyAsHtmlDocument(String text, String sourceLan String base64EncodedText=Base64.encodeBase64String(text.getBytes(StandardCharsets.UTF_8)); JSONObject jsonBody = new JSONObject().put("priority", 0) // .put("requesterCallback", callbackUrl) -// .put("errorCallback", callbackUrl) +// .put("errorCallback", callbackErrorUrl) .put("externalReference", externalReference) .put("callerInformation", new JSONObject().put("application", credentialUsername).put("username", credentialUsername)) .put("sourceLanguage", sourceLang.toUpperCase(Locale.ENGLISH)) diff --git a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java index 69678e5f..7a11252f 100644 --- a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java +++ b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java @@ -21,17 +21,22 @@ public void onMessage(Message message, byte[] pattern) { LOGGER.debug("New message received from RedisMessageListener: {}", message); } String messageBody=new String(message.getBody(), StandardCharsets.UTF_8); + if(messageBody.contains(ETranslationTranslationService.eTranslationErrorCallbackIndicator)) { + //if we enter here, means the eTranslation error callback is called + this.message=null; + } + else { + /* + * the received message is treated as a json object and we need some adjustments for the escaped characters + * (this only applies if we get the translated text from the translated-text field in the eTransl callback, + * which happens if we send the text to be translated in the textToTranslate request param) + */ + //remove double quotes at the beginning and at the end of the response, from some reason they are duplicated + String messageRemDuplQuotes = messageBody.replaceAll("^\"|\"$", ""); + //replace a double backslash with a single backslash + this.message = messageRemDuplQuotes.replace("\\n", "\n"); + } - /* - * the received message is treated as a json object and we need some adjustments for the escaped characters - * (this only applies if we get the translated text from the translated-text field in the eTransl callback, - * which happens if we send the text to be translated in the textToTranslate request param) - */ - //remove double quotes at the beginning and at the end of the response, from some reason they are duplicated - String messageRemDuplQuotes = messageBody.replaceAll("^\"|\"$", ""); - //replace a double backslash with a single backslash - this.message = messageRemDuplQuotes.replace("\\n", "\n"); - //notify all threads waiting on this object notifyAll(); } diff --git a/translation-tests/src/integration-test/java/eu/europeana/api/translation/tests/web/TranslationRestIT.java b/translation-tests/src/integration-test/java/eu/europeana/api/translation/tests/web/TranslationRestIT.java index c603fb77..c76d6db8 100644 --- a/translation-tests/src/integration-test/java/eu/europeana/api/translation/tests/web/TranslationRestIT.java +++ b/translation-tests/src/integration-test/java/eu/europeana/api/translation/tests/web/TranslationRestIT.java @@ -172,7 +172,7 @@ void translationETranslation() throws Exception { mockMvc .perform( - post("/eTranslation/callback").characterEncoding(StandardCharsets.UTF_8) + post("/etranslation/callback").characterEncoding(StandardCharsets.UTF_8) .param("external-reference", eTranslRef) .param("translated-text", translatedText.toString())) .andExpect(status().isOk()); diff --git a/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationApiAutoconfig.java b/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationApiAutoconfig.java index d89b2ea7..68413283 100644 --- a/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationApiAutoconfig.java +++ b/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationApiAutoconfig.java @@ -223,7 +223,8 @@ public ETranslationTranslationService getETranslationService( return new ETranslationTranslationService( translationConfig.getEtranslationBaseUrl(), translationConfig.getEtranslationDomain(), - translationConfig.getEtranslationCallback(), + translationConfig.getEtranslationCallback(), + translationConfig.getEtranslationErrorCallback(), translationConfig.getEtranslationMaxWaitMillisec(), translationConfig.getEtranslationUsername(), translationConfig.getEtranslationPassword(), diff --git a/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationConfig.java b/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationConfig.java index c8f7a81a..f5f6032c 100644 --- a/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationConfig.java +++ b/translation-web/src/main/java/eu/europeana/api/translation/config/TranslationConfig.java @@ -67,6 +67,9 @@ public class TranslationConfig{ @Value("${translation.eTranslation.callback:#{null}}") private String etranslationCallback; + @Value("${translation.eTranslation.error.callback:#{null}}") + private String etranslationErrorCallback; + @Value("${translation.eTranslation.maxWaitMillisec:30000}") private int etranslationMaxWaitMillisec; @@ -174,6 +177,10 @@ public String getEtranslationCallback() { return etranslationCallback; } + public String getEtranslationErrorCallback() { + return etranslationErrorCallback; + } + public int getEtranslationMaxWaitMillisec() { return etranslationMaxWaitMillisec; } diff --git a/translation-web/src/main/java/eu/europeana/api/translation/web/ETranslationCallbackController.java b/translation-web/src/main/java/eu/europeana/api/translation/web/ETranslationCallbackController.java index 70bccfea..d7ff0d07 100644 --- a/translation-web/src/main/java/eu/europeana/api/translation/web/ETranslationCallbackController.java +++ b/translation-web/src/main/java/eu/europeana/api/translation/web/ETranslationCallbackController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import eu.europeana.api.commons.definitions.utils.LoggingUtils; +import eu.europeana.api.translation.service.etranslation.ETranslationTranslationService; import eu.europeana.api.translation.web.model.CachedTranslation; import io.swagger.v3.oas.annotations.tags.Tag; @RestController @@ -25,7 +26,7 @@ public ETranslationCallbackController(RedisTemplate r } @Tag(description = "ETranslation callback endpoint", name = "eTranslationCallback") - @PostMapping(value = "/eTranslation/callback") + @PostMapping(value = "/etranslation/callback") public void eTranslationCallback( @RequestParam(value = "target-language", required = false) String targetLanguage, @RequestParam(value = "translated-text", required = false) String translatedTextSnippet, @@ -33,12 +34,32 @@ public void eTranslationCallback( @RequestParam(value = "external-reference", required = true) String externalReference, @RequestBody(required = false) String body) { if(LOGGER.isDebugEnabled()) { - LOGGER.debug("eTranslation callback on translation api has been received with the request-id: {}, and the" + LOGGER.debug("eTranslation callback has been received with the request-id: {}, and the" + " external-reference: {}", LoggingUtils.sanitizeUserInput(requestId), LoggingUtils.sanitizeUserInput(externalReference)); } if(externalReference!=null && translatedTextSnippet!=null) { redisTemplate.convertAndSend(externalReference, translatedTextSnippet); } } - + + @Tag(description = "ETranslation error callback endpoint", name = "eTranslationErrorCallback") + @PostMapping(value = "/etranslation/error-callback") + public void eTranslationErrorCallback( + @RequestParam(value = "error-code", required = false) String errorCode, + @RequestParam(value = "error-message", required = false) String errorMessage, + @RequestParam(value = "target-languages", required = false) String targetLanguages, + @RequestParam(value = "request-id", required = false) String requestId, + @RequestParam(value = "external-reference", required = false) String externalReference, + @RequestBody(required = false) String body) { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("eTranslation error callback has been received with the following parameters: error-code: {}," + + "error-message: {}, request-id: {}, external-reference: {}", LoggingUtils.sanitizeUserInput(errorCode), + LoggingUtils.sanitizeUserInput(errorMessage), LoggingUtils.sanitizeUserInput(requestId), LoggingUtils.sanitizeUserInput(externalReference)); + } + if(externalReference!=null) { + redisTemplate.convertAndSend(externalReference, String.format("%s: error-code=%s, error-message=%s", + ETranslationTranslationService.eTranslationErrorCallbackIndicator, errorCode, errorMessage)); + } + } + } diff --git a/translation-web/src/main/resources/translation.user.properties.template b/translation-web/src/main/resources/translation.user.properties.template index 41e370aa..3188e421 100644 --- a/translation-web/src/main/resources/translation.user.properties.template +++ b/translation-web/src/main/resources/translation.user.properties.template @@ -53,5 +53,6 @@ translation.eTranslation.password= # eTranslation domain could be "SPD" (for neural and speed-optimized statistical engines on the cloud. This is the default.) else "Europeana" translation.eTranslation.domain= translation.eTranslation.callback= +translation.eTranslation.error.callback= translation.eTranslation.maxWaitMillisec= From 856083474f2c9f0a577c359296f22ae89f57fefc Mon Sep 17 00:00:00 2001 From: SrdjanStevanetic Date: Wed, 15 May 2024 12:01:10 +0200 Subject: [PATCH 2/2] return exception in case of the eTransl error callback --- .../etranslation/ETranslationTranslationService.java | 6 +++++- .../service/etranslation/RedisMessageListener.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java index 9c82f50a..5078ca63 100644 --- a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java +++ b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/ETranslationTranslationService.java @@ -166,7 +166,11 @@ private void createRedisMessageListenerAndWaitForResults(List tr if(LOGGER.isDebugEnabled()) { LOGGER.debug("Received message from redis message listener is: {}", response); } - if(response!=null) { + if(response.contains(ETranslationTranslationService.eTranslationErrorCallbackIndicator)) { + //eTtransl error callback received + throw new TranslationException(response); + } + else if(response!=null) { //extractTranslationsFromETranslationHtmlResponse(translationObjs, redisMessageListenerAdapter, response); extractTranslationsFromETranslationResponse(translationObjs, redisMessageListenerAdapter, response); } diff --git a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java index 7a11252f..47f8f73d 100644 --- a/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java +++ b/translation-service-etranslation/src/main/java/eu/europeana/api/translation/service/etranslation/RedisMessageListener.java @@ -23,7 +23,7 @@ public void onMessage(Message message, byte[] pattern) { String messageBody=new String(message.getBody(), StandardCharsets.UTF_8); if(messageBody.contains(ETranslationTranslationService.eTranslationErrorCallbackIndicator)) { //if we enter here, means the eTranslation error callback is called - this.message=null; + this.message=messageBody; } else { /*