diff --git a/multi-ruleunit-quarkus-example-poc/README.md b/multi-ruleunit-quarkus-example-poc/README.md new file mode 100644 index 0000000000..59c71b45f1 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/README.md @@ -0,0 +1,48 @@ +### POST /find-invalid-applicant + +Returns applicants who are considered as invalid by ApplicantValidationUnit rules: + +```sh +curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"loanApplications":[{"id":"ABC10001","amount":2000,"deposit":100,"applicant":{"age":45,"name":"John","creditScore":20}}, {"id":"ABC10002","amount":500,"deposit":100,"applicant":{"age":25,"name":"Paul","creditScore":200}}, {"id":"ABC10015","amount":1000,"deposit":100,"applicant":{"age":12,"name":"George","creditScore":200}}, {"id":"ABC10020","amount":5000,"deposit":100,"applicant":{"age":30,"name":"Ringo","creditScore":200}}]}' http://localhost:8080/find-invalid-applicant +``` + +George is invalid due to his age. John is invalid due to his creditScore. + +Example response: +```json +[{"name":"George","age":12,"creditScore":200,"invalid":true},{"name":"John","age":45,"creditScore":20,"invalid":true}] +``` + + +### POST /find-approved + +Returns approved loan applications by LoanUnit rules: + +```sh +curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"loanApplications":[{"id":"ABC10001","amount":2000,"deposit":100,"applicant":{"age":45,"name":"John","creditScore":20}}, {"id":"ABC10002","amount":500,"deposit":100,"applicant":{"age":25,"name":"Paul","creditScore":200}}, {"id":"ABC10015","amount":1000,"deposit":100,"applicant":{"age":12,"name":"George","creditScore":200}}, {"id":"ABC10020","amount":5000,"deposit":100,"applicant":{"age":30,"name":"Ringo","creditScore":200}}]}' http://localhost:8080/find-approved +``` + +Ringo was rejected but other 3 loan applications are approved because LoanUnit doesn't validate applicant's age and creditScore. + +Example response: + +```json +[{"id":"ABC10002","applicant":{"name":"Paul","age":25,"creditScore":200,"invalid":false},"amount":500,"deposit":100,"approved":true},{"id":"ABC10001","applicant":{"name":"John","age":45,"creditScore":20,"invalid":false},"amount":2000,"deposit":100,"approved":true},{"id":"ABC10015","applicant":{"name":"George","age":12,"creditScore":200,"invalid":false},"amount":1000,"deposit":100,"approved":true}] +``` + +### POST /2units + +Custom REST endpoint to execute ApplicantValidationUnit and LoanUnit. Then reply with "FindApproved" query. + +```sh +curl -X POST -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"loanApplications":[{"id":"ABC10001","amount":2000,"deposit":100,"applicant":{"age":45,"name":"John","creditScore":20}}, {"id":"ABC10002","amount":500,"deposit":100,"applicant":{"age":25,"name":"Paul","creditScore":200}}, {"id":"ABC10015","amount":1000,"deposit":100,"applicant":{"age":12,"name":"George","creditScore":200}}, {"id":"ABC10020","amount":5000,"deposit":100,"applicant":{"age":30,"name":"Ringo","creditScore":200}}]}' http://localhost:8080/2units +``` + +Only Paul is approved because it passes both ApplicantValidationUnit and LoanUnit rules. + +Example response: + +```json +[{"id":"ABC10002","applicant":{"name":"Paul","age":25,"creditScore":200,"invalid":false},"amount":500,"deposit":100,"approved":true}] +``` + diff --git a/multi-ruleunit-quarkus-example-poc/operator/multi-ruleunit-quarkus-example.yaml b/multi-ruleunit-quarkus-example-poc/operator/multi-ruleunit-quarkus-example.yaml new file mode 100644 index 0000000000..d149fd66a7 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/operator/multi-ruleunit-quarkus-example.yaml @@ -0,0 +1,20 @@ +apiVersion: app.kiegroup.org/v1beta1 +kind: KogitoBuild +metadata: + name: multi-ruleunit-quarkus-example +spec: + type: RemoteSource + #env: + # env can be used to set variables during build + #- name: MY_CUSTOM_ENV + # value: "my value" + gitSource: + contextDir: multi-ruleunit-quarkus-example + uri: 'https://github.com/kiegroup/kogito-examples' + # set your maven nexus repository to speed up the build time + #mavenMirrorURL: +--- +apiVersion: app.kiegroup.org/v1beta1 +kind: KogitoRuntime +metadata: + name: multi-ruleunit-quarkus-example \ No newline at end of file diff --git a/multi-ruleunit-quarkus-example-poc/pom.xml b/multi-ruleunit-quarkus-example-poc/pom.xml new file mode 100644 index 0000000000..aa9e2b8a08 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + org.kie.kogito.examples + kogito-examples + 2.0.0-SNAPSHOT + + multi-ruleunit-quarkus-example-poc + Kogito Example :: Multiple RuleUnit - Quarkus + + 2.3.0.Final + quarkus-bom + io.quarkus + 2.3.0.Final + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + org.kie.kogito + kogito-quarkus-rules + + + io.quarkus + quarkus-resteasy-jackson + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-smallrye-openapi + + + org.kie.kogito + kogito-drools + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + io.quarkus + quarkus-smallrye-health + + + + ${project.artifactId} + + + io.quarkus + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + build + + + + + + + diff --git a/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/Applicant.java b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/Applicant.java new file mode 100644 index 0000000000..3d8a154d5b --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/Applicant.java @@ -0,0 +1,67 @@ +/* + * Copyright 2020 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; + +public class Applicant { + + private String name; + private int age; + private int creditScore; + private boolean invalid = false; // false by default + + public Applicant() { + } + + public Applicant(String name, int age, int creditScore) { + super(); + this.name = name; + this.age = age; + this.creditScore = creditScore; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getCreditScore() { + return creditScore; + } + + public void setCreditScore(int creditScore) { + this.creditScore = creditScore; + } + + public boolean isInvalid() { + return invalid; + } + + public void setInvalid(boolean invalid) { + this.invalid = invalid; + } + +} diff --git a/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/ApplicantValidationUnit.java b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/ApplicantValidationUnit.java new file mode 100644 index 0000000000..08e8a0473f --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/ApplicantValidationUnit.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; + +import org.kie.kogito.rules.DataSource; +import org.kie.kogito.rules.DataStore; +import org.kie.kogito.rules.RuleUnitData; + +public class ApplicantValidationUnit implements RuleUnitData { + + private DataStore loanApplications; + + public ApplicantValidationUnit() { + this(DataSource.createStore()); + } + + public ApplicantValidationUnit(DataStore loanApplications) { + this.loanApplications = loanApplications; + } + + public DataStore getLoanApplications() { + return loanApplications; + } + + public void setLoanApplications(DataStore loanApplications) { + this.loanApplications = loanApplications; + } +} diff --git a/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/LoanApplication.java b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/LoanApplication.java new file mode 100644 index 0000000000..4b84e14d1f --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/LoanApplication.java @@ -0,0 +1,82 @@ +/* + * Copyright 2020 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; + +public class LoanApplication { + + private String id; + + private Applicant applicant; + + private int amount; + + private int deposit; + + private boolean approved = false; // false by default + + public LoanApplication() { + } + + public LoanApplication(String id, Applicant applicant, int amount, int deposit, boolean approved) { + super(); + this.id = id; + this.applicant = applicant; + this.amount = amount; + this.deposit = deposit; + this.approved = approved; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Applicant getApplicant() { + return applicant; + } + + public void setApplicant(Applicant applicant) { + this.applicant = applicant; + } + + public boolean isApproved() { + return approved; + } + + public void setApproved(boolean approved) { + this.approved = approved; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public int getDeposit() { + return deposit; + } + + public void setDeposit(int deposit) { + this.deposit = deposit; + } + +} diff --git a/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/LoanUnit.java b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/LoanUnit.java new file mode 100644 index 0000000000..01471b4949 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/LoanUnit.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; + +import org.kie.kogito.rules.DataSource; +import org.kie.kogito.rules.DataStore; +import org.kie.kogito.rules.RuleUnitData; + +public class LoanUnit implements RuleUnitData { + + private DataStore loanApplications; + + public LoanUnit() { + this(DataSource.createStore()); + } + + public LoanUnit(DataStore loanApplications) { + this.loanApplications = loanApplications; + } + + public DataStore getLoanApplications() { + return loanApplications; + } + + public void setLoanApplications(DataStore loanApplications) { + this.loanApplications = loanApplications; + } +} diff --git a/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/TwoUnitsEndpoint.java b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/TwoUnitsEndpoint.java new file mode 100644 index 0000000000..f559ab8c1f --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/java/org/kie/kogito/examples/TwoUnitsEndpoint.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.kie.kogito.rules.DataStore; +import org.kie.kogito.rules.RuleUnit; +import org.kie.kogito.rules.RuleUnitInstance; + +@Path("/2units") +public class TwoUnitsEndpoint { + + @javax.inject.Inject + RuleUnit applicantValidationUnit; + + @javax.inject.Inject + RuleUnit loanUnit; + + public TwoUnitsEndpoint() { + } + + @POST() + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public List executeQuery(org.kie.kogito.examples.ApplicantValidationUnit unitDTO) { + // 1. Execute ApplicantValidationUnit + RuleUnitInstance applicantValidationUnitInstance = applicantValidationUnit.createInstance(unitDTO); + applicantValidationUnitInstance.fire(); + applicantValidationUnitInstance.dispose(); + + // 2. Execute LoanUnit + DataStore loanApplications = unitDTO.getLoanApplications(); + LoanUnit loanUnitData = new LoanUnit(loanApplications); + RuleUnitInstance loanUnitInstance = loanUnit.createInstance(loanUnitData); + List response = loanUnitInstance.executeQuery("FindApproved").stream().map(this::toResult).collect(Collectors.toList()); + loanUnitInstance.dispose(); + + return response; + } + + private LoanApplication toResult(Map tuple) { + return (LoanApplication) tuple.get("$l"); + } +} diff --git a/multi-ruleunit-quarkus-example-poc/src/main/resources/application.properties b/multi-ruleunit-quarkus-example-poc/src/main/resources/application.properties new file mode 100644 index 0000000000..9557fd6d04 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/resources/application.properties @@ -0,0 +1,7 @@ +# Packaging +# quarkus.package.type=fast-jar + +quarkus.swagger-ui.always-include=true + +# Maximum Java heap to be used during the native image generation +quarkus.native.native-image-xmx=4g diff --git a/multi-ruleunit-quarkus-example-poc/src/main/resources/org/kie/kogito/examples/ApplicantValidationUnit.drl b/multi-ruleunit-quarkus-example-poc/src/main/resources/org/kie/kogito/examples/ApplicantValidationUnit.drl new file mode 100644 index 0000000000..d8bc03c09a --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/resources/org/kie/kogito/examples/ApplicantValidationUnit.drl @@ -0,0 +1,44 @@ +/** + * Copyright 2020 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; +unit ApplicantValidationUnit; + +import org.kie.kogito.examples.LoanApplication; + +rule NotAdult +lock-on-active true +when + $l: /loanApplications[ applicant.age < 20 ] +then + Applicant $a = $l.getApplicant(); + $a.setInvalid(true); + modify($l) { setApplicant($a) }; +end + +rule BadCreditScore +lock-on-active true +when + $l: /loanApplications[ applicant.creditScore < 100 ] +then + Applicant $a = $l.getApplicant(); + $a.setInvalid(true); + modify($l) { setApplicant($a) }; +end + +query FindInvalidApplicant + /loanApplications[ $applicant: applicant, applicant.invalid ] +end + diff --git a/multi-ruleunit-quarkus-example-poc/src/main/resources/org/kie/kogito/examples/LoanUnit.drl b/multi-ruleunit-quarkus-example-poc/src/main/resources/org/kie/kogito/examples/LoanUnit.drl new file mode 100644 index 0000000000..9952ae3ce5 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/main/resources/org/kie/kogito/examples/LoanUnit.drl @@ -0,0 +1,51 @@ +/** + * Copyright 2020 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; +unit LoanUnit; + +import org.kie.kogito.examples.LoanApplication; + +rule SmallDepositApprove when + $l: /loanApplications[ !applicant.invalid, deposit < 1000, amount <= 2000 ] +then + modify($l) { setApproved(true) }; +end + +rule SmallDepositReject when + $l: /loanApplications[ !applicant.invalid, deposit < 1000, amount > 2000 ] +then + modify($l) { setApproved(false) }; +end + +rule LargeDepositApprove when + $l: /loanApplications[ !applicant.invalid, deposit >= 1000, amount <= 10000 ] +then + modify($l) { setApproved(true) }; +end + +rule LargeDepositReject when + $l: /loanApplications[ !applicant.invalid, deposit >= 1000, amount > 10000 ] +then + modify($l) { setApproved(false) }; +end + +query FindApproved + $l: /loanApplications[ approved ] +end + +query FindNotApprovedIdAndAmount + /loanApplications[ !approved, $id: id, $amount : amount ] +end diff --git a/multi-ruleunit-quarkus-example-poc/src/test/java/org/kie/kogito/examples/RestQueryTest.java b/multi-ruleunit-quarkus-example-poc/src/test/java/org/kie/kogito/examples/RestQueryTest.java new file mode 100644 index 0000000000..f608cf439b --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/test/java/org/kie/kogito/examples/RestQueryTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2021 Red Hat, Inc. and/or its affiliates. + * + * Licensed 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.examples; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.http.ContentType; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.hasItem; + +@QuarkusTest +public class RestQueryTest { + + private static final String JSON_PAYLOAD = + "{\n" + + " \"loanApplications\":[\n" + + " {\n" + + " \"id\":\"ABC10001\",\n" + + " \"amount\":2000,\n" + + " \"deposit\":100,\n" + + " \"applicant\":{\n" + + " \"age\":45,\n" + + " \"name\":\"John\",\n" + + " \"creditScore\":20\n" + + " }\n" + + " },\n" + + " {\n" + + " \"id\":\"ABC10002\",\n" + + " \"amount\":500,\n" + + " \"deposit\":100,\n" + + " \"applicant\":{\n" + + " \"age\":25,\n" + + " \"name\":\"Paul\",\n" + + " \"creditScore\":200\n" + + " }\n" + + " },\n" + + " {\n" + + " \"id\":\"ABC10015\",\n" + + " \"amount\":1000,\n" + + " \"deposit\":100,\n" + + " \"applicant\":{\n" + + " \"age\":12,\n" + + " \"name\":\"George\",\n" + + " \"creditScore\":200\n" + + " }\n" + + " },\n" + + " {\n" + + " \"id\":\"ABC10020\",\n" + + " \"amount\":5000,\n" + + " \"deposit\":100,\n" + + " \"applicant\":{\n" + + " \"age\":30,\n" + + " \"name\":\"Ringo\",\n" + + " \"creditScore\":200\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + public void testApprovedDivisionA() { + given() + .body(JSON_PAYLOAD) + .contentType(ContentType.JSON) + .when() + .post("/2units") + .then() + .statusCode(200) + .body("id", hasItem("ABC10002")); + } + +} diff --git a/multi-ruleunit-quarkus-example-poc/src/test/resources/application.properties b/multi-ruleunit-quarkus-example-poc/src/test/resources/application.properties new file mode 100644 index 0000000000..8c5dc5bd35 --- /dev/null +++ b/multi-ruleunit-quarkus-example-poc/src/test/resources/application.properties @@ -0,0 +1,5 @@ +# Quarkus +quarkus.http.test-port=0 + +# Maximum Java heap to be used during the native image generation +quarkus.native.native-image-xmx=4g