Merge branch 'eugenp:master' into master

This commit is contained in:
lsieun 2021-10-20 02:44:01 +08:00 committed by GitHub
commit d3c8cc8a34
20 changed files with 525 additions and 6 deletions

View File

@ -0,0 +1,4 @@
[submodule "project"]
path = project
url = https://github.com/eugenp/tutorials.git
branch = master

View File

@ -0,0 +1,13 @@
ADD . /project/
ADD /build/ /project/
ADD /output/project.jar /project/
ADD ssh-private-key /root/.ssh/id_rsa
RUN git clone git@github.com:eugenp/tutorials.git
ARG username=$GIT_USERNAME
ARG password=$GIT_PASSWORD
RUN git clone https://username:password@github.com:eugenp/tutorials.git
VOLUME /build/ /project/

View File

@ -0,0 +1,14 @@
spring:
h2:
console:
enabled: true
path: /h2-console
console.settings.trace: false
spring.h2.console.settings.web-allow-others: false
datasource:
url: jdbc:h2:mem:mydb
username: sa
password: password
driverClassName: org.h2.Driver
jpa:
spring.jpa.database-platform: org.hibernate.dialect.H2Dialect

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.evrete</groupId>
<artifactId>evrete</artifactId>
<version>1.0</version>
<name>evrete</name>
<properties>
<evrete.version>2.1.04</evrete.version>
</properties>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>rule-engines</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!-- Core library -->
<dependency>
<groupId>org.evrete</groupId>
<artifactId>evrete-core</artifactId>
<version>${evrete.version}</version>
</dependency>
<!-- Annotated Java classes -->
<dependency>
<groupId>org.evrete</groupId>
<artifactId>evrete-dsl-java</artifactId>
<version>${evrete.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,47 @@
package com.baeldung.evrete.introduction;
import com.baeldung.evrete.introduction.model.Customer;
import com.baeldung.evrete.introduction.model.Invoice;
import org.evrete.KnowledgeService;
import org.evrete.api.Knowledge;
import java.io.IOException;
import java.net.URL;
import java.util.*;
public class IntroductionAJR {
public static void main(String[] args) throws IOException {
ClassLoader classLoader = IntroductionAJR.class.getClassLoader();
KnowledgeService service = new KnowledgeService();
URL rulesetUrl = classLoader.getResource("rules/SalesRuleset.java");
Knowledge knowledge = service.newKnowledge(
"JAVA-SOURCE",
rulesetUrl
);
List<Customer> customers = Arrays.asList(
new Customer("Customer A"),
new Customer("Customer B"),
new Customer("Customer C")
);
Random random = new Random();
Collection<Object> sessionData = new LinkedList<>(customers);
for (int i = 0; i < 100_000; i++) {
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
Invoice invoice = new Invoice(randomCustomer, 100 * random.nextDouble());
sessionData.add(invoice);
}
knowledge
.newStatelessSession()
.insert(sessionData)
.fire();
for (Customer c : customers) {
System.out.printf("%s:\t$%,.2f%n", c.getName(), c.getTotal());
}
service.shutdown();
}
}

View File

@ -0,0 +1,58 @@
package com.baeldung.evrete.introduction;
import org.evrete.KnowledgeService;
import org.evrete.api.Knowledge;
import com.baeldung.evrete.introduction.model.*;
import java.util.*;
public class IntroductionInline {
public static void main(String[] args) {
KnowledgeService service = new KnowledgeService();
Knowledge knowledge = service
.newKnowledge()
.newRule("Clear total sales")
.forEach("$c", Customer.class)
.execute(ctx -> {
Customer c = ctx.get("$c");
c.setTotal(0.0);
})
.newRule("Compute totals")
.forEach(
"$c", Customer.class,
"$i", Invoice.class
)
.where("$i.customer == $c")
.execute(ctx -> {
Customer c = ctx.get("$c");
Invoice i = ctx.get("$i");
c.addToTotal(i.getAmount());
});
List<Customer> customers = Arrays.asList(
new Customer("Customer A"),
new Customer("Customer B"),
new Customer("Customer C")
);
Random random = new Random();
Collection<Object> sessionData = new LinkedList<>(customers);
for (int i = 0; i < 100_000; i++) {
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
Invoice invoice = new Invoice(randomCustomer, 100 * random.nextDouble());
sessionData.add(invoice);
}
knowledge
.newStatelessSession()
.insert(sessionData)
.fire();
for (Customer c : customers) {
System.out.printf("%s:\t$%,.2f%n", c.getName(), c.getTotal());
}
service.shutdown();
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.evrete.introduction.model;
public class Customer {
private double total = 0.0;
private final String name;
public Customer(String name) {
this.name = name;
}
public void addToTotal(double amount) {
this.total += amount;
}
public String getName() {
return name;
}
public double getTotal() {
return total;
}
public void setTotal(double total) {
this.total = total;
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.evrete.introduction.model;
public class Invoice {
private final Customer customer;
private final double amount;
public Invoice(Customer customer, double amount) {
this.customer = customer;
this.amount = amount;
}
public Customer getCustomer() {
return customer;
}
public double getAmount() {
return amount;
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,20 @@
package org.abc.author1;
import com.baeldung.evrete.introduction.model.Customer;
import com.baeldung.evrete.introduction.model.Invoice;
import org.evrete.dsl.annotation.Rule;
import org.evrete.dsl.annotation.Where;
public class SalesRuleset {
@Rule
public void rule1(Customer $c) {
$c.setTotal(0.0);
}
@Rule
@Where("$i.customer == $c")
public void rule2(Customer $c, Invoice $i) {
$c.addToTotal($i.getAmount());
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.evrete.introduction;
import com.baeldung.evrete.introduction.model.Customer;
import com.baeldung.evrete.introduction.model.Invoice;
import org.evrete.KnowledgeService;
import org.evrete.api.Knowledge;
import org.evrete.api.RuleSession;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import java.io.IOException;
import java.util.*;
class IntroductionAJRUnitTest {
private static KnowledgeService service;
@BeforeAll
static void setUpClass() {
service = new KnowledgeService();
}
@AfterAll
static void shutDownClass() {
service.shutdown();
}
/**
* This test makes sure that each customer's actual total sales is equal to the amount
* computed by the rule engine
*/
@ParameterizedTest
@ValueSource(strings = {"true", "false"})
void sessionTotalsTest(String type) throws IOException {
boolean stateful = Boolean.parseBoolean(type);
ClassLoader classLoader = IntroductionAJR.class.getClassLoader();
KnowledgeService service = new KnowledgeService();
Knowledge knowledge = service
.newKnowledge(
"JAVA-SOURCE",
classLoader.getResource("rules/SalesRuleset.java")
);
List<Customer> customers = Arrays.asList(
new Customer("Customer A"),
new Customer("Customer B"),
new Customer("Customer C")
);
Collection<Object> sessionData = new LinkedList<>(customers);
HashMap<Customer, Double> actualTotals = new HashMap<>();
Random random = new Random();
for (int i = 0; i < 1_000; i++) {
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
Invoice invoice = new Invoice(randomCustomer, random.nextInt(100));
sessionData.add(invoice);
Double d = actualTotals.get(randomCustomer);
if(d == null) {
d = 0.0;
}
d = d + invoice.getAmount();
actualTotals.put(randomCustomer, d);
}
RuleSession<?> session = stateful ? knowledge.newStatefulSession() : knowledge.newStatelessSession();
session
.insert(sessionData)
.fire();
for(Customer c : customers) {
double d1 = c.getTotal();
double d2 = actualTotals.get(c);
assert d1 == d2;
}
}
}

View File

@ -0,0 +1,90 @@
package com.baeldung.evrete.introduction;
import com.baeldung.evrete.introduction.model.Customer;
import com.baeldung.evrete.introduction.model.Invoice;
import org.evrete.KnowledgeService;
import org.evrete.api.Knowledge;
import org.evrete.api.RuleSession;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import java.util.*;
class IntroductionInlineUnitTest {
private static KnowledgeService service;
@BeforeAll
static void setUpClass() {
service = new KnowledgeService();
}
@AfterAll
static void shutDownClass() {
service.shutdown();
}
/**
* This test makes sure that each customer's actual total sales is equal to the amount
* computed by the rule engine
*/
@ParameterizedTest
@ValueSource(strings = {"true", "false"})
void sessionTotalsTest(String type) {
boolean stateful = Boolean.parseBoolean(type);
Knowledge knowledge = service
.newKnowledge()
.newRule("Clear customer's total sales")
.forEach("$c", Customer.class)
.execute(ctx -> {
Customer c = ctx.get("$c");
c.setTotal(0.0);
})
.newRule("Compute totals")
.forEach(
"$c", Customer.class,
"$i", Invoice.class
)
.where("$i.customer == $c")
.execute(ctx -> {
Customer c = ctx.get("$c");
Invoice i = ctx.get("$i");
c.addToTotal(i.getAmount());
});
List<Customer> customers = Arrays.asList(
new Customer("Customer A"),
new Customer("Customer B"),
new Customer("Customer C")
);
Collection<Object> sessionData = new LinkedList<>(customers);
HashMap<Customer, Double> actualTotals = new HashMap<>();
Random random = new Random();
for (int i = 0; i < 1_000; i++) {
Customer randomCustomer = customers.get(random.nextInt(customers.size()));
Invoice invoice = new Invoice(randomCustomer, random.nextInt(100));
sessionData.add(invoice);
Double d = actualTotals.get(randomCustomer);
if(d == null) {
d = 0.0;
}
d = d + invoice.getAmount();
actualTotals.put(randomCustomer, d);
}
RuleSession<?> session = stateful ? knowledge.newStatefulSession() : knowledge.newStatelessSession();
session
.insert(sessionData)
.fire();
for(Customer c : customers) {
double d1 = c.getTotal();
double d2 = actualTotals.get(c);
assert d1 == d2;
}
}
}

View File

@ -15,6 +15,7 @@
<modules>
<module>easy-rules</module>
<module>evrete</module>
<module>openl-tablets</module>
<module>rulebook</module>
<!-- <module>jess</module> --> <!-- requires dependencies which are not publicly available -->

View File

@ -10,8 +10,8 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<artifactId>spring-web-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>

View File

@ -10,8 +10,8 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<artifactId>spring-web-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>

View File

@ -0,0 +1,21 @@
package com.baeldung.parallel;
import org.junit.jupiter.api.Test;
public class FirstParallelUnitTest {
@Test
public void first() throws Exception{
System.out.println("FirstParallelUnitTest first() start => " + Thread.currentThread().getName());
Thread.sleep(500);
System.out.println("FirstParallelUnitTest first() end => " + Thread.currentThread().getName());
}
@Test
public void second() throws Exception{
System.out.println("FirstParallelUnitTest second() start => " + Thread.currentThread().getName());
Thread.sleep(500);
System.out.println("FirstParallelUnitTest second() end => " + Thread.currentThread().getName());
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.parallel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import java.util.ArrayList;
import java.util.List;
public class ParallelResourceLockUnitTest {
private List<String> resources;
@BeforeEach
void before() {
resources = new ArrayList<>();
resources.add("test");
}
@AfterEach
void after() {
resources.clear();
}
@Test
@ResourceLock(value = "resources")
public void first() throws Exception {
System.out.println("ParallelResourceLockUnitTest first() start => " + Thread.currentThread().getName());
resources.add("first");
System.out.println(resources);
Thread.sleep(500);
System.out.println("ParallelResourceLockUnitTest first() end => " + Thread.currentThread().getName());
}
@Test
@ResourceLock(value = "resources")
public void second() throws Exception {
System.out.println("ParallelResourceLockUnitTest second() start => " + Thread.currentThread().getName());
resources.add("second");
System.out.println(resources);
Thread.sleep(500);
System.out.println("ParallelResourceLockUnitTest second() end => " + Thread.currentThread().getName());
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.parallel;
import org.junit.jupiter.api.Test;
public class SecondParallelUnitTest {
@Test
public void first() throws Exception{
System.out.println("SecondParallelUnitTest first() start => " + Thread.currentThread().getName());
Thread.sleep(500);
System.out.println("SecondParallelUnitTest first() end => " + Thread.currentThread().getName());
}
@Test
public void second() throws Exception{
System.out.println("SecondParallelUnitTest second() start => " + Thread.currentThread().getName());
Thread.sleep(500);
System.out.println("SecondParallelUnitTest second() end => " + Thread.currentThread().getName());
}
}

View File

@ -0,0 +1,4 @@
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.config.strategy=dynamic
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.mode.classes.default = concurrent

View File

@ -15,10 +15,18 @@ public class SimpleXstreamInitializer {
}
public XStream getXstreamJettisonMappedInstance() {
return new XStream(new JettisonMappedXmlDriver());
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.allowTypesByWildcard(new String[]{
"com.baeldung.**"
});
return xstream;
}
public XStream getXstreamJsonHierarchicalInstance() {
return new XStream(new JsonHierarchicalStreamDriver());
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.allowTypesByWildcard(new String[]{
"com.baeldung.**"
});
return xstream;
}
}