From 6092c8462bbc0234b7bb69ccd289a4f2df62b4e2 Mon Sep 17 00:00:00 2001 From: Jonas Blatt <jonasblatt@uni-koblenz.de> Date: Mon, 21 Oct 2019 23:14:38 +0200 Subject: [PATCH] Add camunda engine synchronisation of dmn definitions for continuous integration --- dmnverifierapi/pom.xml | 4 - .../verifier/impl/SubsumptionVerifier.java | 4 +- .../fgbks/dmn/frontend/DmnBean.java | 13 ++ .../fgbks/dmn/frontend/DmnSessionApi.java | 14 +- .../resources/css/img/camundaConnect.png | Bin 0 -> 17622 bytes .../META-INF/resources/css/stylesheets.css | 37 +++- .../META-INF/resources/dmn/emptyDMN.dmn | 4 +- .../resources/META-INF/resources/index.html | 22 +- .../META-INF/resources/js/dmnCamundaApi.js | 198 ++++++++++++++++++ .../META-INF/resources/js/dmnUpDownload.js | 29 ++- dmnverifierparent/pom.xml | 4 + 11 files changed, 302 insertions(+), 27 deletions(-) create mode 100644 dmnverifierfrontend/src/main/resources/META-INF/resources/css/img/camundaConnect.png create mode 100644 dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnCamundaApi.js diff --git a/dmnverifierapi/pom.xml b/dmnverifierapi/pom.xml index d7ed68a7..c6cfe0d6 100644 --- a/dmnverifierapi/pom.xml +++ b/dmnverifierapi/pom.xml @@ -42,10 +42,6 @@ <version>${version.camunda}</version> </dependency> <!-- Quarkus --> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-resteasy-jsonb</artifactId> - </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/SubsumptionVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/SubsumptionVerifier.java index fe62a425..e3606793 100644 --- a/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/SubsumptionVerifier.java +++ b/dmnverifierapi/src/main/java/de/unikoblenz/fgbks/core/dmn/verification/verifier/impl/SubsumptionVerifier.java @@ -60,9 +60,7 @@ public class SubsumptionVerifier extends AbstractVerifier { vreFactory.addVerificationFix(SHOW_RULES); vreFactory.addToEntry( VerificationClassification.WARNING, - templateDecision(inColumns.get(0).getDmnDecision()) - + getMessageText( - currentRules, currentRootSubsumptionElements, differentConclusions)); + getMessageText(currentRules, currentRootSubsumptionElements, differentConclusions)); } } else { // get all input values from the current column, and filter with the prev. iteration diff --git a/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnBean.java b/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnBean.java index beb00ab8..58f01578 100644 --- a/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnBean.java +++ b/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnBean.java @@ -2,10 +2,15 @@ package de.unikoblenz.fgbks.dmn.frontend; import java.io.Serializable; import javax.enterprise.context.SessionScoped; +import javax.json.bind.annotation.JsonbProperty; @SessionScoped public class DmnBean implements Serializable { + @JsonbProperty("camundaUrl") + protected String camundaUrl = ""; + + @JsonbProperty("dmnXml") protected String dmnXml; public String getDmnXml() { @@ -15,4 +20,12 @@ public class DmnBean implements Serializable { public void setDmnXml(String dmnXml) { this.dmnXml = dmnXml; } + + public String getCamundaUrl() { + return camundaUrl; + } + + public void setCamundaUrl(String camundaUrl) { + this.camundaUrl = camundaUrl; + } } diff --git a/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnSessionApi.java b/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnSessionApi.java index 3b316f58..08dc705f 100644 --- a/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnSessionApi.java +++ b/dmnverifierfrontend/src/main/java/de/unikoblenz/fgbks/dmn/frontend/DmnSessionApi.java @@ -16,19 +16,25 @@ public class DmnSessionApi { DmnBean dmnBean; @GET - @Path("/getdmn") - @Produces(MediaType.TEXT_XML) + @Produces(MediaType.APPLICATION_JSON) public Response getSessionDmn() { if (dmnBean.getDmnXml() == null) { return Response.noContent().build(); } - return Response.ok(dmnBean.getDmnXml()).build(); + return Response.ok(dmnBean).build(); } @POST - @Path("/setdmn") + @Path("/setDmn") @Consumes(MediaType.TEXT_XML) public void setSessionDmn(String dmnXml) { dmnBean.setDmnXml(dmnXml); } + + @POST + @Path("/setCamundaUrl") + @Consumes(MediaType.TEXT_PLAIN) + public void setCamundaUrl(String camundaUrl) { + dmnBean.setCamundaUrl(camundaUrl); + } } diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/css/img/camundaConnect.png b/dmnverifierfrontend/src/main/resources/META-INF/resources/css/img/camundaConnect.png new file mode 100644 index 0000000000000000000000000000000000000000..490d9a822b78c19360205616ff3389f7609bffd4 GIT binary patch literal 17622 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 Z`Nz@4j(_~V8-rHgdAj<!taD0e0sv0=xxWAa literal 0 HcmV?d00001 diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/css/stylesheets.css b/dmnverifierfrontend/src/main/resources/META-INF/resources/css/stylesheets.css index fc98b25c..b356d7ad 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/css/stylesheets.css +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/css/stylesheets.css @@ -14,6 +14,10 @@ h1 { color: #0b3004; } +button { + background-color: white; +} + h2 { margin: 10px; } @@ -84,6 +88,7 @@ span.select2 { .clickable { box-shadow: 2px 2px 3px 2px rgba(0, 0, 0, .3); + cursor: pointer; } .clickable:hover { @@ -101,12 +106,13 @@ span.select2 { } .dmn-top { - height: 60px; padding-left: 6px; padding-top: 6px; display: flex; flex-direction: row; + flex-wrap: wrap; justify-content: space-around; + margin-bottom: 5px; } .dmn-top-item { @@ -124,6 +130,7 @@ span.select2 { display: block; background-size: cover; background-position: center; + cursor: pointer; } .dmn-upload { @@ -154,6 +161,30 @@ span.select2 { width: 50px; } +.dmn-camunda-api { + flex-grow: 1; +} + +.dmn-camunda-api > label { + background-image: url("img/camundaConnect.png"); + width: 50px; +} + +.dmn-camunda-api > label > a { + display: inline-block; + width: 100%; + height: 100%; +} + +/** Modal */ +.modal-element { + width: 100%; + margin: 5px; + min-height: 25px; + padding: 5px; + font: 12pt Calibri; +} + /** Verifier configuration */ #dmn-verifier-header { @@ -167,14 +198,12 @@ span.select2 { #dmn-button-verify { flex-grow: 1; max-width: 90px; - background: white; border-radius: 2px; } #dmn-button-reload-verifier { flex-grow: 1; max-width: 120px; - background: white; border-radius: 2px; } @@ -182,7 +211,6 @@ span.select2 { margin: 8px 12px; color: #0b3004; min-height: 35px; - cursor: pointer; font-family: 'Open Sans', sans-serif; font-size: 13px; } @@ -268,5 +296,4 @@ span.select2 { height: 25px; min-width: 100px; margin: 2px 2px 2px 10px; - background: white; } diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/dmn/emptyDMN.dmn b/dmnverifierfrontend/src/main/resources/META-INF/resources/dmn/emptyDMN.dmn index 73f512d1..f6fbeeac 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/dmn/emptyDMN.dmn +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/dmn/emptyDMN.dmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_1kjh9a2" name="DRD" namespace="http://camunda.org/schema/1.0/dmn"> - <decision id="Decision_13nychf" name="Decision 1"> +<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_genid1" name="DRD" namespace="http://camunda.org/schema/1.0/dmn"> + <decision id="Decision_genid2" name="Decision 1"> <extensionElements> <biodi:bounds x="120" y="145" width="180" height="80" /> </extensionElements> diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/index.html b/dmnverifierfrontend/src/main/resources/META-INF/resources/index.html index bf24bcf7..d09c9f69 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/index.html +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/index.html @@ -14,7 +14,8 @@ <link href="https://unpkg.com/dmn-js@7.0.1/dist/assets/dmn-js-literal-expression.css" rel="stylesheet"> <link href="https://unpkg.com/dmn-js@7.0.1/dist/assets/dmn-font/css/dmn.css" rel="stylesheet"> - + <link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.css" + rel="stylesheet"/> <link href="assets/css/select2.min.css" rel="stylesheet"/> <link href="css/stylesheets.css" rel="stylesheet" type="text/css"/> @@ -28,15 +29,20 @@ </label> <input id="dmn-file-upload" type="file"/> </div> + <div class="dmn-top-item dmn-download"> + <label class="clickable" for="dmn-file-download" title="Download current dmn"> + </label> + <input id="dmn-file-download" type="button"/> + </div> <div class="dmn-top-item dmn-empty-file"> <label class="clickable" for="dmn-file-empty" title="Create empty dmn"> </label> <input id="dmn-file-empty" type="button"/> </div> - <div class="dmn-top-item dmn-download"> - <label class="clickable" for="dmn-file-download" title="Download current dmn"> + <div class="dmn-top-item dmn-camunda-api"> + <label class="clickable" for="dmn-camunda-api" title="Connect to Camunda Engine"> + <a href="#modal-camunda-api" id="dmn-camunda-api" rel="modal:open"></a> </label> - <input id="dmn-file-download" type="button"/> </div> <div class="dmn-top-item"> <h1>Verification for Decision Modeling Notation</h1> @@ -53,14 +59,22 @@ </div> <div id="root-dmn-verifier"></div> </div> + +<!-- modal for camunda engine --> +<div class="modal" id="modal-camunda-api"> + <div id="camunda-api-root"></div> +</div> <!-- load jquery --> <script src="https://unpkg.com/jquery@3.4.1/dist/jquery.js" type="text/javascript"></script> <script src="assets/js/select2.full.min.js"></script> +<script + src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.1/jquery.modal.min.js"></script> <!-- load dmn modeler --> <script src="https://unpkg.com/dmn-js@7.0.1/dist/dmn-modeler.development.js"></script> <script src="js/dmnUpDownload.js" type="text/javascript"></script> <script src="js/dmnViewer.js" type="text/javascript"></script> <script src="js/dmnVerifier.js" type="text/javascript"></script> +<script src="js/dmnCamundaApi.js" type="text/javascript"></script> </body> </html> diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnCamundaApi.js b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnCamundaApi.js new file mode 100644 index 00000000..98f1f42e --- /dev/null +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnCamundaApi.js @@ -0,0 +1,198 @@ +const engineUrl = 'engine-rest/'; +let camundaEngineUrl = ''; +let connectionSuccess = false; +let $camundaApiRoot = $('#camunda-api-root'); +let $textCamundaUrl = $(` + <input class="modal-element" type="text" size="60"> +`); +$textCamundaUrl.val('localhost'); +let $buttonConnectCamundaUrl = $(` + <button class="clickable modal-element" size="60" id="camunda-connect" + onclick="connectCamunda()">Connect</button> +`); +let $selectCamundaDecisions = $( + `<select class="clickable modal-element" name="decisions" + id="select-camunda-decisions" + onchange="loadCamundaDecisionXml(this)"> + `); +let $buttonDeployDmn = $(` + <button class="clickable modal-element" size="60" id="camunda-connect" + onclick="deployDmn()">Deploy DMN</button> +`); +let $camundaApiContainer = $(`<div id="camunda-api-container">`); + +// register Button action +$(document).ready(function () { + clearCamundaApiRoot(); +}); + +function clearCamundaApiRoot() { + $camundaApiRoot.empty(); + $camundaApiRoot.append($(`<h2>Camunda DMN Deployment</h2>`)); + $camundaApiRoot.append($camundaApiContainer); + loadCamundaSessionParams(); +} + +function refreshParams() { + $textCamundaUrl.val(camundaEngineUrl); + $camundaApiContainer.empty(); + if (connectionSuccess) { + $camundaApiContainer.append($selectCamundaDecisions); + $camundaApiContainer.append($buttonDeployDmn); + } else { + $camundaApiContainer.append($textCamundaUrl); + $camundaApiContainer.append($buttonConnectCamundaUrl); + } +} + +function connectCamunda() { + camundaEngineUrl = $textCamundaUrl.val(); + if (!camundaEngineUrl.endsWith('/')) { + camundaEngineUrl += '/'; + } + if (!camundaEngineUrl.startsWith('http://')) { + camundaEngineUrl = 'http://' + camundaEngineUrl; + } + $textCamundaUrl.val(camundaEngineUrl); + requestOptionsCamundaDecisions(); +} + +function deployDmn() { + let dmnXml = exportDiagram(); + if (dmnXml) { + if (confirm("Do you really want to deploy this dmn?")) { + var fileStringArray = [dmnXml]; + + var fileName = "file.dmn"; + var blobAttrs = {type: "xml"}; + var file = new File(fileStringArray, fileName, blobAttrs); + + var formData = new FormData(); + formData.append("deployment-name", "test"); + formData.append("enable-duplicate-filtering", "true"); + formData.append("deployment-source", "process application"); + formData.append("data", file, file.name); + + $.ajax({ + url: camundaEngineUrl + engineUrl + "deployment/create", + type: "POST", + data: formData, + enctype: 'multipart/form-data', + async: true, + crossDomain: true, + processData: false, + contentType: false, + cache: false, + timeout: 0, + success: function (data) { + $.modal.close(); + requestOptionsCamundaDecisions(); + }, + error: function (e) { + alert("There was a error while deploying the dmn."); + } + }); + } + } +} + +function saveCamundaUrl() { + $.ajax({ + timeout: 1000, + url: "/dmn/setCamundaUrl", + type: 'POST', + contentType: 'text/plain', + data: $textCamundaUrl.val(), + error: function (err) { + // nothing + console.log(err); + } + }); +} + +function loadCamundaSessionParams() { + $.ajax({ + timeout: 1000, + url: "/dmn", + type: 'GET', + contentType: 'application/json', + error: function (err) { + camundaEngineUrl = ''; + connectionSuccess = false; + + refreshParams(); + }, + success: function (data) { + if (data !== undefined && data.camundaUrl !== undefined) { + camundaEngineUrl = data.camundaUrl; + } else { + camundaEngineUrl = ''; + } + refreshParams(); + } + }); +} + +function requestOptionsCamundaDecisions() { + $selectCamundaDecisions.empty(); + $.ajax({ + timeout: 1000, + url: camundaEngineUrl + engineUrl + + 'decision-definition?latestVersion=true', + type: 'GET', + contentType: 'application/json', + error: function (err) { + connectionSuccess = false; + alert( + "Error: No connection to the camunda engine established. Check URL or CORS options."); + refreshParams(); + }, + success: function (data) { + connectionSuccess = true; + renderDecisionsOptions(data); + saveCamundaUrl(); + refreshParams(); + } + }); +} + +function renderDecisionsOptions(decisions) { + $selectCamundaDecisions.empty(); + $selectCamundaDecisions.append($(` + <option value="null" selected>Select a definition</option> + `)); + for (let i = 0; i < decisions.length; i++) { + let decision = decisions[i]; + $selectCamundaDecisions.append($(` + <option value="${decision.key}">${decision.name} (Version: ${decision.version})</option> + `)); + } +} + +function loadCamundaDecisionXml(decisionSelect) { + if (decisionSelect.value !== 'null') { + if (confirm( + 'Do you really want to load the dmn "' + + $("#select-camunda-decisions option:selected").text() + + '"?')) { + $.ajax({ + timeout: 1000, + url: camundaEngineUrl + engineUrl + 'decision-definition/key/' + + decisionSelect.value + + '/xml/', + type: 'GET', + error: function (err) { + console.log("error", err); + connectionSuccess = false; + refreshParams(); + alert(err); + }, + success: function (data) { + openDiagram(data.dmnXml); + refreshParams(); + $.modal.close(); + } + }); + } + } +} diff --git a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnUpDownload.js b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnUpDownload.js index 83295f03..d96a586f 100644 --- a/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnUpDownload.js +++ b/dmnverifierfrontend/src/main/resources/META-INF/resources/js/dmnUpDownload.js @@ -21,8 +21,12 @@ function loadEmptyFile() { $.ajax({ url: 'dmn/emptyDMN.dmn', type: 'GET', + cache: false, contentType: 'text/xml', success: function (data) { + // TODO, replace definition ID + data = data.replace("genid1", generateId(8)) + .replace("genid2", generateId(8)); openDiagram(data); } }); @@ -48,9 +52,9 @@ let oSerializer = new XMLSerializer(); function loadSessionDmn() { $.ajax({ timeout: 1000, - url: "/dmn/getdmn", + url: "/dmn", type: 'GET', - contentType: 'text/xml', + contentType: 'application/json', error: function (err) { // nothing console.log(">-->--> loading session dmn failed. <--<--<"); @@ -58,8 +62,13 @@ function loadSessionDmn() { loadEmptyFile(); }, success: function (data) { - let sXML = oSerializer.serializeToString(data); - openDiagram(sXML); + if (data !== undefined && data.dmnXml !== undefined) { + // let sXML = oSerializer.serializeToString(data.dmnXml); + let sXML = data.dmnXml; + openDiagram(sXML); + } else { + loadEmptyFile(); + } } }); } @@ -68,7 +77,7 @@ function saveSessionDmn() { let dmnXml = exportDiagram(); $.ajax({ timeout: 1000, - url: "/dmn/setdmn", + url: "/dmn/setDmn", type: 'POST', contentType: 'text/xml', data: dmnXml, @@ -78,3 +87,13 @@ function saveSessionDmn() { } }); } + +function generateId(length) { + var result = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} diff --git a/dmnverifierparent/pom.xml b/dmnverifierparent/pom.xml index ee94bcb9..0e5861a2 100644 --- a/dmnverifierparent/pom.xml +++ b/dmnverifierparent/pom.xml @@ -37,6 +37,10 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> + <dependency> + <artifactId>quarkus-resteasy-jsonb</artifactId> + <groupId>io.quarkus</groupId> + </dependency> </dependencies> <modules> -- GitLab