diff --git a/bpm/bonita-common/src/main/java/org/bonitasoft/engine/bpm/process/ProcessExecutionException.java b/bpm/bonita-common/src/main/java/org/bonitasoft/engine/bpm/process/ProcessExecutionException.java index 7fcf5bac335..d4b3573aa53 100644 --- a/bpm/bonita-common/src/main/java/org/bonitasoft/engine/bpm/process/ProcessExecutionException.java +++ b/bpm/bonita-common/src/main/java/org/bonitasoft/engine/bpm/process/ProcessExecutionException.java @@ -13,6 +13,7 @@ **/ package org.bonitasoft.engine.bpm.process; +import lombok.Getter; import org.bonitasoft.engine.exception.ExecutionException; /** @@ -26,6 +27,8 @@ public class ProcessExecutionException extends ExecutionException { private static final long serialVersionUID = 4412292065541283593L; + @Getter + private long retryAfter = -1L; /** * Constructs a new exception with the specified detail cause. @@ -39,6 +42,11 @@ public ProcessExecutionException(Throwable cause) { super(cause); } + public ProcessExecutionException(Throwable cause, long retryAfter) { + super(cause); + this.retryAfter = retryAfter; + } + /** * Constructs a new exception with the specified detail message. * diff --git a/bpm/bonita-core/bonita-core-data/src/main/java/org/bonitasoft/engine/core/data/instance/impl/TransientDataServiceImpl.java b/bpm/bonita-core/bonita-core-data/src/main/java/org/bonitasoft/engine/core/data/instance/impl/TransientDataServiceImpl.java index c901181699e..8f38c3360f5 100644 --- a/bpm/bonita-core/bonita-core-data/src/main/java/org/bonitasoft/engine/core/data/instance/impl/TransientDataServiceImpl.java +++ b/bpm/bonita-core/bonita-core-data/src/main/java/org/bonitasoft/engine/core/data/instance/impl/TransientDataServiceImpl.java @@ -272,7 +272,7 @@ public List getDataInstances(final long containerId, final String } catch (SProcessDefinitionNotFoundException | SFlowNodeNotFoundException | SFlowNodeReadException | SBonitaReadException e) { throw new SDataInstanceException( - String.format("An error occured while retrieving transient data for container %s with type %s", + String.format("An error occurred while retrieving transient data for container %s with type %s", containerId, containerType), e); } diff --git a/bpm/bonita-core/bonita-parameter/src/main/java/org/bonitasoft/engine/parameter/ParameterService.java b/bpm/bonita-core/bonita-parameter/src/main/java/org/bonitasoft/engine/parameter/ParameterService.java index 7d40201e7b7..366d4dc454c 100644 --- a/bpm/bonita-core/bonita-parameter/src/main/java/org/bonitasoft/engine/parameter/ParameterService.java +++ b/bpm/bonita-core/bonita-parameter/src/main/java/org/bonitasoft/engine/parameter/ParameterService.java @@ -50,9 +50,9 @@ void update(final long processDefinitionId, final String parameterName, final St * @param parameters * parameters to merge * @throws SBonitaReadException - * error thrown if an error occured while retrieving the process definition + * error thrown if an error occurred while retrieving the process definition * @throws SObjectModificationException - * error thrown if an error occured while updating the parameter value + * error thrown if an error occurred while updating the parameter value */ void merge(long processDefinitionId, Map parameters) throws SBonitaReadException, SObjectModificationException; diff --git a/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/api/impl/ProcessStarter.java b/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/api/impl/ProcessStarter.java index c2235986869..05d8c9453eb 100755 --- a/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/api/impl/ProcessStarter.java +++ b/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/api/impl/ProcessStarter.java @@ -39,7 +39,11 @@ import org.bonitasoft.engine.core.process.instance.model.SProcessInstance; import org.bonitasoft.engine.exception.BonitaRuntimeException; import org.bonitasoft.engine.exception.RetrieveException; -import org.bonitasoft.engine.execution.*; +import org.bonitasoft.engine.execution.Filter; +import org.bonitasoft.engine.execution.FlowNodeNameFilter; +import org.bonitasoft.engine.execution.FlowNodeSelector; +import org.bonitasoft.engine.execution.ProcessExecutor; +import org.bonitasoft.engine.execution.StartFlowNodeFilter; import org.bonitasoft.engine.identity.IdentityService; import org.bonitasoft.engine.identity.model.SUser; import org.bonitasoft.engine.operation.Operation; @@ -110,6 +114,12 @@ public ProcessInstance start() throw new RetrieveException(e); } catch (final SProcessDefinitionException e) { throw new ProcessActivationException(e); + } catch (final SProcessInstanceCreationException e) { + if (e.getRetryAfter() != -1L) { + throw new ProcessExecutionException(e, e.getRetryAfter()); + } else { + throw new ProcessExecutionException(e); + } } catch (final SBonitaException e) { throw new ProcessExecutionException(e); } diff --git a/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/execution/ProcessStarterVerifierImpl.java b/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/execution/ProcessStarterVerifierImpl.java index ef3886ea468..b321957663a 100644 --- a/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/execution/ProcessStarterVerifierImpl.java +++ b/bpm/bonita-core/bonita-process-engine/src/main/java/org/bonitasoft/engine/execution/ProcessStarterVerifierImpl.java @@ -95,11 +95,14 @@ public void verify(SProcessInstance processInstance) throws SProcessInstanceCrea final long processStartDate = processInstance.getStartDate(); cleanupOldValues(processStartDate - PERIOD_IN_MILLIS); log.debug("Found {} cases already started in the last {} days", counters.size(), PERIOD_IN_DAYS); + if (counters.size() >= LIMIT) { - final String nextValidTime = getStringRepresentation(getNextResetTimestamp(counters)); + var nextResetTimestamp = getNextResetTimestamp(counters); + final String nextValidTime = getStringRepresentation(nextResetTimestamp); throw new SProcessInstanceCreationException( format("Process start limit (%s cases during last %s days) reached. You are not allowed to start a new process until %s.", - LIMIT, PERIOD_IN_DAYS, nextValidTime)); + LIMIT, PERIOD_IN_DAYS, nextValidTime), + nextResetTimestamp); } try { synchronized (counters) { @@ -112,7 +115,7 @@ public void verify(SProcessInstance processInstance) throws SProcessInstanceCrea } catch (IOException | SPlatformNotFoundException | SPlatformUpdateException e) { log.trace(e.getMessage(), e); throw new SProcessInstanceCreationException( - format("Unable to start the process instance %s", processInstance.getId())); + format("Unable to start the process instance %s", processInstance.getId()), e); } } diff --git a/bpm/bonita-core/bonita-process-instance/src/main/java/org/bonitasoft/engine/core/process/instance/api/exceptions/SProcessInstanceCreationException.java b/bpm/bonita-core/bonita-process-instance/src/main/java/org/bonitasoft/engine/core/process/instance/api/exceptions/SProcessInstanceCreationException.java index b72d6123835..8d5238dd325 100644 --- a/bpm/bonita-core/bonita-process-instance/src/main/java/org/bonitasoft/engine/core/process/instance/api/exceptions/SProcessInstanceCreationException.java +++ b/bpm/bonita-core/bonita-process-instance/src/main/java/org/bonitasoft/engine/core/process/instance/api/exceptions/SProcessInstanceCreationException.java @@ -13,6 +13,7 @@ **/ package org.bonitasoft.engine.core.process.instance.api.exceptions; +import lombok.Getter; import org.bonitasoft.engine.commons.exceptions.SBonitaException; import org.bonitasoft.engine.core.process.definition.model.SProcessDefinition; @@ -23,21 +24,26 @@ public class SProcessInstanceCreationException extends SBonitaException { private static final long serialVersionUID = 7581906795549409593L; + @Getter + private long retryAfter = -1L; + public SProcessInstanceCreationException(final Throwable cause) { super(cause); } - public SProcessInstanceCreationException(final String message, final SBonitaException e) { - super(message, e); + public SProcessInstanceCreationException(final String message, final Throwable cause) { + super(message, cause); } - /** - * @param string - */ public SProcessInstanceCreationException(final String message) { super(message); } + public SProcessInstanceCreationException(final String message, final long retryAfter) { + super(message); + this.retryAfter = retryAfter; + } + /** * @param sDefinition * The process definition to add on context diff --git a/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/page/PageDownloadServlet.java b/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/page/PageDownloadServlet.java index 37d9144fdcc..2123caecd2d 100644 --- a/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/page/PageDownloadServlet.java +++ b/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/page/PageDownloadServlet.java @@ -105,7 +105,7 @@ protected void doGet(final HttpServletRequest request, final HttpServletResponse LOGGER.error(e.getMessage(), e); } try { - out.write("An exception occured. Please contact an administrator".getBytes()); + out.write("An exception occurred. Please contact an administrator".getBytes()); } catch (final IOException e1) { throw new ServletException(e1); } diff --git a/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/servlet/ErrorPageServlet.java b/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/servlet/ErrorPageServlet.java index 057575157bf..28a7d491bc1 100644 --- a/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/servlet/ErrorPageServlet.java +++ b/bpm/bonita-web-server/src/main/java/org/bonitasoft/console/common/server/servlet/ErrorPageServlet.java @@ -87,7 +87,7 @@ protected void doGet(final HttpServletRequest request, final HttpServletResponse if (LOGGER.isErrorEnabled()) { LOGGER.error("Error while trying to get the error page.", e); } - output.println("An Error occured."); + output.println("An Error occurred."); } } writeFormatedResponse(output, errorCode, contextPath); @@ -124,7 +124,7 @@ protected void writeFormatedResponse(PrintWriter output, String errorCode, Strin if (LOGGER.isErrorEnabled()) { LOGGER.error("Error while trying to display the error page.", e); } - output.println("An Error occured."); + output.println("An Error occurred."); } } diff --git a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResource.java b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResource.java index 7f4dfb45c01..d065b890ee5 100644 --- a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResource.java +++ b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResource.java @@ -15,6 +15,7 @@ import java.io.FileNotFoundException; import java.io.Serializable; +import java.util.Date; import java.util.Map; import com.fasterxml.jackson.databind.node.JsonNodeFactory; @@ -29,6 +30,8 @@ import org.bonitasoft.engine.bpm.process.ProcessExecutionException; import org.bonitasoft.web.rest.server.api.resource.CommonResource; import org.bonitasoft.web.toolkit.client.common.exception.api.APIException; +import org.restlet.Response; +import org.restlet.data.Status; import org.restlet.resource.Post; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,7 +86,17 @@ public String instantiateProcess(final Map inputs) } catch (ProcessExecutionException e) { String errorMessage = "Unable to start the process with ID " + processDefinitionId; if (LOGGER.isErrorEnabled()) { - LOGGER.error(errorMessage + " Error: " + e.getMessage()); + LOGGER.error("{}. Caused by: {}", errorMessage, e.getMessage()); + } + if (e.getRetryAfter() != -1L) { + // Return a 429 status code with Retry-After header to indicate the client + // that he should retry later in case of case creation limit reached + Response response = getResponse(); + response.setRetryAfter(new Date(e.getRetryAfter())); + var status = new Status(Status.CLIENT_ERROR_TOO_MANY_REQUESTS, "Case creation limit reached.", + errorMessage); + response.setStatus(status); + return null; } //Avoid throwing original exception that may contain sensitive information unwanted in the HTTP response throw new ProcessExecutionException(errorMessage + " (consult the logs for more information)."); diff --git a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/engineclient/CaseEngineClient.java b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/engineclient/CaseEngineClient.java index dff3404bb81..b5995db99b2 100644 --- a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/engineclient/CaseEngineClient.java +++ b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/rest/server/engineclient/CaseEngineClient.java @@ -27,6 +27,7 @@ import org.bonitasoft.engine.search.SearchOptionsBuilder; import org.bonitasoft.web.toolkit.client.common.exception.api.APIException; import org.bonitasoft.web.toolkit.client.common.exception.api.APINotFoundException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APITooManyRequestException; import org.bonitasoft.web.toolkit.client.common.i18n.T_; import org.bonitasoft.web.toolkit.client.common.texttemplate.Arg; @@ -70,8 +71,14 @@ public ProcessInstance start(final long userId, final long processId, final Map< new T_("Can't start process, process %processId% is not enabled", new Arg("processId", processId)), e); } catch (final ProcessExecutionException e) { + if (e.getRetryAfter() != -1L) { + throw new APITooManyRequestException( + new T_("Error occurred when starting process %processId%. Case creation limit reached.", + new Arg("processId", processId)), + e.getRetryAfter()); + } throw new APIException( - new T_("Error occured when starting process %processId%", new Arg("processId", processId)), e); + new T_("Error occurred when starting process %processId%", new Arg("processId", processId)), e); } catch (final UserNotFoundException e) { throw new APIException( new T_("Can't start process %processId%, user %userId% not found", new Arg("processId", processId), diff --git a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/client/common/exception/api/APITooManyRequestException.java b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/client/common/exception/api/APITooManyRequestException.java new file mode 100644 index 00000000000..97b8ab38660 --- /dev/null +++ b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/client/common/exception/api/APITooManyRequestException.java @@ -0,0 +1,35 @@ +/** + * Copyright (C) 2024 Bonitasoft S.A. + * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble + * This library is free software; you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Foundation + * version 2.1 of the License. + * This library 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 Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License along with this + * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301, USA. + **/ +package org.bonitasoft.web.toolkit.client.common.exception.api; + +import lombok.Getter; +import org.bonitasoft.web.toolkit.client.common.i18n.T_; + +public class APITooManyRequestException extends APIException { + + private static final long serialVersionUID = 1820639344042666872L; + @Getter + private long retryAfter = -1L; + + public APITooManyRequestException(final T_ message, long retryAfter) { + super(message); + this.retryAfter = retryAfter; + setStatusCode(429); + } + + @Override + protected String defaultMessage() { + return getApi() + "#" + getResource() + ": Case creation limit reached."; + } +} diff --git a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/server/servlet/ToolkitHttpServlet.java b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/server/servlet/ToolkitHttpServlet.java index 07275b39d29..3b83e647f36 100644 --- a/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/server/servlet/ToolkitHttpServlet.java +++ b/bpm/bonita-web-server/src/main/java/org/bonitasoft/web/toolkit/server/servlet/ToolkitHttpServlet.java @@ -15,6 +15,11 @@ import java.io.IOException; import java.io.PrintWriter; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.ServletRequest; @@ -26,7 +31,14 @@ import org.bonitasoft.console.common.server.utils.LocaleUtils; import org.bonitasoft.web.rest.server.framework.json.JSonSimpleDeserializer; import org.bonitasoft.web.toolkit.client.common.CommonDateFormater; -import org.bonitasoft.web.toolkit.client.common.exception.api.*; +import org.bonitasoft.web.toolkit.client.common.exception.api.APIException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APIForbiddenException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APIIncorrectIdException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APIItemIdMalformedException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APIItemNotFoundException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APIMethodNotAllowedException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APINotFoundException; +import org.bonitasoft.web.toolkit.client.common.exception.api.APITooManyRequestException; import org.bonitasoft.web.toolkit.client.common.i18n.AbstractI18n.LOCALE; import org.bonitasoft.web.toolkit.client.common.json.JSonItemReader; import org.bonitasoft.web.toolkit.client.common.json.JSonSerializer; @@ -45,6 +57,10 @@ public abstract class ToolkitHttpServlet extends HttpServlet { private static final long serialVersionUID = -8470006030459575773L; + public static final DateTimeFormatter RFC1123_DATE_TIME_FORMATTER = DateTimeFormatter + .ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US) + .withZone(ZoneId.of("GMT")); + /** * Console logger */ @@ -104,8 +120,8 @@ protected final void outputException(final Throwable e, final HttpServletRequest try { final PrintWriter output = resp.getWriter(); - if (e instanceof APIException) { - setLocalization((APIException) e, LocaleUtils.getUserLocaleAsString(req)); + if (e instanceof APIException apiException) { + setLocalization(apiException, LocaleUtils.getUserLocaleAsString(req)); } output.print(e == null ? "" : JSonSerializer.serialize(e)); @@ -115,6 +131,14 @@ protected final void outputException(final Throwable e, final HttpServletRequest } } + protected final void outputException(final Throwable e, final HttpServletRequest req, + final HttpServletResponse resp, final int httpStatusCode, Map headers) { + for (var header : headers.entrySet()) { + resp.addHeader(header.getKey(), header.getValue()); + } + outputException(e, req, resp, httpStatusCode); + } + /** * Output an exception in JSon. Expect the status code to be already set * @@ -161,12 +185,7 @@ protected void catchAllExceptions(final Throwable exception, final HttpServletRe LOGGER.info(exception.getMessage(), exception); } outputException(exception, req, resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED); - } else if (exception instanceof APINotFoundException) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info(exception.getMessage(), exception); - } - outputException(exception, req, resp, HttpServletResponse.SC_NOT_FOUND); - } else if (exception instanceof ServiceNotFoundException) { + } else if (exception instanceof APINotFoundException || exception instanceof ServiceNotFoundException) { if (LOGGER.isInfoEnabled()) { LOGGER.info(exception.getMessage(), exception); } @@ -194,6 +213,13 @@ protected void catchAllExceptions(final Throwable exception, final HttpServletRe LOGGER.debug(exception.getMessage(), exception); } outputException(exception, req, resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } else if (exception instanceof APITooManyRequestException ex) { + if (LOGGER.isErrorEnabled()) { + LOGGER.error(exception.getMessage(), exception); + } + var headers = Map.of("Retry-After", + RFC1123_DATE_TIME_FORMATTER.format(Instant.ofEpochMilli(ex.getRetryAfter()))); + outputException(exception, req, resp, ex.getStatusCode(), headers); } else { if (LOGGER.isErrorEnabled()) { LOGGER.error(exception.getMessage(), exception); diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_es.po b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_es.po index 40607ba2b4e..d030b060144 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_es.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_es.po @@ -97,7 +97,7 @@ msgstr "Una aplicación es un entorno personalizado para un perfil de usuario es msgid "An error has occurred. For more information, check the log file." msgstr "Ha ocurrido un error. Para más información, compruebe el archivo de registro." -msgid "An error occured during categories update" +msgid "An error occurred during categories update" msgstr "Se produjo un error durante la actualización de las categorías" msgid "An error occurred when deploying the BDM. Consult the logs for more information." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_fr.po b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_fr.po index cac772b1ee8..09a72933fd4 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_fr.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_fr.po @@ -97,7 +97,7 @@ msgstr "Une application est un environnement adapté à un profil particulier, d msgid "An error has occurred. For more information, check the log file." msgstr "Une erreur s'est produite. Pour plus d'informations, consultez les logs." -msgid "An error occured during categories update" +msgid "An error occurred during categories update" msgstr "Une erreur s'est produite à la mise à jour des catégories" msgid "An error occurred when deploying the BDM. Consult the logs for more information." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_ja.po b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_ja.po index ec895c66362..10e911b1c9a 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_ja.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_ja.po @@ -97,7 +97,7 @@ msgstr "アプリケーションは、特定のユーザー プロファイル msgid "An error has occurred. For more information, check the log file." msgstr "エラーが発生しました。 詳細についてはログファイルを確認してください。" -msgid "An error occured during categories update" +msgid "An error occurred during categories update" msgstr "カテゴリの更新中にエラーが発生しました" msgid "An error occurred when deploying the BDM. Consult the logs for more information." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_pt_BR.po b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_pt_BR.po index 881b4568600..8c04ff3c0ea 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal-js_pt_BR.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal-js_pt_BR.po @@ -97,7 +97,7 @@ msgstr "Uma aplicação é um ambiente personalizado para um perfil específico, msgid "An error has occurred. For more information, check the log file." msgstr "Ocorreu um erro. Para mais informações, verifique o arquivo de log." -msgid "An error occured during categories update" +msgid "An error occurred during categories update" msgstr "Ocorreu um erro durante a atualização de categorias" msgid "An error occurred when deploying the BDM. Consult the logs for more information." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal_es.po b/bpm/bonita-web-server/src/main/resources/i18n/portal_es.po index 84a53e79451..add6e283b7b 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal_es.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal_es.po @@ -125,7 +125,7 @@ msgstr "La definición de dato %dataName% no existe para el proceso %processId%" msgid "Error during Application import file reading." msgstr "Error durante la lectura del archivo de importación de la aplicación." -msgid "Error occured when starting process %processId%" +msgid "Error occurred when starting process %processId%" msgstr "Ha ocurrido un error al iniciar el proceso %processId%" msgid "Error uploading the file. Maybe your session expired. You can try to refresh the page." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal_fr.po b/bpm/bonita-web-server/src/main/resources/i18n/portal_fr.po index 434ab7111c8..b04da05a302 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal_fr.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal_fr.po @@ -125,7 +125,7 @@ msgstr "Data definition %dataName% n'existe pas pour le process %processId%" msgid "Error during Application import file reading." msgstr "Erreur lors de l'importation de l'Application." -msgid "Error occured when starting process %processId%" +msgid "Error occurred when starting process %processId%" msgstr "Une erreur s'est produite au démarrage du processus %processId%" msgid "Error uploading the file. Maybe your session expired. You can try to refresh the page." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal_ja.po b/bpm/bonita-web-server/src/main/resources/i18n/portal_ja.po index 849a9dfffe4..4480dbc0687 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal_ja.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal_ja.po @@ -125,7 +125,7 @@ msgstr "データ定義:%dataName% は、プロセス:%processId% に存在 msgid "Error during Application import file reading." msgstr "アプリケーションのインポート ファイルの読み取り中にエラーが発生しました。" -msgid "Error occured when starting process %processId%" +msgid "Error occurred when starting process %processId%" msgstr "プロセス:%processId% の開始時にエラーが発生しました" msgid "Error uploading the file. Maybe your session expired. You can try to refresh the page." diff --git a/bpm/bonita-web-server/src/main/resources/i18n/portal_pt_BR.po b/bpm/bonita-web-server/src/main/resources/i18n/portal_pt_BR.po index 36e35621d88..7b5baaf74cd 100644 --- a/bpm/bonita-web-server/src/main/resources/i18n/portal_pt_BR.po +++ b/bpm/bonita-web-server/src/main/resources/i18n/portal_pt_BR.po @@ -125,7 +125,7 @@ msgstr "Definição do dado %dataName% não existe para o processo %processId%" msgid "Error during Application import file reading." msgstr "Erro na leitura do arquivo de importação de aplicações." -msgid "Error occured when starting process %processId%" +msgid "Error occurred when starting process %processId%" msgstr "Ocorreu um erro ao iniciar o processo %processId%" msgid "Error uploading the file. Maybe your session expired. You can try to refresh the page." diff --git a/bpm/bonita-web-server/src/test/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResourceTest.java b/bpm/bonita-web-server/src/test/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResourceTest.java index 5ca9966d28a..c5ea4ddcb75 100644 --- a/bpm/bonita-web-server/src/test/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResourceTest.java +++ b/bpm/bonita-web-server/src/test/java/org/bonitasoft/web/rest/server/api/bpm/process/ProcessInstantiationResourceTest.java @@ -23,6 +23,7 @@ import java.io.Serializable; import java.util.Arrays; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -155,7 +156,7 @@ public void should_instanciate_a_process_with_given_inputs_for_a_specific_user() } @Test - public void should_respond_400_Bad_request_when_contract_is_not_validated_when_instanciate_a_process() + public void should_respond_400_Bad_request_when_contract_is_not_validated_when_instantiate_a_process() throws Exception { doThrow(new ContractViolationException("aMessage", "aMessage", asList("first explanation", "second explanation"), null)) @@ -164,15 +165,15 @@ public void should_respond_400_Bad_request_when_contract_is_not_validated_when_i final Response response = request(URL_API_PROCESS_INSTANTIATION_TEST).post(VALID_POST_BODY); - assertThat(response).hasStatus(Status.CLIENT_ERROR_BAD_REQUEST); assertThat(response) + .hasStatus(Status.CLIENT_ERROR_BAD_REQUEST) .hasJsonEntityEqualTo( "{\"exception\":\"class org.bonitasoft.engine.bpm.contract.ContractViolationException\",\"message\":\"aMessage\",\"explanations\":[\"first explanation\",\"second explanation\"]}"); verify(processInstantiationResource.typeConverterUtil, times(0)).deleteTemporaryFiles(anyMap()); } @Test - public void should_respond_500_Internal_server_error_when_error_occurs_on_process_instanciation() throws Exception { + public void should_respond_500_Internal_server_error_when_error_occurs_on_process_instantiation() throws Exception { doThrow(new ProcessExecutionException("aMessage")) .when(processAPI).startProcessWithInputs(anyLong(), anyMapOf(String.class, Serializable.class)); @@ -184,6 +185,21 @@ public void should_respond_500_Internal_server_error_when_error_occurs_on_proces verify(processInstantiationResource.typeConverterUtil, times(0)).deleteTemporaryFiles(anyMap()); } + @Test + public void should_respond_429_Too_Many_Requests_when_case_creation_limit_reached() throws Exception { + var retryAfter = new Date(); + doThrow(new ProcessExecutionException(new RuntimeException("aMessage"), retryAfter.getTime())) + .when(processAPI).startProcessWithInputs(anyLong(), anyMapOf(String.class, Serializable.class)); + + final Response response = request(URL_API_PROCESS_INSTANTIATION_TEST).post(VALID_POST_BODY); + + assertThat(response).hasStatus(Status.CLIENT_ERROR_TOO_MANY_REQUESTS); + assertThat(response.getRetryAfter()).isInSameSecondAs(retryAfter); + assertThat(response.getEntityAsText()) + .contains("Case creation limit reached.") + .contains("Unable to start the process with ID"); + } + @Test public void should_respond_400_Bad_request_when_trying_to_execute_with_not_json_payload() throws Exception { final Response response = request(URL_API_PROCESS_INSTANTIATION_TEST).post("invalid json string"); @@ -261,4 +277,5 @@ public void should_getProcessDefinitionIdParameter_throws_an_exception_when_task } } + }