Q:

How to use drools in grails3 without any plugin?

Is it possible to use drools rule engine in GRAILS3 without any plugin installation? I ask that because I know drools is implemented in java and  actual official plugin by Ken Siprell for GRAILS is (apparently) no more working.

A:

After much investigation and many attempts, I got a small GRAILS3 API service through which it is possible to process data using DROOLS engine without any plugin. All that is possible because DROOLS is based on java and because of perfect compatibility between GRAILS and Java. 
All you need is the following:

include minimal DROOLS dependency in build.gradle
choose a folder to store files.drl 
have some entities to use as facts to process (not mandatory to persist them, so I skip hibernate configuration)
implement a service to build rule base knowledge and to get a session
implement some methods into API controller to process data through DROOLS (having got its session from service)

Below there is a simple example of all that:
DROOLS dependencies (in build.gradle):
runtime "org.drools:drools-compiler:6.5.0.Final"
compile "org.drools:drools-core:6.5.0.Final"
compile "org.drools:knowledge-api:6.5.0.Final"

DRL storage in src/rules (reference to this path will be in the service, see below): myrules.drl
import my.entities.Book;
import java.util.List;

rule "Find author"
   salience 10
   when
    $book: Book( author=="Shakespeare" )
   then
    System.out.println("Book found, date:"+$book.getDate0());
end

Some entity, for example Book:
package my.entities
import java.util.Date

class Book {
    String title, author
    Date date0
}

Service to build DROOLS knowledge and get session (I prepared a stateless engine, lighter than the stateful one):
package my.services
import grails.converters.*

import org.kie.api.runtime.*;
import org.kie.internal.io.ResourceFactory;
import org.kie.api.*;
import org.kie.api.io.*;
import org.kie.api.builder.*;

class DroolsService  {

def getSession() {
        def path    = "src/rules"
        def lru = ["myrules.drl"]
        def rules   = []
        lru.each{
            rules.add("${path}${it}")
        }
        StatelessKieSession ksess   = buildSession(rules)
        return ksess
    }
}

private buildSession(def lfile) {
    println "Building DROOLS session..."
    try {
        def lres    = []
        lfile.each{
            Resource resource   = ResourceFactory.newFileResource(new File(it));
            lres.add(resource)
        }

        KieContainer kieContainer = buildKieContainer(lres)
        StatelessKieSession kieSession = kieContainer.newStatelessKieSession()
        return kieSession
    } catch(Exception e) {
        e.printStackTrace()
        return null
    }

protected KieContainer buildKieContainer(def lres) {
    KieServices kieServices = KieServices.Factory.get()
    KieFileSystem kieFileSystem = kieServices.newKieFileSystem()
    lres.each{
        kieFileSystem.write("src/main/resources/rule.drl", it)  
    }

    KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll()
    Results results = kieBuilder.results
    if (results.hasMessages(Message.Level.ERROR)) {
        throw new IllegalStateException(this.class.name + ": " + results.messages.toString())
    }
    KieContainer kieContainer = kieServices.newKieContainer(kieServices.repository.defaultReleaseId)
    kieContainer
}

}

And use of service in API controller:
class ApiController  {

def droolsService

def proc = {
    def sess    = droolsService.getSession()

    def mess    = "ok DROOLS proc from JSON"
    Book book   = null

    if (params.contbook) {
        book = new Book(JSON.parse(params.contbook))
        sess.execute book
    } 

    response.status  = 200 
    render mess
}

In the controller I take json data from parameter and populate an entity by them, in order to execute it with the rule engine initialised by the DROOLS service. Of course this is a very simple solution, but it is working. 
Some notes:

the RHS part of each drl rule (after "then") must be java, so, as  in the example, you cannot access directly private property of the entity but you have to use a getter or setter (implicitly created by GRAILS)
getSession create a new build of the knowledge and a new session and that is not optimal, you may redesign it in order to store a DROOLS session and then reuse it through a user session
you can have several files.drl in the same folder and then you have to list them all in the service in order to pack them in the knowledge engine

Hope all that is useful.

