JBoss.orgCommunity Documentation
Drools Android integration comes in two flavors, with or without the drools-compiler dependency. Without the drools-compiler dependency the knowledge bases are pre-serialized at buildtime using the kie-maven-plugin. They can be then deserialized using the API, or directly injected using Roboguice. When using the drools-compiler dependency there are two options: (1) standard KieContainer API or (2) CDI-like injection with Roboguice.
It is possible to use Drools without the drools-compiler dependency, which results in a smaller apk, by pre-serializing the compiled knowledge bases during build-time and then de-serializing them at runtime.
The KieBase must be serialized during build time using kie-maven-plugin.
Example 14.1. Pre-serialized KieBase Maven pom.xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-bom</artifactId>
<version>6.5.0.Final</version>
<type>pom</type>
<scope>import</scope>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-android</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusions>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.kie</groupId>
<artifactId>kie-maven-plugin</artifactId>
<version>6.5.0.Final</version>
<configuration>
<kiebases>
<kiebase>HelloKB</kiebase>
</kiebases>
<resDirectory>${basedir}/src/main/res/raw</resDirectory>
</configuration>
<executions>
<execution>
<id>touch</id>
<goals>
<goal>touch</goal>
</goals>
<phase>initialize</phase>
</execution>
<execution>
<id>compile-kbase</id>
<goals>
<goal>build</goal>
</goals>
<phase>compile</phase>
</execution>
<execution>
<id>serialize</id>
<goals>
<goal>serialize</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
The KieBase must be de-serialized before creating the sessions.
Figure 14.1. Loading serialized KieBase
private class LoadKieBaseTask extends AsyncTask<InputStream, Void, KieBase> {
@Override
protected KieBase doInBackground(InputStream... params) {
try {
logger.debug("Loading knowledge base");
final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages((List<KnowledgePackage>) DroolsStreamUtils.streamIn(params[0]));
return kbase;
}catch(Exception e) {
logger.error("Drools exception", e);
return null;
}
}
}
With the drools-compiler dependency standard KieContainer API can be used. This comes at a cost of a larger apk. To avoid the 65K limit, multidex (or proguard) can be used.
The kie-maven-plugin must be configured to build the kiebase. Multidex must be used to allow for the increased dependencies. There are also some settings for merging various Drools XML files within the apk.
Example 14.2. pom.xml with drools-compiler and multidex
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-bom</artifactId>
<version>6.5.0.Final</version>
<type>pom</type>
<scope>import</scope>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-android</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>xmlpull</groupId>
<artifactId>xmlpull</artifactId>
</exclusion>
<exclusion>
<groupId>xpp3</groupId>
<artifactId>xpp3_min</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.kie</groupId>
<artifactId>kie-maven-plugin</artifactId>
<version>6.5.0.Final</version>
<executions>
<execution>
<id>compile-kbase</id>
<goals>
<goal>build</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.simpligility.maven.plugins</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>4.2.1</version>
<extensions>true</extensions>
<configuration>
<sdk>
<platform>21</platform>
</sdk>
<dex>
<coreLibrary>true</coreLibrary>
<jvmArguments><jvmArgument>-Xmx2048m</jvmArgument></jvmArguments>
<multiDex>true</multiDex>
<mainDexList>maindex.txt</mainDexList>
</dex>
<extractDuplicates>true</extractDuplicates>
<apk>
<metaInf>
<includes>
<include>services/**</include>
<include>kmodule.*</include>
<include>HelloKB/**</include>
<include>drools**</include>
<include>maven/${project.groupId}/${project.artifactId}/**</include>
</includes>
</metaInf>
</apk>
</configuration>
</plugin>
</plugins>
</build>
With Roboguice pre-serialized knowledge bases can be injected using the @KBase annotation.
@KBase supports an optional 'name' attribute. CDI typically does "getOrCreate" when it injects, all injections receive the same instance for the same set of annotations. the 'name' annotation forces a unique instance for each name, although all instances for that name will be identity equals.
The Roboguice module needs to be specified in the manifest.
Example 14.3. Roboguice manifest with pre-serialized knowledge base
<application
android:largeHeap="true"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<meta-data
android:name="roboguice.modules"
android:value="org.drools.android.roboguice.DroolsModule"/>
<activity
android:label="@string/app_name"
android:name="org.drools.examples.android.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
With Roboguice and drools-compiler almost the full CDI syntax can be used to inject KieContainers, KieBases, and KieSessions.
@KContainer, @KBase and @KSession all support an optional 'name' attribute. CDI typically does "getOrCreate" when it injects, all injections receive the same instance for the same set of annotations. the 'name' annotation forces a unique instance for each name, although all instance for that name will be identity equals.
The default argument, if given, maps to the value attribute and specifies the name of the KieBase from the kmodule.xml file.
Figure 14.4. Injects the Default KieBase from the Classpath KieContainer
@Inject
private KieBase kbase;
Figure 14.5. Injects KieBase by name from the Classpath KieContainer
@Inject
@KBase("kbase1")
private KieBase kbase;
@KSession is optional as it can be detected and added by the use of @Inject and variable type inference.
The default argument, if given, maps to the value attribute and specifies the name of the KieSession from the kmodule.xml file
Figure 14.6. Injects the Default KieSession from the Classpath KieContainer
@Inject
private KieSession ksession;
Figure 14.7. Injects StatelessKieSession by name from the Classpath KieContainer
@Inject
@KSession("ksession1")
private KieSession ksession;
@KSession is optional as it can be detected and added by the use of @Inject and variable type inference.
The default argument, if given, maps to the value attribute and specifies the name of the KieSession from the kmodule.xml file.
Figure 14.8. Injects the Default StatelessKieSession from the Classpath KieContainer
@Inject
private StatelessKieSession ksession;
Figure 14.9. Injects StatelessKieSession by name from the Classpath KieContainer
@Inject
@KSession("ksession1")
private StatelessKieSession ksession;
The Roboguice module needs to be specified in the manifest.
Example 14.4. Roboguice manifest configuration
<application
android:largeHeap="true"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<meta-data
android:name="roboguice.modules"
android:value="org.drools.android.roboguice.DroolsContainerModule"/>
<activity
android:label="@string/app_name"
android:name="org.drools.examples.android.SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>