Skip to content

Commit

Permalink
Merge pull request #102 from folio-org/sprint5-staging
Browse files Browse the repository at this point in the history
Sprint5 staging
  • Loading branch information
kaladay authored May 30, 2024
2 parents 59d4793 + e85de40 commit e58e4c8
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 18 deletions.
38 changes: 37 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,37 @@
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>23.0.3</version>
<version>23.0.4</version>
</dependency>

<dependency>
<groupId>org.graalvm.python</groupId>
<artifactId>python-language</artifactId>
<version>23.1.3</version>
</dependency>

<dependency>
<groupId>org.graalvm.python</groupId>
<artifactId>python-resources</artifactId>
<version>23.1.3</version>
</dependency>

<dependency>
<groupId>org.graalvm.ruby</groupId>
<artifactId>ruby-language</artifactId>
<version>23.1.3</version>
</dependency>

<dependency>
<groupId>org.graalvm.ruby</groupId>
<artifactId>ruby-resources</artifactId>
<version>23.1.3</version>
</dependency>

<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>9.4.7.0</version>
</dependency>

<dependency>
Expand All @@ -254,6 +284,12 @@
<version>23.1.2</version>
</dependency>

<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>23.1.3</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.folio.rest.camunda.controller;

import lombok.extern.slf4j.Slf4j;
import org.folio.rest.camunda.exception.ScriptTaskDeserializeCodeFailure;
import org.folio.rest.camunda.exception.WorkflowAlreadyActiveException;
import org.folio.rest.camunda.service.CamundaApiService;
import org.folio.rest.workflow.model.Workflow;
Expand All @@ -26,7 +27,7 @@ public WorkflowController(CamundaApiService camundaApiService) {

@PostMapping(value = {"/activate", "/activate/"}, produces = { MediaType.APPLICATION_JSON_VALUE })
public Workflow activateWorkflow(@RequestBody Workflow workflow, @TenantHeader String tenant)
throws WorkflowAlreadyActiveException {
throws WorkflowAlreadyActiveException, ScriptTaskDeserializeCodeFailure {
log.debug("Activating Workflow: {}", workflow == null ? null : workflow.getId());
return camundaApiService.deployWorkflow(workflow, tenant);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.folio.rest.camunda.exception;

public class ScriptTaskDeserializeCodeFailure extends Exception {

private static final long serialVersionUID = -6270663785866339965L;

private static final String MESSAGE = "Failed to De-serialize code for ScriptTask %s.";

public ScriptTaskDeserializeCodeFailure(String scriptTaskUuid) {
super(String.format(MESSAGE, scriptTaskUuid));
}

public ScriptTaskDeserializeCodeFailure(String scriptTaskUuid, Exception e) {
super(String.format(MESSAGE, scriptTaskUuid), e);
}

}
28 changes: 20 additions & 8 deletions src/main/java/org/folio/rest/camunda/service/BpmnModelFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.camunda.bpm.model.bpmn.instance.camunda.CamundaField;
import org.camunda.bpm.model.xml.instance.ModelElementInstance;
import org.folio.rest.camunda.delegate.AbstractWorkflowDelegate;
import org.folio.rest.camunda.exception.ScriptTaskDeserializeCodeFailure;
import org.folio.rest.workflow.enums.StartEventType;
import org.folio.rest.workflow.model.Condition;
import org.folio.rest.workflow.model.ConnectTo;
Expand Down Expand Up @@ -77,7 +78,7 @@ public class BpmnModelFactory {
@Autowired
private List<AbstractWorkflowDelegate> workflowDelegates;

public BpmnModelInstance fromWorkflow(Workflow workflow) {
public BpmnModelInstance fromWorkflow(Workflow workflow) throws ScriptTaskDeserializeCodeFailure {

// @formatter:off
ProcessBuilder processBuilder = Bpmn.createExecutableProcess().name(workflow.getName())
Expand All @@ -90,15 +91,21 @@ public BpmnModelInstance fromWorkflow(Workflow workflow) {
// @formatter:off
workflow.getNodes().stream()
.filter(node -> node instanceof EventSubprocess)
.forEach(subprocess -> eventSubprocess(processBuilder, subprocess));
.forEach(subprocess -> {
try {
eventSubprocess(processBuilder, subprocess);
} catch (ScriptTaskDeserializeCodeFailure e) {
throw new RuntimeException(e);
}
});
// @formatter:on

setup(model, workflow);
expressions(model, workflow.getNodes());
return model;
}

private BpmnModelInstance build(ProcessBuilder processBuilder, Workflow workflow) {
private BpmnModelInstance build(ProcessBuilder processBuilder, Workflow workflow) throws ScriptTaskDeserializeCodeFailure {
List<Node> nodes = workflow.getNodes();

if (nodes.isEmpty()) {
Expand All @@ -117,15 +124,15 @@ private BpmnModelInstance build(ProcessBuilder processBuilder, Workflow workflow
return builder.done();
}

private void eventSubprocess(ProcessBuilder processBuilder, Node node) {
private void eventSubprocess(ProcessBuilder processBuilder, Node node) throws ScriptTaskDeserializeCodeFailure {
AbstractFlowNodeBuilder<?, ?> builder = null;
String identifier = node.getIdentifier();
String name = node.getName();
builder = processBuilder.eventSubProcess(identifier).name(name).startEvent();
builder = build(builder, ((EventSubprocess) node).getNodes(), Setup.NONE);
}

private AbstractFlowNodeBuilder<?, ?> build(AbstractFlowNodeBuilder<?, ?> builder, List<Node> nodes, Setup setup) {
private AbstractFlowNodeBuilder<?, ?> build(AbstractFlowNodeBuilder<?, ?> builder, List<Node> nodes, Setup setup) throws ScriptTaskDeserializeCodeFailure {

for (Node node : nodes) {

Expand Down Expand Up @@ -314,7 +321,6 @@ private void eventSubprocess(ProcessBuilder processBuilder, Node node) {
} else {
logger.warn("Navigation named {} is of an unknown type.", node.getName());
}

} else if (node instanceof Task) {
if (node instanceof Wait) {
if (node instanceof ReceiveTask) {
Expand All @@ -324,13 +330,19 @@ private void eventSubprocess(ProcessBuilder processBuilder, Node node) {
logger.warn("Wait Task named {} is of an unknown type.", node.getName());
}
} else if (node instanceof ScriptTask) {
String code;
try {
code = objectMapper.readValue(((ScriptTask) node).getCode(), String.class);
} catch (JsonProcessingException e) {
throw new ScriptTaskDeserializeCodeFailure(node.getId(), e);
}

builder = builder.scriptTask(node.getIdentifier()).name(node.getName())
.scriptFormat(((ScriptTask) node).getScriptFormat()).scriptText(((ScriptTask) node).getCode());
.scriptFormat(((ScriptTask) node).getScriptFormat()).scriptText(code);

if (((ScriptTask) node).hasResultVariable()) {
builder = ((ScriptTaskBuilder) builder).camundaResultVariable(((ScriptTask) node).getResultVariable());
}

} else {
logger.warn("Script Task named {} is of an unknown type.", node.getName());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.folio.rest.camunda.exception.ScriptTaskDeserializeCodeFailure;
import org.folio.rest.camunda.exception.WorkflowAlreadyActiveException;
import org.folio.rest.workflow.model.Workflow;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -17,7 +18,7 @@ public class CamundaApiService {
@Autowired
private BpmnModelFactory bpmnModelFactory;

public Workflow deployWorkflow(Workflow workflow, String tenant) throws WorkflowAlreadyActiveException {
public Workflow deployWorkflow(Workflow workflow, String tenant) throws WorkflowAlreadyActiveException, ScriptTaskDeserializeCodeFailure {
if (workflow.isActive()) {
throw new WorkflowAlreadyActiveException(workflow.getId());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.folio.rest.camunda.utility;

import org.graalvm.shadowed.org.json.JSONObject;

/**
* Provide utility functions specifically needed for scripting engines.
*/
public class ScriptEngineUtility {

/**
* Decode a JSON string into a JSONObject.
*
* This is required by several of the scripting engines, such as engine.py.
*
* @param json
* The JSON string to decode.
*
* @return
* A generated JSON object, containing the decoded JSON string.
*/
public JSONObject decodeJson(String json) {
return new JSONObject(json);
}

/**
* Encode a JSONObject into a JSON string.
*
* @param json
* The JSONObject to encode.
*
* @return
* A String containing the encoded JSON data.
*/
public String encodeJson(JSONObject json) {
return json.toString(2);
}
}
2 changes: 1 addition & 1 deletion src/main/resources/scripts/engine.groovy
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import org.folio.rest.utility.ScriptEngineUtility
import org.folio.rest.camunda.utility.ScriptEngineUtility

def %s(String inArgs) {
def scriptEngineUtility = new ScriptEngineUtility();
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/scripts/engine.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import org.camunda.bpm.engine.impl.util.json.JSONObject;
import org.folio.rest.utility.ScriptEngineUtility;
import org.graalvm.shadowed.org.json.JSONObject;
import org.folio.rest.camunda.utility.ScriptEngineUtility;

public String %s(String inArgs) {
ScriptEngineUtility scriptEngineUtility = new ScriptEngineUtility();
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/scripts/engine.pl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use JSON;
use org.folio.rest.utility.ScriptEngineUtility;
use org.folio.rest.camunda.utility.ScriptEngineUtility;

sub %s($) {
my ($inArgs) = @_;
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/scripts/engine.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import json
import org.folio.rest.utility.ScriptEngineUtility;
import org.folio.rest.camunda.utility.ScriptEngineUtility;

def %s(inArgs):
scriptEngineUtility = org.folio.rest.utility.ScriptEngineUtility();
scriptEngineUtility = org.folio.rest.camunda.utility.ScriptEngineUtility();
args = scriptEngineUtility.decodeJson(inArgs);
returnObj = scriptEngineUtility.createJson();
%s
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/scripts/engine.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require 'json'
require 'use org.folio.rest.utility.ScriptEngineUtility'
require 'use org.folio.rest.camunda.utility.ScriptEngineUtility'

def %s(inArgs)
scriptEngineUtility = ScriptEngineUtility();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.folio.rest.camunda.exception;

import static org.folio.spring.test.mock.MockMvcConstant.UUID;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ScriptTaskDeserializeCodeFailureTest {

@Test
void scriptEngineLoadFailedWorksTest() throws IOException {
ScriptTaskDeserializeCodeFailure exception = Assertions.assertThrows(ScriptTaskDeserializeCodeFailure.class, () -> {
throw new ScriptTaskDeserializeCodeFailure(UUID);
});

assertNotNull(exception);
assertTrue(exception.getMessage().contains(UUID));
}

@Test
void scriptEngineLoadFailedWorksWithParameterTest() throws IOException {
ScriptTaskDeserializeCodeFailure exception = Assertions.assertThrows(ScriptTaskDeserializeCodeFailure.class, () -> {
throw new ScriptTaskDeserializeCodeFailure(UUID, new RuntimeException());
});

assertNotNull(exception);
assertTrue(exception.getMessage().contains(UUID));
}
}

0 comments on commit e58e4c8

Please sign in to comment.