Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eTransl error callback #52

Merged
merged 2 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,33 @@ 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;
private final RedisMessageListenerContainer redisMessageListenerContainer;
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<String> missingParams= new ArrayList<>(6);
if(StringUtils.isBlank(baseUrl)) {
missingParams.add("baseUrl");
Expand All @@ -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)");
}
Expand Down Expand Up @@ -160,7 +166,11 @@ private void createRedisMessageListenerAndWaitForResults(List<TranslationObj> 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);
}
Expand Down Expand Up @@ -240,6 +250,7 @@ private String generateJointStringForTranslation(List<TranslationObj> 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))
Expand Down Expand Up @@ -272,7 +283,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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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=messageBody;
}
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -174,6 +177,10 @@ public String getEtranslationCallback() {
return etranslationCallback;
}

public String getEtranslationErrorCallback() {
return etranslationErrorCallback;
}

public int getEtranslationMaxWaitMillisec() {
return etranslationMaxWaitMillisec;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -25,20 +26,40 @@ public ETranslationCallbackController(RedisTemplate<String, CachedTranslation> 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,
@RequestParam(value = "request-id", required = false) String requestId,
@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));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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=

Loading