Extend Capability in Kie Server
The Kie Server REST API enables you to interact with our business assets (such as business rules, processes, and solvers). The available REST endpoints are determined by the capabilities enabled in our Kie Server. We can extend an existing Kie Server capability with a custom REST API endpoint to further adapt our business needs.
In this post, we’re going to extend the BRM capability (Drools extension) using the Kie Server 7.7.1 image with the following custom REST API endpoint:
/server/containers/instances/{containerId}/customksession/{ksessionId}
1.- Create Project
mvn archetype:generate -DgroupId=org.sgitario.jbpm -DartifactId=extend-capability -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
2.- Add kie server dependencies into the pom.xml
Depending on the Kie Server image, you might need to change the kie server dependencies. For Kie Server 7.7.1 image, the dependencies version is 7.38.0.Final.
<packaging>jar</packaging>
<properties>
<version.org.kie>7.38.0.Final</version.org.kie>
</properties>
<dependencies>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.kie.server</groupId>
<artifactId>kie-server-api</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.kie.server</groupId>
<artifactId>kie-server-services-common</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.kie.server</groupId>
<artifactId>kie-server-services-drools</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.kie.server</groupId>
<artifactId>kie-server-rest-common</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${version.org.kie}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
3.- Implement KieServerApplicationComponentsService interface in order to filter out application resources depending on the caller extensions and transports
public class CustomKieServerApplicationComponentsService implements KieServerApplicationComponentsService {
private static final String OWNER_EXTENSION = "Drools";
@Override
public Collection<Object> getAppComponents(String extension, SupportedTransports type, Object... services) {
// Do not accept calls from extensions other than the owner extension
// Only REST transport is implemented
if (!OWNER_EXTENSION.equals(extension) || !SupportedTransports.REST.equals(type)) {
return Collections.emptyList();
}
RulesExecutionService rulesExecutionService = findByType(services, RulesExecutionService.class);
KieServerRegistry context = findByType(services, KieServerRegistry.class);
Object resource = new CustomKSessionResource(rulesExecutionService, context);
return Arrays.asList(resource);
}
@SuppressWarnings("unchecked")
private <T> T findByType(Object[] services, Class<T> clazz) {
return Stream.of(services).filter(svc -> clazz.isAssignableFrom(svc.getClass())).map(svc -> (T) svc).findFirst()
.get();
}
}
4.- Make the service discoverable
To make the new endpoint discoverable, create a src/main/resources/META-INF/services/org.kie.server.services.api.KieServerApplicationComponentsService file and add the fully qualified class name of the KieServerApplicationComponentsService implementation class within the file:
org.sgitario.jbpm.CustomKieServerApplicationComponentsService
5.- Build the project
mvn clean package
It will generate the file target/extend-capability-1.0-SNAPSHOT.jar.
6.- Create our own image of Kie Server
Create a file called Dockerfile:
FROM registry.redhat.io/rhdm-7/rhdm-kieserver-rhel8:7.7.1
COPY target/extend-capability-1.0-SNAPSHOT.jar /opt/eap/standalone/deployments/ROOT.war/WEB-INF/lib/
Note that we need to sign up in the Red Hat registry. |
Then, build the image:
docker build . --tag quay.io/jcarvaja/rhdm-kieserver-rhel8-extended-capability
7.- Prepare the KJAR example
We’re going to create a pretty simple example in Drools (more about this topic in this post). This example will only say hello to persons.
First, we need a Maven repository to be accessible to push the KJar module and our Kie Server:
docker run -d -p 8081:8081 --name nexus sonatype/nexus
The default credentials is admin/admin123.
Create the pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jbpm.test</groupId>
<artifactId>say-hello-kjar-example</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>kjar</packaging>
<name>say-hello-kjar-example</name>
<build>
<plugins>
<plugin>
<groupId>org.kie</groupId>
<artifactId>kie-maven-plugin</artifactId>
<version>7.38.0.Final</version>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://localhost:8081/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>
Then, the *Person.java domain model:
package org.jbpm.test;
public class Person implements java.io.Serializable {
private Integer age;
private String name;
// constructors, getters and setters
}
The say-hello-person.drl rule:
import org.jbpm.test.Person;
rule SayHello
when
$p : Person(age >= 21)
then
System.out.println("Hello " + $p.getName());
end
And finally, we build and publish the artifact into our Nexus instance:
mvn --settings settings.xml clean install deploy
8.- Test it
We first run our Kie Server image:
docker run -it -p 8080:8080 --rm --env KIE_ADMIN_USER=admin --env KIE_ADMIN_PWD=admin --env MAVEN_MIRROR_URL=http://nexus:8081/nexus/content/groups/public/ --link nexus quay.io/jcarvaja/rhdm-kieserver-rhel8-extended-capability
Then, we deploy our KJAR example:
curl -X PUT "http://admin:admin@localhost:8080/services/rest/server/containers/sayHello" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"container-id\" : \"sayHello\", \"release-id\" : { \"group-id\" : \"org.jbpm.test\", \"artifact-id\" : \"say-hello-kjar-example\", \"version\" : \"1.0-SNAPSHOT\" }}"
And run our example:
curl -X POST "http://admin:admin@localhost:8080/services/rest/server/containers/instances/sayHello/customksession/ksession" -H "Content-Type: application/json" -d '[{"org.jbpm.test.Person": {"name": "john","age": 25}}]'
Where ksession is the name in the kmodule.xml of our KJAR module.
In our server logs, as “john” is older than 21, we should see:
14:12:49,715 INFO [stdout] (default task-1) Hello john
Conclusion
All the source code can be found in this repository.