This is an automated email from the ASF dual-hosted git repository.
porcelli pushed a commit to branch main
in repository
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git
The following commit(s) were added to refs/heads/main by this push:
new 912c47011d [incubator-kie-issues-1550] Add Transaction error handling
when transaction is enabled (#3740)
912c47011d is described below
commit 912c47011d8ff244e4d578795de76bf57e9c2b6c
Author: Enrique <[email protected]>
AuthorDate: Fri Nov 1 20:02:34 2024 +0100
[incubator-kie-issues-1550] Add Transaction error handling when transaction
is enabled (#3740)
* [incubator-kie-issues-1550] Add Transaction error handling when
transaction is enabled
* ProcessGenerationIT fix tests
* clean up exception handling
* add exception handler
* handlers creation for spring boot and quarkus
* fix throwable
* fix compilation errors
* fix ProcessGenerationIT
* fix java standalone no tx
* fix quarkus exceptions handling
* ProcessResourceGeneratorTest fix
* fix resources
* fix quarkus error handling
* fix spring boot unitof work
* fix transactions templates
* fix template class name
* fix
* fix composed messages based on the exceptions processed
---
.../exceptions/AbstractExceptionsHandler.java | 142 ++++++++++++++
.../resource/exceptions/BaseExceptionsHandler.java | 203 ---------------------
.../resource/exceptions/ExceptionBodyMessage.java | 57 ++++++
.../exceptions/ExceptionBodyMessageFunctions.java | 124 +++++++++++++
.../resource/exceptions/RestExceptionHandler.java | 58 ++++++
.../exceptions/BaseExceptionHandlerTest.java | 14 +-
.../org/kie/kogito/handler/ExceptionHandler.java | 12 +-
.../java/org/jbpm/bpmn2/xml/ProcessHandler.java | 4 +-
.../java/org/jbpm/workflow/core/impl/NodeImpl.java | 6 +-
.../org/jbpm/workflow/core/node/ActionNode.java | 6 +-
.../java/org/jbpm/workflow/core/node/EndNode.java | 4 +-
.../org/jbpm/workflow/core/node/EventNode.java | 6 +-
.../org/jbpm/workflow/core/node/MilestoneNode.java | 6 +-
.../org/jbpm/workflow/core/node/RuleSetNode.java | 5 +-
.../java/org/jbpm/workflow/core/node/Split.java | 4 +-
.../org/jbpm/workflow/core/node/StartNode.java | 4 +-
.../jbpm/workflow/core/node/SubProcessNode.java | 6 +-
.../org/jbpm/workflow/core/node/TimerNode.java | 6 +-
.../org/jbpm/workflow/core/node/WorkItemNode.java | 6 +-
.../instance/WorkflowProcessParameters.java | 56 ++++++
.../workflow/instance/impl/NodeInstanceImpl.java | 18 +-
.../instance/impl/WorkflowProcessInstanceImpl.java | 10 +
.../instance/node/ForEachNodeInstance.java | 4 +-
.../codegen/process/ProcessGenerationIT.java | 16 +-
.../kie/kogito/codegen/process/ProcessCodegen.java | 29 ++-
.../kogito/codegen/process/util/CodegenUtil.java | 12 +-
...ExceptionHandlerTransactionQuarkusTemplate.java | 77 ++++++++
.../ExceptionHandlerTransactionSpringTemplate.java | 73 ++++++++
quarkus/addons/rest-exception-handler/pom.xml | 4 +
.../resource/exceptions/BaseExceptionMapper.java | 7 -
.../resource/exceptions/ExceptionsHandler.java | 28 +--
...nMapper.java => ExceptionsHandlerProducer.java} | 15 +-
.../exceptions/IllegalArgumentExceptionMapper.java | 4 +
.../InvalidLifeCyclePhaseExceptionMapper.java | 4 +
.../InvalidTransitionExceptionMapper.java | 4 +
.../NodeInstanceNotFoundExceptionMapper.java | 4 +
.../exceptions/NodeNotFoundExceptionMapper.java | 4 +
.../exceptions/NotAuthorizedExceptionMapper.java | 4 +
.../ProcessInstanceDuplicatedExceptionMapper.java | 4 +
.../ProcessInstanceExecutionExceptionMapper.java | 4 +
.../ProcessInstanceNotFoundExceptionMapper.java | 4 +
...erTaskInstanceNotAuthorizedExceptionMapper.java | 4 +
.../UserTaskInstanceNotFoundExceptionMapper.java | 4 +
.../UserTaskTransitionExceptionMapper.java | 4 +
.../VariableViolationExceptionMapper.java | 4 +
.../WorkItemExecutionExceptionMapper.java | 4 +
.../WorkItemNotFoundExceptionMapper.java | 4 +
.../resource/exceptions/ExceptionsHandlerTest.java | 8 +-
.../addon/source/files/SourceFilesResource.java | 47 +++--
.../source/files/SourceFilesResourceTest.java | 4 +-
.../exceptions/springboot/ExceptionsHandler.java | 59 +++---
.../springboot/ExceptionsHandlerTest.java | 22 ++-
.../org/kie/kogito/process/KogitoBeanProducer.java | 9 +
53 files changed, 887 insertions(+), 344 deletions(-)
diff --git
a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/AbstractExceptionsHandler.java
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/AbstractExceptionsHandler.java
new file mode 100644
index 0000000000..26923edcd2
--- /dev/null
+++
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/AbstractExceptionsHandler.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.resource.exceptions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.kie.kogito.handler.ExceptionHandler;
+import org.kie.kogito.internal.process.runtime.MessageException;
+import org.kie.kogito.internal.process.workitem.InvalidLifeCyclePhaseException;
+import org.kie.kogito.internal.process.workitem.InvalidTransitionException;
+import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
+import org.kie.kogito.internal.process.workitem.WorkItemExecutionException;
+import org.kie.kogito.internal.process.workitem.WorkItemNotFoundException;
+import org.kie.kogito.process.NodeInstanceNotFoundException;
+import org.kie.kogito.process.NodeNotFoundException;
+import org.kie.kogito.process.ProcessInstanceDuplicatedException;
+import org.kie.kogito.process.ProcessInstanceExecutionException;
+import org.kie.kogito.process.ProcessInstanceNotFoundException;
+import org.kie.kogito.process.VariableViolationException;
+import org.kie.kogito.usertask.UserTaskInstanceNotAuthorizedException;
+import org.kie.kogito.usertask.UserTaskInstanceNotFoundException;
+import org.kie.kogito.usertask.lifecycle.UserTaskTransitionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.nodeInstanceNotFoundMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.nodeNotFoundMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.processInstanceDuplicatedMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.processInstanceExecutionMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.processInstanceNotFoundExceptionMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.variableViolationMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.workItemExecutionMessageException;
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.workItemNotFoundMessageException;
+import static
org.kie.kogito.resource.exceptions.RestExceptionHandler.newExceptionHandler;
+
+public abstract class AbstractExceptionsHandler<T> {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(AbstractExceptionsHandler.class);
+
+ RestExceptionHandler<? extends Exception, T> DEFAULT_HANDLER =
newExceptionHandler(Exception.class, this::badRequest);
+
+ private Map<Class<? extends Throwable>, RestExceptionHandler<? extends
Throwable, T>> mapper;
+
+ private List<ExceptionHandler> errorHandlers;
+
+ protected AbstractExceptionsHandler() {
+ this(Collections.emptyList());
+ }
+
+ protected AbstractExceptionsHandler(Iterable<ExceptionHandler>
errorHandlers) {
+ List<RestExceptionHandler<? extends Throwable, T>> handlers =
List.<RestExceptionHandler<? extends Throwable, T>> of(
+ newExceptionHandler(InvalidLifeCyclePhaseException.class,
this::badRequest),
+ newExceptionHandler(UserTaskTransitionException.class,
this::badRequest),
+ newExceptionHandler(UserTaskInstanceNotFoundException.class,
this::notFound),
+
newExceptionHandler(UserTaskInstanceNotAuthorizedException.class,
this::forbidden),
+ newExceptionHandler(InvalidTransitionException.class,
this::badRequest),
+ newExceptionHandler(NodeInstanceNotFoundException.class,
nodeInstanceNotFoundMessageException(), this::notFound),
+ newExceptionHandler(NodeNotFoundException.class,
nodeNotFoundMessageException(), this::notFound),
+ newExceptionHandler(NotAuthorizedException.class,
this::forbidden),
+ newExceptionHandler(ProcessInstanceDuplicatedException.class,
processInstanceDuplicatedMessageException(), this::conflict),
+ newExceptionHandler(ProcessInstanceExecutionException.class,
processInstanceExecutionMessageException(), this::internalError),
+ newExceptionHandler(ProcessInstanceNotFoundException.class,
processInstanceNotFoundExceptionMessageException(), this::notFound),
+ newExceptionHandler(WorkItemNotFoundException.class,
workItemNotFoundMessageException(), this::notFound),
+ newExceptionHandler(VariableViolationException.class,
variableViolationMessageException(), this::badRequest),
+ newExceptionHandler(WorkItemExecutionException.class,
workItemExecutionMessageException(), this::fromErrorCode),
+ newExceptionHandler(IllegalArgumentException.class,
this::badRequest),
+ newExceptionHandler(MessageException.class, this::badRequest));
+
+ this.mapper = new HashMap<>();
+ for (RestExceptionHandler<? extends Throwable, T> handler : handlers) {
+ this.mapper.put(handler.getType(), handler);
+ }
+ this.errorHandlers = new ArrayList<>();
+ errorHandlers.iterator().forEachRemaining(this.errorHandlers::add);
+
+ }
+
+ private T fromErrorCode(ExceptionBodyMessage message) {
+ switch (message.getErrorCode()) {
+ case "400":
+ return badRequest(message);
+ case "403":
+ return forbidden(message);
+ case "404":
+ return notFound(message);
+ case "409":
+ return conflict(message);
+ default:
+ return internalError(message);
+ }
+ }
+
+ protected abstract T badRequest(ExceptionBodyMessage body);
+
+ protected abstract T conflict(ExceptionBodyMessage body);
+
+ protected abstract T internalError(ExceptionBodyMessage body);
+
+ protected abstract T notFound(ExceptionBodyMessage body);
+
+ protected abstract T forbidden(ExceptionBodyMessage body);
+
+ public T mapException(Exception exceptionThrown) {
+
+ var handler = mapper.getOrDefault(exceptionThrown.getClass(),
DEFAULT_HANDLER);
+ ExceptionBodyMessage message = handler.getContent(exceptionThrown);
+
+ Throwable rootCause = exceptionThrown.getCause();
+ while (rootCause != null) {
+ if (mapper.containsKey(rootCause.getClass())) {
+ handler = mapper.get(rootCause.getClass());
+ message.merge(handler.getContent(rootCause));
+ }
+ rootCause = rootCause.getCause();
+ }
+ // we invoked the error handlers
+ errorHandlers.forEach(e -> e.handle(exceptionThrown));
+ T response = handler.buildResponse(message);
+ LOG.debug("mapping exception {} with response {}", exceptionThrown,
message.getBody());
+ return response;
+ }
+}
diff --git
a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java
deleted file mode 100644
index c326eeebe7..0000000000
---
a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionsHandler.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.kie.kogito.resource.exceptions;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Function;
-
-import org.kie.kogito.internal.process.runtime.MessageException;
-import org.kie.kogito.internal.process.workitem.InvalidLifeCyclePhaseException;
-import org.kie.kogito.internal.process.workitem.InvalidTransitionException;
-import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
-import org.kie.kogito.internal.process.workitem.WorkItemExecutionException;
-import org.kie.kogito.internal.process.workitem.WorkItemNotFoundException;
-import org.kie.kogito.process.NodeInstanceNotFoundException;
-import org.kie.kogito.process.NodeNotFoundException;
-import org.kie.kogito.process.ProcessInstanceDuplicatedException;
-import org.kie.kogito.process.ProcessInstanceExecutionException;
-import org.kie.kogito.process.ProcessInstanceNotFoundException;
-import org.kie.kogito.process.VariableViolationException;
-import org.kie.kogito.usertask.UserTaskInstanceNotAuthorizedException;
-import org.kie.kogito.usertask.UserTaskInstanceNotFoundException;
-import org.kie.kogito.usertask.lifecycle.UserTaskTransitionException;
-
-public abstract class BaseExceptionsHandler<T> {
-
- public static final String MESSAGE = "message";
- public static final String PROCESS_INSTANCE_ID = "processInstanceId";
- private static final String TASK_ID = "taskId";
- public static final String VARIABLE = "variable";
- public static final String NODE_INSTANCE_ID = "nodeInstanceId";
- public static final String NODE_ID = "nodeId";
- public static final String FAILED_NODE_ID = "failedNodeId";
- public static final String ID = "id";
- private final Map<Class<? extends Exception>, FunctionHolder<T, ?>> mapper;
-
- private static class FunctionHolder<T, R> {
- private final Function<Exception, R> contentGenerator;
- private final Function<Exception, Function<R, T>> responseGenerator;
-
- public FunctionHolder(Function<Exception, R> contentGenerator,
Function<Exception, Function<R, T>> responseGenerator) {
- this.contentGenerator = contentGenerator;
- this.responseGenerator = responseGenerator;
- }
-
- public Function<Exception, R> getContentGenerator() {
- return contentGenerator;
- }
-
- public Function<Exception, Function<R, T>> getResponseGenerator() {
- return responseGenerator;
- }
- }
-
- private final FunctionHolder<T, Exception> defaultHolder = new
FunctionHolder<>(ex -> ex, ex -> BaseExceptionsHandler.this::internalError);
- private final FunctionHolder<T, ?> messageFunctionHolder = new
FunctionHolder<>(ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::badRequest);
-
- protected BaseExceptionsHandler() {
- mapper = new HashMap<>();
- mapper.put(InvalidLifeCyclePhaseException.class, new FunctionHolder<>(
- ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::badRequest));
-
- mapper.put(UserTaskTransitionException.class, new FunctionHolder<>(
- ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::badRequest));
-
- mapper.put(UserTaskInstanceNotFoundException.class, new
FunctionHolder<>(
- ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::notFound));
-
- mapper.put(UserTaskInstanceNotAuthorizedException.class, new
FunctionHolder<>(
- ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::forbidden));
-
- mapper.put(InvalidTransitionException.class, new FunctionHolder<>(
- ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::badRequest));
-
- mapper.put(NodeInstanceNotFoundException.class, new FunctionHolder<>(
- ex -> {
- NodeInstanceNotFoundException exception =
(NodeInstanceNotFoundException) ex;
- Map<String, String> response = new HashMap<>();
- response.put(MESSAGE, exception.getMessage());
- response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
- response.put(NODE_INSTANCE_ID,
exception.getNodeInstanceId());
- return response;
- }, ex -> BaseExceptionsHandler.this::notFound));
-
- mapper.put(NodeNotFoundException.class, new FunctionHolder<>(
- ex -> {
- NodeNotFoundException exception = (NodeNotFoundException)
ex;
- Map<String, String> response = new HashMap<>();
- response.put(MESSAGE, exception.getMessage());
- response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
- response.put(NODE_ID, exception.getNodeId());
- return response;
- }, ex -> BaseExceptionsHandler.this::notFound));
-
- mapper.put(NotAuthorizedException.class, new FunctionHolder<>(
- ex -> Collections.singletonMap(MESSAGE, ex.getMessage()), ex
-> BaseExceptionsHandler.this::forbidden));
-
- mapper.put(ProcessInstanceDuplicatedException.class, new
FunctionHolder<>(
- ex -> {
- ProcessInstanceDuplicatedException exception =
(ProcessInstanceDuplicatedException) ex;
- Map<String, String> response = new HashMap<>();
- response.put(MESSAGE, exception.getMessage());
- response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
- return response;
- }, ex -> BaseExceptionsHandler.this::conflict));
-
- mapper.put(ProcessInstanceExecutionException.class, new
FunctionHolder<>(
- ex -> {
- ProcessInstanceExecutionException exception =
(ProcessInstanceExecutionException) ex;
- Map<String, String> response = new HashMap<>();
- response.put(ID, exception.getProcessInstanceId());
- response.put(FAILED_NODE_ID, exception.getFailedNodeId());
- response.put(MESSAGE, exception.getErrorMessage());
- return response;
- }, ex -> BaseExceptionsHandler.this::internalError));
-
- mapper.put(ProcessInstanceNotFoundException.class, new
FunctionHolder<>(
- ex -> {
- ProcessInstanceNotFoundException exception =
(ProcessInstanceNotFoundException) ex;
- Map<String, String> response = new HashMap<>();
- response.put(MESSAGE, exception.getMessage());
- response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
- return response;
- }, ex -> BaseExceptionsHandler.this::notFound));
-
- mapper.put(WorkItemNotFoundException.class, new FunctionHolder<>(ex ->
{
- WorkItemNotFoundException exception = (WorkItemNotFoundException)
ex;
- return Map.of(MESSAGE, exception.getMessage(), TASK_ID,
exception.getWorkItemId());
- }, ex -> BaseExceptionsHandler.this::notFound));
-
- mapper.put(VariableViolationException.class, new FunctionHolder<>(
- ex -> {
- VariableViolationException exception =
(VariableViolationException) ex;
- Map<String, String> response = new HashMap<>();
- response.put(MESSAGE, exception.getMessage() + " : " +
exception.getErrorMessage());
- response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
- response.put(VARIABLE, exception.getVariableName());
- return response;
- }, ex -> BaseExceptionsHandler.this::badRequest));
-
- mapper.put(WorkItemExecutionException.class, new FunctionHolder<>(
- ex -> Map.of(MESSAGE, ex.getMessage()),
- ex -> fromErrorCode(((WorkItemExecutionException)
ex).getErrorCode())));
- mapper.put(IllegalArgumentException.class, messageFunctionHolder);
- mapper.put(MessageException.class, messageFunctionHolder);
- }
-
- private <R> Function<R, T> fromErrorCode(String errorCode) {
- switch (errorCode) {
- case "400":
- return this::badRequest;
- case "403":
- return this::forbidden;
- case "404":
- return this::notFound;
- case "409":
- return this::conflict;
- default:
- return this::internalError;
- }
- }
-
- protected abstract <R> T badRequest(R body);
-
- protected abstract <R> T conflict(R body);
-
- protected abstract <R> T internalError(R body);
-
- protected abstract <R> T notFound(R body);
-
- protected abstract <R> T forbidden(R body);
-
- public <R extends Exception, U> T mapException(R exception) {
- FunctionHolder<T, U> holder = (FunctionHolder<T, U>)
mapper.getOrDefault(exception.getClass(), defaultHolder);
- U body = holder.getContentGenerator().apply(exception);
- Throwable rootCause = exception.getCause();
- while (rootCause != null) {
- if (mapper.containsKey(rootCause.getClass())) {
- holder = (FunctionHolder<T, U>)
mapper.get(rootCause.getClass());
- exception = (R) rootCause;
- }
- rootCause = rootCause.getCause();
- }
- return holder.getResponseGenerator().apply(exception).apply(body);
- }
-}
diff --git
a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionBodyMessage.java
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionBodyMessage.java
new file mode 100644
index 0000000000..b491b111f4
--- /dev/null
+++
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionBodyMessage.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.resource.exceptions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ExceptionBodyMessage {
+
+ public static final String MESSAGE = "message";
+ public static final String PROCESS_INSTANCE_ID = "processInstanceId";
+ public static final String TASK_ID = "taskId";
+ public static final String VARIABLE = "variable";
+ public static final String NODE_INSTANCE_ID = "nodeInstanceId";
+ public static final String NODE_ID = "nodeId";
+ public static final String FAILED_NODE_ID = "failedNodeId";
+ public static final String ID = "id";
+ public static final String ERROR_CODE = "errorCode";
+
+ private Map<String, String> body;
+
+ public ExceptionBodyMessage() {
+ body = new HashMap<>();
+ }
+
+ public ExceptionBodyMessage(Map<String, String> body) {
+ this.body = new HashMap<>(body);
+ }
+
+ public Map<String, String> getBody() {
+ return body;
+ }
+
+ public String getErrorCode() {
+ return body.getOrDefault(ERROR_CODE, "");
+ }
+
+ public void merge(ExceptionBodyMessage content) {
+ this.body.putAll(content.body);
+ }
+}
diff --git
a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionBodyMessageFunctions.java
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionBodyMessageFunctions.java
new file mode 100644
index 0000000000..0bc1e6fd81
--- /dev/null
+++
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionBodyMessageFunctions.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.resource.exceptions;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.kie.kogito.internal.process.workitem.WorkItemExecutionException;
+import org.kie.kogito.internal.process.workitem.WorkItemNotFoundException;
+import org.kie.kogito.process.NodeInstanceNotFoundException;
+import org.kie.kogito.process.NodeNotFoundException;
+import org.kie.kogito.process.ProcessInstanceDuplicatedException;
+import org.kie.kogito.process.ProcessInstanceExecutionException;
+import org.kie.kogito.process.ProcessInstanceNotFoundException;
+import org.kie.kogito.process.VariableViolationException;
+
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessage.ERROR_CODE;
+
+public class ExceptionBodyMessageFunctions {
+
+ public static final String MESSAGE = "message";
+ public static final String PROCESS_INSTANCE_ID = "processInstanceId";
+ public static final String TASK_ID = "taskId";
+ public static final String VARIABLE = "variable";
+ public static final String NODE_INSTANCE_ID = "nodeInstanceId";
+ public static final String NODE_ID = "nodeId";
+ public static final String FAILED_NODE_ID = "failedNodeId";
+ public static final String ID = "id";
+
+ public static <T extends Exception> Function<T, ExceptionBodyMessage>
defaultMessageException() {
+ return ex -> new
ExceptionBodyMessage(Collections.singletonMap(MESSAGE, ex.getMessage()));
+ }
+
+ public static Function<NodeInstanceNotFoundException,
ExceptionBodyMessage> nodeInstanceNotFoundMessageException() {
+ return ex -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(MESSAGE, ex.getMessage());
+ response.put(PROCESS_INSTANCE_ID, ex.getProcessInstanceId());
+ response.put(NODE_INSTANCE_ID, ex.getNodeInstanceId());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+
+ public static Function<NodeNotFoundException, ExceptionBodyMessage>
nodeNotFoundMessageException() {
+ return exception -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(MESSAGE, exception.getMessage());
+ response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
+ response.put(NODE_ID, exception.getNodeId());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+
+ public static Function<ProcessInstanceDuplicatedException,
ExceptionBodyMessage> processInstanceDuplicatedMessageException() {
+ return exception -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(MESSAGE, exception.getMessage());
+ response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+
+ public static Function<ProcessInstanceExecutionException,
ExceptionBodyMessage> processInstanceExecutionMessageException() {
+ return exception -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(ID, exception.getProcessInstanceId());
+ response.put(FAILED_NODE_ID, exception.getFailedNodeId());
+ response.put(MESSAGE, exception.getErrorMessage());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+
+ public static Function<ProcessInstanceNotFoundException,
ExceptionBodyMessage> processInstanceNotFoundExceptionMessageException() {
+ return exception -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(MESSAGE, exception.getMessage());
+ response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+
+ public static Function<WorkItemNotFoundException, ExceptionBodyMessage>
workItemNotFoundMessageException() {
+ return exception -> {
+ return new ExceptionBodyMessage(Map.of(MESSAGE,
exception.getMessage(), TASK_ID, exception.getWorkItemId()));
+ };
+ }
+
+ public static Function<WorkItemExecutionException, ExceptionBodyMessage>
workItemExecutionMessageException() {
+ return exception -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(MESSAGE, exception.getMessage());
+ response.put(ERROR_CODE, exception.getErrorCode());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+
+ public static Function<VariableViolationException, ExceptionBodyMessage>
variableViolationMessageException() {
+ return exception -> {
+ Map<String, String> response = new HashMap<>();
+ response.put(MESSAGE, exception.getMessage() + " : " +
exception.getErrorMessage());
+ response.put(PROCESS_INSTANCE_ID,
exception.getProcessInstanceId());
+ response.put(VARIABLE, exception.getVariableName());
+ return new ExceptionBodyMessage(response);
+ };
+ }
+}
diff --git
a/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/RestExceptionHandler.java
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/RestExceptionHandler.java
new file mode 100644
index 0000000000..083e4efe83
--- /dev/null
+++
b/addons/common/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/RestExceptionHandler.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.resource.exceptions;
+
+import java.util.function.Function;
+
+import static
org.kie.kogito.resource.exceptions.ExceptionBodyMessageFunctions.defaultMessageException;
+
+public class RestExceptionHandler<EXCEPTION extends Throwable, RESPONSE> {
+ private final Function<EXCEPTION, ExceptionBodyMessage> messageConverter;
+
+ private final Function<ExceptionBodyMessage, RESPONSE> responseConverter;
+
+ private Class<EXCEPTION> type;
+
+ public RestExceptionHandler(Class<EXCEPTION> type, Function<EXCEPTION,
ExceptionBodyMessage> messageConverter, Function<ExceptionBodyMessage,
RESPONSE> responseConverter) {
+ this.type = type;
+ this.messageConverter = messageConverter;
+ this.responseConverter = responseConverter;
+ }
+
+ public Class<EXCEPTION> getType() {
+ return type;
+ }
+
+ public ExceptionBodyMessage getContent(Throwable exception) {
+ return messageConverter.apply(getType().cast(exception));
+ }
+
+ public RESPONSE buildResponse(ExceptionBodyMessage exceptionBodyMessage) {
+ return responseConverter.apply(exceptionBodyMessage);
+ }
+
+ public static <TYPE extends Exception, RES> RestExceptionHandler<TYPE,
RES> newExceptionHandler(Class<TYPE> type, Function<TYPE, ExceptionBodyMessage>
contentGenerator,
+ Function<ExceptionBodyMessage, RES> responseGenerator) {
+ return new RestExceptionHandler<TYPE, RES>(type, contentGenerator,
responseGenerator);
+ }
+
+ public static <F extends Exception, R> RestExceptionHandler<F, R>
newExceptionHandler(Class<F> type, Function<ExceptionBodyMessage, R>
responseGenerator) {
+ return new RestExceptionHandler<F, R>(type, defaultMessageException(),
responseGenerator);
+ }
+}
\ No newline at end of file
diff --git
a/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java
b/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java
index 01f244915d..bf8f28fc31 100644
---
a/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java
+++
b/addons/common/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/BaseExceptionHandlerTest.java
@@ -40,7 +40,7 @@ import static org.mockito.Mockito.spy;
@ExtendWith(MockitoExtension.class)
class BaseExceptionHandlerTest {
- private BaseExceptionsHandler tested;
+ private AbstractExceptionsHandler<Object> tested;
@Mock
private Object badRequestResponse;
@@ -59,29 +59,29 @@ class BaseExceptionHandlerTest {
@BeforeEach
void setUp() {
- tested = spy(new BaseExceptionsHandler() {
+ tested = spy(new AbstractExceptionsHandler<Object>() {
@Override
- protected Object badRequest(Object body) {
+ protected Object badRequest(ExceptionBodyMessage body) {
return badRequestResponse;
}
@Override
- protected Object conflict(Object body) {
+ protected Object conflict(ExceptionBodyMessage body) {
return conflictResponse;
}
@Override
- protected Object internalError(Object body) {
+ protected Object internalError(ExceptionBodyMessage body) {
return internalErrorResponse;
}
@Override
- protected Object notFound(Object body) {
+ protected Object notFound(ExceptionBodyMessage body) {
return notFoundResponse;
}
@Override
- protected Object forbidden(Object body) {
+ protected Object forbidden(ExceptionBodyMessage body) {
return forbiddenResponse;
}
});
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
b/api/kogito-api/src/main/java/org/kie/kogito/handler/ExceptionHandler.java
similarity index 69%
copy from
quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
copy to
api/kogito-api/src/main/java/org/kie/kogito/handler/ExceptionHandler.java
index 56a734a511..7bfbdf37ef 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/handler/ExceptionHandler.java
@@ -16,16 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.kie.kogito.resource.exceptions;
+package org.kie.kogito.handler;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.ext.Provider;
+public interface ExceptionHandler {
-@Provider
-public class IllegalArgumentExceptionMapper extends
BaseExceptionMapper<IllegalArgumentException> {
+ void handle(Exception th);
- @Override
- public Response toResponse(IllegalArgumentException e) {
- return exceptionsHandler.mapException(e);
- }
}
diff --git
a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
index 644f9fe25a..72180a45c1 100755
--- a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
+++ b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
@@ -107,6 +107,8 @@ import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
public class ProcessHandler extends BaseAbstractHandler implements Handler {
private static final Logger logger =
LoggerFactory.getLogger(ProcessHandler.class);
@@ -412,7 +414,7 @@ public class ProcessHandler extends BaseAbstractHandler
implements Handler {
result.setMetaData("bendpoints", connection.getBendpoints());
result.setMetaData(Metadata.UNIQUE_ID, connection.getId());
- if (source instanceof NodeImpl nodeImpl &&
Boolean.parseBoolean((String)
process.getMetaData().get("jbpm.enable.multi.con"))) {
+ if (source instanceof NodeImpl nodeImpl &&
WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(process)) {
Constraint constraint = buildConstraint(connection,
nodeImpl);
if (constraint != null) {
nodeImpl.addConstraint(new
ConnectionRef(connection.getId(), target.getId(),
org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE),
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java
index 0ea5dee550..13a21788e1 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/impl/NodeImpl.java
@@ -40,6 +40,8 @@ import org.kie.api.definition.process.Connection;
import org.kie.api.definition.process.NodeContainer;
import org.kie.api.definition.process.WorkflowElementIdentifier;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of a node.
*/
@@ -297,7 +299,7 @@ public abstract class NodeImpl implements Node,
ContextResolver, Mappable {
if (list.size() == 1) {
return list.get(0);
}
- if (Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
return list.get(0);
} else {
throw new IllegalArgumentException(
@@ -317,7 +319,7 @@ public abstract class NodeImpl implements Node,
ContextResolver, Mappable {
if (list.size() == 1) {
return list.get(0);
}
- if (Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
return list.get(0);
} else {
throw new IllegalArgumentException(
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ActionNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ActionNode.java
index 9144d42833..53f74b4143 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ActionNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/ActionNode.java
@@ -27,6 +27,8 @@ import org.jbpm.workflow.core.impl.DataAssociation;
import org.jbpm.workflow.core.impl.ExtendedNodeImpl;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of an action node.
*
@@ -53,7 +55,7 @@ public class ActionNode extends ExtendedNodeImpl {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
@@ -68,7 +70,7 @@ public class ActionNode extends ExtendedNodeImpl {
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] only accepts default outgoing connection
type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] cannot have more than one outgoing
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EndNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EndNode.java
index ae88f43956..222f13d1c7 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EndNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EndNode.java
@@ -22,6 +22,8 @@ import org.jbpm.workflow.core.Node;
import org.jbpm.workflow.core.impl.ExtendedNodeImpl;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of an end node.
*
@@ -58,7 +60,7 @@ public class EndNode extends ExtendedNodeImpl {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EventNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EventNode.java
index 42d216f483..0ce70b86f8 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EventNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/EventNode.java
@@ -28,6 +28,8 @@ import org.jbpm.workflow.core.Node;
import org.jbpm.workflow.core.impl.ExtendedNodeImpl;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
public class EventNode extends ExtendedNodeImpl implements EventNodeInterface {
private static final long serialVersionUID = 510l;
@@ -104,7 +106,7 @@ public class EventNode extends ExtendedNodeImpl implements
EventNodeInterface {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
@@ -119,7 +121,7 @@ public class EventNode extends ExtendedNodeImpl implements
EventNodeInterface {
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] only accepts default outgoing connection
type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] cannot have more than one outgoing
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/MilestoneNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/MilestoneNode.java
index 7ffabedcda..1a1ba697ff 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/MilestoneNode.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/MilestoneNode.java
@@ -24,6 +24,8 @@ import org.jbpm.workflow.core.Node;
import org.kie.api.definition.process.Connection;
import org.kie.api.runtime.process.ProcessContext;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of a milestone node.
*/
@@ -59,7 +61,7 @@ public class MilestoneNode extends StateBasedNode implements
Constrainable {
if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
throwValidationException(connection, "only accepts default
incoming connection type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throwValidationException(connection, "cannot have more than one
incoming connection!");
}
}
@@ -70,7 +72,7 @@ public class MilestoneNode extends StateBasedNode implements
Constrainable {
if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
throwValidationException(connection, "only accepts default
outgoing connection type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throwValidationException(connection, "cannot have more than one
outgoing connection!");
}
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/RuleSetNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/RuleSetNode.java
index 3d129f3b22..b7d9f87207 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/RuleSetNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/RuleSetNode.java
@@ -35,6 +35,7 @@ import org.kie.api.definition.process.Connection;
import org.kie.api.runtime.KieRuntime;
import org.kie.kogito.decision.DecisionModel;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
import static org.jbpm.workflow.instance.rule.RuleType.DRL_LANG;
/**
@@ -105,7 +106,7 @@ public class RuleSetNode extends StateBasedNode implements
ContextContainer {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
@@ -120,7 +121,7 @@ public class RuleSetNode extends StateBasedNode implements
ContextContainer {
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] only accepts default outgoing connection
type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] cannot have more than one outgoing
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/Split.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/Split.java
index fe2114905c..77c4a8e717 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/Split.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/Split.java
@@ -26,6 +26,8 @@ import org.jbpm.workflow.core.impl.ConnectionRef;
import org.jbpm.workflow.core.impl.NodeImpl;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of a split node.
*
@@ -143,7 +145,7 @@ public class Split extends NodeImpl implements
Constrainable {
+ "] only accepts default incoming connection
type!");
}
- if (!getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE).isEmpty() &&
!Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (!getIncomingConnections(Node.CONNECTION_DEFAULT_TYPE).isEmpty() &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/StartNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/StartNode.java
index 3743bbd157..e6e43a2bb3 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/StartNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/StartNode.java
@@ -27,6 +27,8 @@ import org.jbpm.workflow.core.Node;
import org.jbpm.workflow.core.impl.ExtendedNodeImpl;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of a start node.
*
@@ -92,7 +94,7 @@ public class StartNode extends ExtendedNodeImpl {
throw new IllegalArgumentException(
"A start node [" + this.getUniqueId() + ", " +
this.getName() + "] only accepts default outgoing connection type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"A start node [" + this.getUniqueId() + ", " +
this.getName() + "] cannot have more than one outgoing connection!");
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/SubProcessNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/SubProcessNode.java
index 77f873ddc7..7dcad36021 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/SubProcessNode.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/SubProcessNode.java
@@ -27,6 +27,8 @@ import org.jbpm.process.core.impl.ContextContainerImpl;
import org.jbpm.workflow.core.Node;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of a sub-flow node.
*
@@ -77,7 +79,7 @@ public class SubProcessNode extends StateBasedNode implements
ContextContainer {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
@@ -92,7 +94,7 @@ public class SubProcessNode extends StateBasedNode implements
ContextContainer {
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] only accepts default outgoing connection
type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] cannot have more than one outgoing
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/TimerNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/TimerNode.java
index e8ce9a5495..5096a47f0e 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/TimerNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/TimerNode.java
@@ -23,6 +23,8 @@ import org.jbpm.workflow.core.Node;
import org.jbpm.workflow.core.impl.ExtendedNodeImpl;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
public class TimerNode extends ExtendedNodeImpl {
private static final long serialVersionUID = 510l;
@@ -45,7 +47,7 @@ public class TimerNode extends ExtendedNodeImpl {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
@@ -60,7 +62,7 @@ public class TimerNode extends ExtendedNodeImpl {
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] only accepts default outgoing connection
type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] cannot have more than one outgoing
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/WorkItemNode.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/WorkItemNode.java
index d7cd3c06c1..5eb00999d0 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/WorkItemNode.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/WorkItemNode.java
@@ -28,6 +28,8 @@ import org.jbpm.process.core.impl.ContextContainerImpl;
import org.jbpm.workflow.core.Node;
import org.kie.api.definition.process.Connection;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Default implementation of a task node.
*
@@ -66,7 +68,7 @@ public class WorkItemNode extends StateBasedNode implements
ContextContainer {
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] only accepts default incoming connection
type!");
}
- if (getFrom() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getFrom() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getTo().getUniqueId() +
", " + connection.getTo().getName()
+ "] cannot have more than one incoming
connection!");
@@ -81,7 +83,7 @@ public class WorkItemNode extends StateBasedNode implements
ContextContainer {
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] only accepts default outgoing connection
type!");
}
- if (getTo() != null && !Boolean.parseBoolean((String)
getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if (getTo() != null &&
!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcess())) {
throw new IllegalArgumentException(
"This type of node [" + connection.getFrom().getUniqueId()
+ ", " + connection.getFrom().getName()
+ "] cannot have more than one outgoing
connection!");
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/WorkflowProcessParameters.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/WorkflowProcessParameters.java
new file mode 100644
index 0000000000..cf5c1bd611
--- /dev/null
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/WorkflowProcessParameters.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jbpm.workflow.instance;
+
+import java.util.function.Function;
+
+public class WorkflowProcessParameters {
+
+ /**
+ * Allows activities to have multiple outgoing connections
+ */
+ public static final WorkflowProcessParameter<Boolean>
WORKFLOW_PARAM_MULTIPLE_CONNECTIONS =
newBooleanParameter("jbpm.enable.multi.con");
+ public static final WorkflowProcessParameter<Boolean>
WORKFLOW_PARAM_TRANSACTIONS = newBooleanParameter("jbpm.transactions.enable");
+
+ public static WorkflowProcessParameter<String> newStringParameter(String
name) {
+ return new WorkflowProcessParameter<String>(name, Function.identity());
+ }
+
+ public static WorkflowProcessParameter<Boolean> newBooleanParameter(String
name) {
+ return new WorkflowProcessParameter<Boolean>(name,
Boolean::parseBoolean);
+ }
+
+ public static class WorkflowProcessParameter<T> {
+ private String name;
+ private Function<String, T> converter;
+
+ WorkflowProcessParameter(String name, Function<String, T> converter) {
+ this.name = name;
+ this.converter = converter;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public T get(org.kie.api.definition.process.Process workflowProcess) {
+ return converter.apply((String)
workflowProcess.getMetaData().get(name));
+ }
+ }
+}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
index fb73d73c00..fd78e89418 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
@@ -61,12 +61,15 @@ import
org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstanceContainer;
import org.kie.kogito.internal.process.runtime.KogitoProcessContext;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
+import org.kie.kogito.process.ProcessInstanceExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.jbpm.ruleflow.core.Metadata.HIDDEN;
import static org.jbpm.ruleflow.core.Metadata.INCOMING_CONNECTION;
import static org.jbpm.ruleflow.core.Metadata.OUTGOING_CONNECTION;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_TRANSACTIONS;
import static
org.kie.kogito.internal.process.runtime.KogitoProcessInstance.STATE_ACTIVE;
/**
@@ -248,10 +251,15 @@ public abstract class NodeInstanceImpl implements
org.jbpm.workflow.instance.Nod
try {
internalTrigger(from, type);
} catch (Exception e) {
- logger.debug("Node instance causing process instance error in id
{}", this.getStringId(), e);
- captureError(e);
+ if
(!WORKFLOW_PARAM_TRANSACTIONS.get(getProcessInstance().getProcess())) {
+ logger.error("Node instance causing process instance error in
id {} in a non transactional environment", this.getStringId());
+ captureError(e);
+ return;
+ } else {
+ logger.error("Node instance causing process instance error in
id {} in a transactional environment (Wrapping)", this.getStringId());
+ throw new
ProcessInstanceExecutionException(this.getProcessInstance().getId(),
this.getNodeDefinitionId(), e.getMessage(), e);
+ }
// stop after capturing error
- return;
}
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime())
@@ -260,8 +268,6 @@ public abstract class NodeInstanceImpl implements
org.jbpm.workflow.instance.Nod
}
protected void captureError(Exception e) {
- logger.error("capture error", e);
- e.printStackTrace();
getProcessInstance().setErrorState(this, e);
}
@@ -317,7 +323,7 @@ public abstract class NodeInstanceImpl implements
org.jbpm.workflow.instance.Nod
List<Connection> connections = null;
if (node != null) {
- if (Boolean.parseBoolean((String)
getProcessInstance().getProcess().getMetaData().get("jbpm.enable.multi.con"))
&& !((NodeImpl) node).getConstraints().isEmpty()) {
+ if
(WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcessInstance().getProcess()) &&
!((NodeImpl) node).getConstraints().isEmpty()) {
int priority;
connections = ((NodeImpl)
node).getDefaultOutgoingConnections();
boolean found = false;
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
index 48a7276e26..e185f6d019 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
@@ -100,6 +100,7 @@ import org.kie.kogito.process.BaseEventDescription;
import org.kie.kogito.process.EventDescription;
import org.kie.kogito.process.NamedDataType;
import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.ProcessInstanceExecutionException;
import org.kie.kogito.process.flexible.AdHocFragment;
import org.kie.kogito.process.flexible.ItemDescription;
import org.kie.kogito.process.flexible.Milestone;
@@ -1316,6 +1317,15 @@ public abstract class WorkflowProcessInstanceImpl
extends ProcessInstanceImpl im
this.errorCause = Optional.empty();
}
+ public void internalSetError(ProcessInstanceExecutionException e) {
+ this.nodeIdInError = e.getFailedNodeId();
+ Throwable rootException = getRootException(e);
+ this.errorMessage = rootException instanceof MessageException ?
rootException.getMessage() : rootException.getClass().getCanonicalName() + " -
" + rootException.getMessage();
+ this.errorCause = Optional.of(e);
+ setState(STATE_ERROR);
+ ((InternalProcessRuntime)
getKnowledgeRuntime().getProcessRuntime()).getProcessEventSupport().fireOnError(this,
null, getKnowledgeRuntime(), e);
+ }
+
@Override
public Collection<AdHocFragment> adHocFragments() {
return Stream.of(getNodeContainer().getNodes())
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
index 9b17022e46..4749aee86e 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/ForEachNodeInstance.java
@@ -54,6 +54,8 @@ import
org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.mvel2.integration.VariableResolver;
import org.mvel2.integration.impl.SimpleValueResolver;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_MULTIPLE_CONNECTIONS;
+
/**
* Runtime counterpart of a for each node.
*/
@@ -297,7 +299,7 @@ public class ForEachNodeInstance extends
CompositeContextNodeInstance {
((NodeInstanceContainer)
getNodeInstanceContainer()).removeNodeInstance(this);
if (getForEachNode().isWaitForCompletion()) {
- if (!Boolean.parseBoolean((String)
getForEachNode().getProcess().getMetaData().get("jbpm.enable.multi.con"))) {
+ if
(!WORKFLOW_PARAM_MULTIPLE_CONNECTIONS.get(getProcessInstance().getProcess())) {
triggerConnection(getForEachJoinNode().getTo());
} else {
List<Connection> connections =
getForEachJoinNode().getOutgoingConnections(Node.CONNECTION_DEFAULT_TYPE);
diff --git
a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/process/ProcessGenerationIT.java
b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/process/ProcessGenerationIT.java
index 9c84008fc5..7737a67aca 100644
---
a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/process/ProcessGenerationIT.java
+++
b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/process/ProcessGenerationIT.java
@@ -34,6 +34,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -82,6 +83,7 @@ import static org.jbpm.ruleflow.core.Metadata.TRIGGER_REF;
import static org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE;
import static org.jbpm.workflow.core.impl.ExtendedNodeImpl.EVENT_NODE_ENTER;
import static org.jbpm.workflow.core.impl.ExtendedNodeImpl.EVENT_NODE_EXIT;
+import static
org.jbpm.workflow.instance.WorkflowProcessParameters.WORKFLOW_PARAM_TRANSACTIONS;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -108,7 +110,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class ProcessGenerationIT extends AbstractCodegenIT {
private static final Collection<String> IGNORED_PROCESS_META =
- Arrays.asList("Definitions", "BPMN.Connections",
"BPMN.Associations", "ItemDefinitions");
+ Arrays.asList("Definitions", "BPMN.Connections",
"BPMN.Associations", "ItemDefinitions", WORKFLOW_PARAM_TRANSACTIONS.getName());
private static final Path BASE_PATH = Paths.get("src/test/resources");
static Stream<String> processesProvider() throws IOException {
@@ -405,13 +407,15 @@ public class ProcessGenerationIT extends
AbstractCodegenIT {
return;
}
expected.remove("CorrelationSubscriptions");
- assertThat(current).hasSize((int) expected.keySet()
- .stream()
- .filter(k -> ignoredKeys == null || !ignoredKeys.contains(k))
- .count());
+ Predicate<String> precicateIgnoredKeys =
Predicate.not(ignoredKeys::contains);
+
+ List<String> currentKeys =
current.keySet().stream().filter(precicateIgnoredKeys).toList();
+ List<String> expectedKeys =
expected.keySet().stream().filter(precicateIgnoredKeys).toList();
+ assertThat(currentKeys).containsExactlyElementsOf(expectedKeys);
+
expected.keySet()
.stream()
- .filter(k -> ignoredKeys == null || !ignoredKeys.contains(k))
+ .filter(precicateIgnoredKeys)
.forEach(k -> assertThat(current).as("Metadata " +
k).containsEntry(k, expected.get(k)));
}
diff --git
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
index 14bab62579..20c7189198 100644
---
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
+++
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
@@ -48,6 +48,8 @@ import org.jbpm.compiler.xml.XmlProcessReader;
import org.jbpm.compiler.xml.core.SemanticModules;
import org.jbpm.process.core.impl.ProcessImpl;
import org.jbpm.process.core.validation.ProcessValidatorRegistry;
+import org.jbpm.workflow.core.impl.WorkflowProcessImpl;
+import org.jbpm.workflow.instance.WorkflowProcessParameters;
import org.kie.api.definition.process.Process;
import org.kie.api.definition.process.WorkflowProcess;
import org.kie.api.io.Resource;
@@ -57,7 +59,9 @@ import org.kie.kogito.codegen.api.GeneratedInfo;
import org.kie.kogito.codegen.api.SourceFileCodegenBindEvent;
import org.kie.kogito.codegen.api.context.ContextAttributesConstants;
import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+import org.kie.kogito.codegen.api.context.impl.JavaKogitoBuildContext;
import org.kie.kogito.codegen.api.io.CollectedResource;
+import org.kie.kogito.codegen.api.template.TemplatedGenerator;
import org.kie.kogito.codegen.core.AbstractGenerator;
import org.kie.kogito.codegen.core.DashboardGeneratedFileUtils;
import org.kie.kogito.codegen.process.config.ProcessConfigGenerator;
@@ -74,11 +78,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
+import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
import static
org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_PATH;
+import static
org.kie.kogito.codegen.process.util.CodegenUtil.isTransactionEnabled;
import static
org.kie.kogito.grafana.GrafanaConfigurationWriter.buildDashboardName;
import static
org.kie.kogito.grafana.GrafanaConfigurationWriter.generateOperationalDashboard;
import static org.kie.kogito.internal.utils.ConversionUtils.sanitizeClassName;
@@ -297,6 +303,12 @@ public class ProcessCodegen extends AbstractGenerator {
// first we generate all the data classes from variable declarations
for (WorkflowProcess workFlowProcess : processes.values()) {
+ // transaction is disabled by default for SW types
+ boolean defaultTransactionEnabled =
!KogitoWorkflowProcess.SW_TYPE.equals(workFlowProcess.getType());
+ if (isTransactionEnabled(this, context(),
defaultTransactionEnabled)) {
+ ((WorkflowProcessImpl)
workFlowProcess).setMetaData(WorkflowProcessParameters.WORKFLOW_PARAM_TRANSACTIONS.getName(),
"true");
+ }
+
if (!skipModelGeneration(workFlowProcess)) {
ModelClassGenerator mcg = new ModelClassGenerator(context(),
workFlowProcess);
processIdToModelGenerator.put(workFlowProcess.getId(), mcg);
@@ -308,9 +320,10 @@ public class ProcessCodegen extends AbstractGenerator {
processIdToOutputModelGenerator.put(workFlowProcess.getId(),
omcg);
}
}
-
+ boolean isServerless = false;
// then we generate work items task inputs and outputs if any
for (WorkflowProcess workFlowProcess : processes.values()) {
+ isServerless |=
KogitoWorkflowProcess.SW_TYPE.equals(workFlowProcess.getType());
if
(KogitoWorkflowProcess.SW_TYPE.equals(workFlowProcess.getType())) {
continue;
}
@@ -339,6 +352,7 @@ public class ProcessCodegen extends AbstractGenerator {
}
// generate Process, ProcessInstance classes and the REST resource
+
for (ProcessExecutableModelGenerator execModelGen :
processExecutableModelGenerators) {
String classPrefix =
sanitizeClassName(execModelGen.extractedProcessId());
KogitoWorkflowProcess workFlowProcess = execModelGen.process();
@@ -373,7 +387,7 @@ public class ProcessCodegen extends AbstractGenerator {
.withWorkItems(processIdToWorkItemModel.get(workFlowProcess.getId()))
.withSignals(metaData.getSignals())
.withTriggers(metaData.isStartable(),
metaData.isDynamic(), metaData.getTriggers())
-
.withTransaction(CodegenUtil.isTransactionEnabled(this, context()));
+ .withTransaction(isTransactionEnabled(this,
context()));
rgs.add(processResourceGenerator);
}
@@ -451,6 +465,17 @@ public class ProcessCodegen extends AbstractGenerator {
.forEach((key, value) -> storeFile(PRODUCER_TYPE, key,
value));
}
+ if (CodegenUtil.isTransactionEnabled(this, context()) &&
!isServerless) {
+ String template = "ExceptionHandlerTransaction";
+ TemplatedGenerator generator = TemplatedGenerator.builder()
+ .withTemplateBasePath("/class-templates/transaction/")
+ .withFallbackContext(JavaKogitoBuildContext.CONTEXT_NAME)
+ .withTargetTypeName(template)
+ .build(context(), template);
+ CompilationUnit handler = generator.compilationUnitOrThrow();
+ storeFile(MODEL_TYPE, generator.generatedFilePath(),
handler.toString());
+ }
+
if (context().hasRESTForGenerator(this)) {
for (ProcessResourceGenerator resourceGenerator : rgs) {
storeFile(REST_TYPE, resourceGenerator.generatedFilePath(),
diff --git
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
index ecf9737e17..1e33a95861 100644
---
a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
+++
b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/util/CodegenUtil.java
@@ -22,6 +22,7 @@ import java.util.function.Function;
import org.kie.kogito.codegen.api.Generator;
import org.kie.kogito.codegen.api.context.KogitoBuildContext;
+import org.kie.kogito.codegen.api.context.impl.JavaKogitoBuildContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,9 +66,14 @@ public final class CodegenUtil {
* @see CodegenUtil#getProperty
*/
public static boolean isTransactionEnabled(Generator generator,
KogitoBuildContext context) {
- boolean propertyValue = getProperty(generator, context,
TRANSACTION_ENABLED, Boolean::parseBoolean, true);
- LOG.debug("trying to compute property {} for generator {} property
with value {}", TRANSACTION_ENABLED, generator.name(), propertyValue);
- return propertyValue;
+ return isTransactionEnabled(generator, context, true);
+ }
+
+ public static boolean isTransactionEnabled(Generator generator,
KogitoBuildContext context, boolean defaultValue) {
+ boolean propertyValue = getProperty(generator, context,
TRANSACTION_ENABLED, Boolean::parseBoolean, defaultValue);
+ LOG.debug("Compute property {} for generator {} property with value
{}", TRANSACTION_ENABLED, generator.name(), propertyValue);
+ // java implementation does not have transactions
+ return !JavaKogitoBuildContext.CONTEXT_NAME.equals(context.name()) &&
propertyValue;
}
/**
diff --git
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/transaction/ExceptionHandlerTransactionQuarkusTemplate.java
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/transaction/ExceptionHandlerTransactionQuarkusTemplate.java
new file mode 100644
index 0000000000..3230f0d71b
--- /dev/null
+++
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/transaction/ExceptionHandlerTransactionQuarkusTemplate.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.quarkus.workflow.handler;
+
+import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl;
+import org.kie.kogito.Model;
+import org.kie.kogito.handler.ExceptionHandler;
+import org.kie.kogito.process.MutableProcessInstances;
+import org.kie.kogito.process.ProcessInstanceExecutionException;
+import org.kie.kogito.process.Processes;
+import org.kie.kogito.process.impl.AbstractProcessInstance;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.uow.UnitOfWorkManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Instance;
+import jakarta.inject.Inject;
+import jakarta.transaction.Transactional;
+import jakarta.transaction.Transactional.TxType;
+
+@ApplicationScoped
+public class ExceptionHandlerTransaction implements ExceptionHandler {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ExceptionHandlerTransaction.class);
+
+ @Inject
+ UnitOfWorkManager unitOfWorkManager;
+
+ @Inject
+ Instance<Processes> processesContainer;
+
+ @Override
+ @Transactional(value = TxType.REQUIRES_NEW)
+ public void handle(Exception th) {
+ if (processesContainer.isResolvable()) {
+ return;
+ }
+
+ Processes processes = processesContainer.get();
+ if (th instanceof ProcessInstanceExecutionException) {
+ ProcessInstanceExecutionException
processInstanceExecutionException = (ProcessInstanceExecutionException) th;
+ LOG.info("handling exception {} by the handler {}", th,
this.getClass().getName());
+ UnitOfWorkExecutor.executeInUnitOfWork(unitOfWorkManager, () -> {
+ String processInstanceId =
processInstanceExecutionException.getProcessInstanceId();
+
processes.processByProcessInstanceId(processInstanceId).ifPresent(processDefinition
-> {
+
processDefinition.instances().findById(processInstanceId).ifPresent(instance ->
{
+ AbstractProcessInstance<? extends Model>
processInstance = ((AbstractProcessInstance<? extends Model>) instance);
+ ((WorkflowProcessInstanceImpl)
processInstance.internalGetProcessInstance()).internalSetError(processInstanceExecutionException);
+ ((MutableProcessInstances)
processDefinition.instances()).update(processInstanceId, processInstance);
+ });
+
+ });
+
+ return null;
+ });
+ }
+ }
+
+}
diff --git
a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/transaction/ExceptionHandlerTransactionSpringTemplate.java
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/transaction/ExceptionHandlerTransactionSpringTemplate.java
new file mode 100644
index 0000000000..d9996d62f1
--- /dev/null
+++
b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/transaction/ExceptionHandlerTransactionSpringTemplate.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.process.handler;
+
+import org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl;
+import org.kie.kogito.Model;
+import org.kie.kogito.handler.ExceptionHandler;
+import org.kie.kogito.process.MutableProcessInstances;
+import org.kie.kogito.process.ProcessInstanceExecutionException;
+import org.kie.kogito.process.Processes;
+import org.kie.kogito.process.impl.AbstractProcessInstance;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.uow.UnitOfWorkManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class ExceptionHandlerTransaction implements ExceptionHandler {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(ExceptionHandlerTransaction.class);
+
+ @Autowired
+ UnitOfWorkManager unitOfWorkManager;
+
+ @Autowired(required = false)
+ Processes processes;
+
+ @Override
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public void handle(Exception th) {
+ if (processes == null) {
+ return;
+ }
+ if (th instanceof ProcessInstanceExecutionException) {
+ ProcessInstanceExecutionException
processInstanceExecutionException = (ProcessInstanceExecutionException) th;
+ LOG.info("handling exception {} by the handler {}", th,
this.getClass().getName());
+ UnitOfWorkExecutor.executeInUnitOfWork(unitOfWorkManager, () -> {
+ String processInstanceId =
processInstanceExecutionException.getProcessInstanceId();
+
processes.processByProcessInstanceId(processInstanceId).ifPresent(processDefinition
-> {
+
processDefinition.instances().findById(processInstanceId).ifPresent(instance ->
{
+ AbstractProcessInstance<? extends Model>
processInstance = ((AbstractProcessInstance<? extends Model>) instance);
+ ((WorkflowProcessInstanceImpl)
processInstance.internalGetProcessInstance()).internalSetError(processInstanceExecutionException);
+ ((MutableProcessInstances)
processDefinition.instances()).update(processInstanceId, processInstance);
+ });
+
+ });
+
+ return null;
+ });
+ }
+ }
+
+}
diff --git a/quarkus/addons/rest-exception-handler/pom.xml
b/quarkus/addons/rest-exception-handler/pom.xml
index a5419789ab..03f28e9266 100644
--- a/quarkus/addons/rest-exception-handler/pom.xml
+++ b/quarkus/addons/rest-exception-handler/pom.xml
@@ -51,6 +51,10 @@
<artifactId>jakarta.inject-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>jakarta.enterprise</groupId>
+ <artifactId>jakarta.enterprise.cdi-api</artifactId>
+ </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionMapper.java
index 21b70e76d7..09a44058b3 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/BaseExceptionMapper.java
@@ -23,13 +23,6 @@ import jakarta.ws.rs.ext.ExceptionMapper;
public abstract class BaseExceptionMapper<E extends Throwable> implements
ExceptionMapper<E> {
- protected ExceptionsHandler exceptionsHandler;
-
- protected BaseExceptionMapper() {
- this.exceptionsHandler = new ExceptionsHandler();
- }
-
@Override
- @SuppressWarnings("squid:S3038")
public abstract Response toResponse(E e);
}
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandler.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandler.java
index ec1bd6679d..2d1afaf578 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandler.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandler.java
@@ -18,54 +18,60 @@
*/
package org.kie.kogito.resource.exceptions;
+import org.kie.kogito.handler.ExceptionHandler;
+
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
-public class ExceptionsHandler extends BaseExceptionsHandler<Response> {
+public class ExceptionsHandler extends AbstractExceptionsHandler<Response> {
+
+ public ExceptionsHandler(Iterable<ExceptionHandler> handlers) {
+ super(handlers);
+ }
@Override
- protected <R> Response badRequest(R body) {
+ protected Response badRequest(ExceptionBodyMessage body) {
return Response
.status(Response.Status.BAD_REQUEST)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
- .entity(body)
+ .entity(body.getBody())
.build();
}
@Override
- protected <R> Response conflict(R body) {
+ protected Response conflict(ExceptionBodyMessage body) {
return Response
.status(Response.Status.CONFLICT)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
- .entity(body)
+ .entity(body.getBody())
.build();
}
@Override
- protected <R> Response internalError(R body) {
+ protected Response internalError(ExceptionBodyMessage body) {
return Response
.status(Response.Status.INTERNAL_SERVER_ERROR)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
- .entity(body)
+ .entity(body.getBody())
.build();
}
@Override
- protected <R> Response notFound(R body) {
+ protected Response notFound(ExceptionBodyMessage body) {
return Response
.status(Response.Status.NOT_FOUND)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
- .entity(body)
+ .entity(body.getBody())
.build();
}
@Override
- protected <R> Response forbidden(R body) {
+ protected Response forbidden(ExceptionBodyMessage body) {
return Response
.status(Response.Status.FORBIDDEN)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
- .entity(body)
+ .entity(body.getBody())
.build();
}
}
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerProducer.java
similarity index 72%
copy from
quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
copy to
quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerProducer.java
index 56a734a511..a207c68072 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerProducer.java
@@ -18,14 +18,15 @@
*/
package org.kie.kogito.resource.exceptions;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.ext.Provider;
+import org.kie.kogito.handler.ExceptionHandler;
-@Provider
-public class IllegalArgumentExceptionMapper extends
BaseExceptionMapper<IllegalArgumentException> {
+import jakarta.enterprise.inject.Instance;
+import jakarta.enterprise.inject.Produces;
- @Override
- public Response toResponse(IllegalArgumentException e) {
- return exceptionsHandler.mapException(e);
+public class ExceptionsHandlerProducer {
+
+ @Produces
+ public ExceptionsHandler newExceptionsHandler(Instance<ExceptionHandler>
handlers) {
+ return new ExceptionsHandler(handlers);
}
}
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
index 56a734a511..e019fd12f9 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/IllegalArgumentExceptionMapper.java
@@ -18,12 +18,16 @@
*/
package org.kie.kogito.resource.exceptions;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class IllegalArgumentExceptionMapper extends
BaseExceptionMapper<IllegalArgumentException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(IllegalArgumentException e) {
return exceptionsHandler.mapException(e);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidLifeCyclePhaseExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidLifeCyclePhaseExceptionMapper.java
index 82341b6eec..7d5b5a938a 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidLifeCyclePhaseExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidLifeCyclePhaseExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.internal.process.workitem.InvalidLifeCyclePhaseException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class InvalidLifeCyclePhaseExceptionMapper extends
BaseExceptionMapper<InvalidLifeCyclePhaseException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(InvalidLifeCyclePhaseException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidTransitionExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidTransitionExceptionMapper.java
index ff04b15e15..abd80e367d 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidTransitionExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/InvalidTransitionExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.internal.process.workitem.InvalidTransitionException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class InvalidTransitionExceptionMapper extends
BaseExceptionMapper<InvalidTransitionException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(InvalidTransitionException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeInstanceNotFoundExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeInstanceNotFoundExceptionMapper.java
index 698a1155e7..891c60fb7c 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeInstanceNotFoundExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeInstanceNotFoundExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.process.NodeInstanceNotFoundException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class NodeInstanceNotFoundExceptionMapper extends
BaseExceptionMapper<NodeInstanceNotFoundException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(NodeInstanceNotFoundException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeNotFoundExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeNotFoundExceptionMapper.java
index 182e1df839..c41b0397fe 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeNotFoundExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NodeNotFoundExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.process.NodeNotFoundException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class NodeNotFoundExceptionMapper extends
BaseExceptionMapper<NodeNotFoundException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(NodeNotFoundException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NotAuthorizedExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NotAuthorizedExceptionMapper.java
index 030783daa6..2831677feb 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NotAuthorizedExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/NotAuthorizedExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class NotAuthorizedExceptionMapper extends
BaseExceptionMapper<NotAuthorizedException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(NotAuthorizedException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceDuplicatedExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceDuplicatedExceptionMapper.java
index ed9bb35c96..6c54bf486e 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceDuplicatedExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceDuplicatedExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.process.ProcessInstanceDuplicatedException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class ProcessInstanceDuplicatedExceptionMapper extends
BaseExceptionMapper<ProcessInstanceDuplicatedException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(ProcessInstanceDuplicatedException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceExecutionExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceExecutionExceptionMapper.java
index 9e3f41ef95..3ff0d6449c 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceExecutionExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceExecutionExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.process.ProcessInstanceExecutionException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class ProcessInstanceExecutionExceptionMapper extends
BaseExceptionMapper<ProcessInstanceExecutionException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(ProcessInstanceExecutionException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceNotFoundExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceNotFoundExceptionMapper.java
index 46b511d6b3..d0e31c3fc5 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceNotFoundExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/ProcessInstanceNotFoundExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.process.ProcessInstanceNotFoundException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class ProcessInstanceNotFoundExceptionMapper extends
BaseExceptionMapper<ProcessInstanceNotFoundException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(ProcessInstanceNotFoundException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotAuthorizedExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotAuthorizedExceptionMapper.java
index 9871032881..be350a1d6d 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotAuthorizedExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotAuthorizedExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.usertask.UserTaskInstanceNotFoundException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class UserTaskInstanceNotAuthorizedExceptionMapper extends
BaseExceptionMapper<UserTaskInstanceNotFoundException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(UserTaskInstanceNotFoundException e) {
return exceptionsHandler.mapException(e);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotFoundExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotFoundExceptionMapper.java
index d74ddf1fc5..196bd85535 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotFoundExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskInstanceNotFoundExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.usertask.UserTaskInstanceNotAuthorizedException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class UserTaskInstanceNotFoundExceptionMapper extends
BaseExceptionMapper<UserTaskInstanceNotAuthorizedException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(UserTaskInstanceNotAuthorizedException e) {
return exceptionsHandler.mapException(e);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskTransitionExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskTransitionExceptionMapper.java
index 233d3cd679..063439ead6 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskTransitionExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/UserTaskTransitionExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.usertask.UserTaskInstanceNotFoundException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class UserTaskTransitionExceptionMapper extends
BaseExceptionMapper<UserTaskInstanceNotFoundException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(UserTaskInstanceNotFoundException e) {
return exceptionsHandler.mapException(e);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/VariableViolationExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/VariableViolationExceptionMapper.java
index 85ab766ee4..fdea325335 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/VariableViolationExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/VariableViolationExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.process.VariableViolationException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class VariableViolationExceptionMapper extends
BaseExceptionMapper<VariableViolationException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(VariableViolationException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java
index 1ffb619ceb..bcd9f18ede 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemExecutionExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.internal.process.workitem.WorkItemExecutionException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class WorkItemExecutionExceptionMapper extends
BaseExceptionMapper<WorkItemExecutionException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(WorkItemExecutionException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemNotFoundExceptionMapper.java
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemNotFoundExceptionMapper.java
index a0d0731dcc..000e0f748a 100644
---
a/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemNotFoundExceptionMapper.java
+++
b/quarkus/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/WorkItemNotFoundExceptionMapper.java
@@ -20,12 +20,16 @@ package org.kie.kogito.resource.exceptions;
import org.kie.kogito.internal.process.workitem.WorkItemNotFoundException;
+import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.Provider;
@Provider
public class WorkItemNotFoundExceptionMapper extends
BaseExceptionMapper<WorkItemNotFoundException> {
+ @Inject
+ ExceptionsHandler exceptionsHandler;
+
@Override
public Response toResponse(WorkItemNotFoundException exception) {
return exceptionsHandler.mapException(exception);
diff --git
a/quarkus/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerTest.java
b/quarkus/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerTest.java
index 028a91a91b..156d8aae68 100644
---
a/quarkus/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerTest.java
+++
b/quarkus/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/ExceptionsHandlerTest.java
@@ -18,6 +18,8 @@
*/
package org.kie.kogito.resource.exceptions;
+import java.util.ArrayList;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -40,7 +42,7 @@ class ExceptionsHandlerTest {
private ExceptionsHandler tested;
@Mock
- private Object body;
+ private ExceptionBodyMessage body;
@Mock
private RuntimeDelegate runtimeDelegate;
@@ -53,7 +55,7 @@ class ExceptionsHandlerTest {
@BeforeEach
void setUp() {
- tested = new ExceptionsHandler();
+ tested = new ExceptionsHandler(new ArrayList<>());
RuntimeDelegate.setInstance(runtimeDelegate);
when(runtimeDelegate.createResponseBuilder()).thenReturn(builder);
when(builder.status(any(Response.StatusType.class))).thenReturn(builder);
@@ -71,7 +73,7 @@ class ExceptionsHandlerTest {
private void assertRequest(Response.Status status) {
verify(builder).header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_JSON);
verify(builder).status((Response.StatusType) status);
- verify(builder).entity(body);
+ verify(builder).entity(body.getBody());
}
@Test
diff --git
a/quarkus/addons/source-files/runtime/src/main/java/org/kie/kogito/addon/source/files/SourceFilesResource.java
b/quarkus/addons/source-files/runtime/src/main/java/org/kie/kogito/addon/source/files/SourceFilesResource.java
index 6165d773ab..29ca134938 100644
---
a/quarkus/addons/source-files/runtime/src/main/java/org/kie/kogito/addon/source/files/SourceFilesResource.java
+++
b/quarkus/addons/source-files/runtime/src/main/java/org/kie/kogito/addon/source/files/SourceFilesResource.java
@@ -19,11 +19,10 @@
package org.kie.kogito.addon.source.files;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
+import java.util.Optional;
-import org.kie.kogito.resource.exceptions.ExceptionsHandler;
import org.kie.kogito.source.files.SourceFile;
import org.kie.kogito.source.files.SourceFilesProvider;
@@ -41,24 +40,24 @@ import jakarta.ws.rs.core.Response;
@Path("/management/processes/")
public final class SourceFilesResource {
- private static final ExceptionsHandler EXCEPTIONS_HANDLER = new
ExceptionsHandler();
-
SourceFilesProvider sourceFilesProvider;
@GET
@Path("sources")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
- public Response getSourceFileByUri(@QueryParam("uri") String uri) {
- return sourceFilesProvider.getSourceFilesByUri(uri)
- .map(sourceFile -> {
- try (InputStream file = new
ByteArrayInputStream(sourceFile.readContents())) {
- return Response.ok(file,
MediaType.APPLICATION_OCTET_STREAM)
- .header("Content-Disposition", "inline;
filename=\"" + java.nio.file.Path.of(sourceFile.getUri()).getFileName() + "\"")
- .build();
- } catch (Exception e) {
- return EXCEPTIONS_HANDLER.mapException(e);
- }
- }).orElseGet(() ->
Response.status(Response.Status.NOT_FOUND).build());
+ public Response getSourceFileByUri(@QueryParam("uri") String uri) throws
Exception {
+ Optional<SourceFile> sourceFile =
sourceFilesProvider.getSourceFilesByUri(uri);
+
+ if (sourceFile.isEmpty()) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ try (InputStream file = new
ByteArrayInputStream(sourceFile.get().readContents())) {
+ return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
+ .header("Content-Disposition", "inline; filename=\"" +
java.nio.file.Path.of(sourceFile.get().getUri()).getFileName() + "\"")
+ .build();
+ }
+
}
@GET
@@ -71,15 +70,15 @@ public final class SourceFilesResource {
@GET
@Path("{processId}/source")
@Produces(MediaType.TEXT_PLAIN)
- public Response getSourceFileByProcessId(@PathParam("processId") String
processId) {
- return sourceFilesProvider.getProcessSourceFile(processId)
- .map(sourceFile -> {
- try {
- return Response.ok(sourceFile.readContents()).build();
- } catch (IOException e) {
- return EXCEPTIONS_HANDLER.mapException(e);
- }
- }).orElseGet(() ->
Response.status(Response.Status.NOT_FOUND).build());
+ public Response getSourceFileByProcessId(@PathParam("processId") String
processId) throws Exception {
+ Optional<SourceFile> sourceFile =
sourceFilesProvider.getProcessSourceFile(processId);
+
+ if (sourceFile.isEmpty()) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+
+ return Response.ok(sourceFile.get().readContents()).build();
+
}
@Inject
diff --git
a/quarkus/addons/source-files/runtime/src/test/java/org/kie/kogito/addon/source/files/SourceFilesResourceTest.java
b/quarkus/addons/source-files/runtime/src/test/java/org/kie/kogito/addon/source/files/SourceFilesResourceTest.java
index 642bf95be8..2968fe78d6 100644
---
a/quarkus/addons/source-files/runtime/src/test/java/org/kie/kogito/addon/source/files/SourceFilesResourceTest.java
+++
b/quarkus/addons/source-files/runtime/src/test/java/org/kie/kogito/addon/source/files/SourceFilesResourceTest.java
@@ -58,14 +58,14 @@ class SourceFilesResourceTest {
}
@Test
- void getEmptySourceFileByProcessIdTest() {
+ void getEmptySourceFileByProcessIdTest() throws Exception {
when(mockSourceFileProvider.getProcessSourceFile(PROCESS_ID)).thenReturn(Optional.empty());
assertThat(sourceFilesTestResource.getSourceFileByProcessId(PROCESS_ID).getStatus()).isEqualTo(Response.Status.NOT_FOUND.getStatusCode());
verify(mockSourceFileProvider).getProcessSourceFile(PROCESS_ID);
}
@Test
- void getValidSourceFileByProcessIdTest() {
+ void getValidSourceFileByProcessIdTest() throws Exception {
when(mockSourceFileProvider.getProcessSourceFile(PROCESS_ID)).thenReturn(Optional.of(new
SourceFile("petstore.sw.json")));
assertThat(sourceFilesTestResource.getSourceFileByProcessId(PROCESS_ID).getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
verify(mockSourceFileProvider).getProcessSourceFile(PROCESS_ID);
diff --git
a/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java
b/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java
index d5d5dfa96e..9872513141 100644
---
a/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java
+++
b/springboot/addons/rest-exception-handler/src/main/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandler.java
@@ -18,6 +18,9 @@
*/
package org.kie.kogito.resource.exceptions.springboot;
+import java.util.List;
+import java.util.Map;
+
import org.kie.kogito.internal.process.workitem.InvalidLifeCyclePhaseException;
import org.kie.kogito.internal.process.workitem.InvalidTransitionException;
import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
@@ -29,7 +32,9 @@ import
org.kie.kogito.process.ProcessInstanceDuplicatedException;
import org.kie.kogito.process.ProcessInstanceExecutionException;
import org.kie.kogito.process.ProcessInstanceNotFoundException;
import org.kie.kogito.process.VariableViolationException;
-import org.kie.kogito.resource.exceptions.BaseExceptionsHandler;
+import org.kie.kogito.resource.exceptions.AbstractExceptionsHandler;
+import org.kie.kogito.resource.exceptions.ExceptionBodyMessage;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -37,105 +42,111 @@ import
org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
-public class ExceptionsHandler extends BaseExceptionsHandler<ResponseEntity> {
+public class ExceptionsHandler extends
AbstractExceptionsHandler<ResponseEntity<Map<String, String>>> {
+
+ @Autowired
+ public ExceptionsHandler(List<org.kie.kogito.handler.ExceptionHandler>
handlers) {
+ super(handlers);
+ }
@Override
- protected <R> ResponseEntity badRequest(R body) {
+ protected ResponseEntity<Map<String, String>>
badRequest(ExceptionBodyMessage body) {
return ResponseEntity
.badRequest()
.contentType(MediaType.APPLICATION_JSON)
- .body(body);
+ .body(body.getBody());
}
@Override
- protected <R> ResponseEntity conflict(R body) {
+ protected ResponseEntity<Map<String, String>>
conflict(ExceptionBodyMessage body) {
return ResponseEntity
.status(HttpStatus.CONFLICT)
.contentType(MediaType.APPLICATION_JSON)
- .body(body);
+ .body(body.getBody());
}
@Override
- protected <R> ResponseEntity internalError(R body) {
+ protected ResponseEntity<Map<String, String>>
internalError(ExceptionBodyMessage body) {
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON)
- .body(body);
+ .body(body.getBody());
}
@Override
- protected <R> ResponseEntity notFound(R body) {
+ protected ResponseEntity<Map<String, String>>
notFound(ExceptionBodyMessage body) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.contentType(MediaType.APPLICATION_JSON)
- .body(body);
+ .body(body.getBody());
}
@Override
- protected <R> ResponseEntity forbidden(R body) {
+ protected ResponseEntity<Map<String, String>>
forbidden(ExceptionBodyMessage body) {
return ResponseEntity
.status(HttpStatus.FORBIDDEN)
.contentType(MediaType.APPLICATION_JSON)
- .body(body);
+ .body(body.getBody());
}
@ExceptionHandler(InvalidLifeCyclePhaseException.class)
- public ResponseEntity toResponse(InvalidLifeCyclePhaseException exception)
{
+ public ResponseEntity<Map<String, String>>
toResponse(InvalidLifeCyclePhaseException exception) {
return mapException(exception);
}
@ExceptionHandler(InvalidTransitionException.class)
- public ResponseEntity toResponse(InvalidTransitionException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(InvalidTransitionException exception) {
return mapException(exception);
}
@ExceptionHandler(NodeInstanceNotFoundException.class)
- public ResponseEntity toResponse(NodeInstanceNotFoundException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(NodeInstanceNotFoundException exception) {
return mapException(exception);
}
@ExceptionHandler(NodeNotFoundException.class)
- public ResponseEntity toResponse(NodeNotFoundException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(NodeNotFoundException exception) {
return mapException(exception);
}
@ExceptionHandler(NotAuthorizedException.class)
- public ResponseEntity toResponse(NotAuthorizedException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(NotAuthorizedException exception) {
return mapException(exception);
}
@ExceptionHandler(ProcessInstanceDuplicatedException.class)
- public ResponseEntity<Object>
toResponse(ProcessInstanceDuplicatedException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(ProcessInstanceDuplicatedException exception) {
return mapException(exception);
}
@ExceptionHandler(ProcessInstanceExecutionException.class)
- public ResponseEntity toResponse(ProcessInstanceExecutionException
exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(ProcessInstanceExecutionException exception) {
return mapException(exception);
}
@ExceptionHandler(ProcessInstanceNotFoundException.class)
- public ResponseEntity toResponse(ProcessInstanceNotFoundException
exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(ProcessInstanceNotFoundException exception) {
return mapException(exception);
}
@ExceptionHandler(WorkItemNotFoundException.class)
- public ResponseEntity toResponse(WorkItemNotFoundException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(WorkItemNotFoundException exception) {
return mapException(exception);
}
@ExceptionHandler(WorkItemExecutionException.class)
- public ResponseEntity toResponse(WorkItemExecutionException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(WorkItemExecutionException exception) {
return mapException(exception);
}
@ExceptionHandler(VariableViolationException.class)
- public ResponseEntity toResponse(VariableViolationException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(VariableViolationException exception) {
return mapException(exception);
}
@ExceptionHandler(IllegalArgumentException.class)
- public ResponseEntity toResponse(IllegalArgumentException exception) {
+ public ResponseEntity<Map<String, String>>
toResponse(IllegalArgumentException exception) {
return mapException(exception);
}
+
}
diff --git
a/springboot/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandlerTest.java
b/springboot/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandlerTest.java
index 4512a30b7f..10c8290620 100644
---
a/springboot/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandlerTest.java
+++
b/springboot/addons/rest-exception-handler/src/test/java/org/kie/kogito/resource/exceptions/springboot/ExceptionsHandlerTest.java
@@ -18,6 +18,9 @@
*/
package org.kie.kogito.resource.exceptions.springboot;
+import java.util.ArrayList;
+import java.util.Map;
+
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -29,6 +32,7 @@ import
org.kie.kogito.process.ProcessInstanceDuplicatedException;
import org.kie.kogito.process.ProcessInstanceExecutionException;
import org.kie.kogito.process.ProcessInstanceNotFoundException;
import org.kie.kogito.process.VariableViolationException;
+import org.kie.kogito.resource.exceptions.ExceptionBodyMessage;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
@@ -44,45 +48,45 @@ class ExceptionsHandlerTest {
private ExceptionsHandler tested;
@Mock
- private Object body;
+ private ExceptionBodyMessage body;
@BeforeEach
void setUp() {
- tested = spy(new ExceptionsHandler());
+ tested = spy(new ExceptionsHandler(new ArrayList<>()));
}
@Test
void testBadRequest() {
- ResponseEntity responseEntity = tested.badRequest(body);
+ ResponseEntity<Map<String, String>> responseEntity =
tested.badRequest(body);
assertResponse(responseEntity, HttpStatus.BAD_REQUEST);
}
- private void assertResponse(ResponseEntity responseEntity, HttpStatus
status) {
+ private void assertResponse(ResponseEntity<Map<String, String>>
responseEntity, HttpStatus status) {
assertThat(responseEntity.getStatusCode()).isEqualTo(status);
- assertThat(responseEntity.getBody()).isEqualTo(body);
+ assertThat(responseEntity.getBody()).isEqualTo(body.getBody());
}
@Test
void testConflict() {
- ResponseEntity responseEntity = tested.conflict(body);
+ ResponseEntity<Map<String, String>> responseEntity =
tested.conflict(body);
assertResponse(responseEntity, HttpStatus.CONFLICT);
}
@Test
void testIternalError() {
- ResponseEntity responseEntity = tested.internalError(body);
+ ResponseEntity<Map<String, String>> responseEntity =
tested.internalError(body);
assertResponse(responseEntity, HttpStatus.INTERNAL_SERVER_ERROR);
}
@Test
void testNotFound() {
- ResponseEntity responseEntity = tested.badRequest(body);
+ ResponseEntity<Map<String, String>> responseEntity =
tested.badRequest(body);
assertResponse(responseEntity, HttpStatus.BAD_REQUEST);
}
@Test
void testForbidden() {
- ResponseEntity responseEntity = tested.forbidden(body);
+ ResponseEntity<Map<String, String>> responseEntity =
tested.forbidden(body);
assertResponse(responseEntity, HttpStatus.FORBIDDEN);
}
diff --git
a/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/KogitoBeanProducer.java
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/KogitoBeanProducer.java
index b823c16d26..d1875057a9 100644
---
a/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/KogitoBeanProducer.java
+++
b/springboot/starters/kogito-processes-spring-boot-starter/src/main/java/org/kie/kogito/process/KogitoBeanProducer.java
@@ -22,6 +22,9 @@ import org.kie.kogito.config.ConfigBean;
import org.kie.kogito.correlation.CorrelationService;
import org.kie.kogito.event.correlation.DefaultCorrelationService;
import org.kie.kogito.process.version.ProjectVersionProcessVersionResolver;
+import org.kie.kogito.services.uow.CollectingUnitOfWorkFactory;
+import org.kie.kogito.services.uow.DefaultUnitOfWorkManager;
+import org.kie.kogito.uow.UnitOfWorkManager;
import org.kogito.workitem.rest.RestWorkItemHandlerUtils;
import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -53,6 +56,12 @@ public class KogitoBeanProducer {
return new
ProjectVersionProcessVersionResolver(configBean.getGav().orElseThrow(() -> new
RuntimeException("Unable to use kogito.workflow.version-strategy without a
project GAV")));
}
+ @Bean
+ @ConditionalOnMissingBean(UnitOfWorkManager.class)
+ UnitOfWorkManager unitOfWorkManager() {
+ return new DefaultUnitOfWorkManager(new CollectingUnitOfWorkFactory());
+ }
+
@Bean
@ConditionalOnMissingBean(WebClientOptions.class)
WebClientOptions sslDefaultOptions() {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]