Proper use of Enums without backing Java classes

1,497 views
Skip to first unread message

sascha.s...@signavio.com

unread,
Feb 27, 2015, 10:31:17 AM2/27/15
to drools...@googlegroups.com
Hey *,

I am currently trying to programmatically export Decision Tables (out of a JSON based diagram format, not CSV or Excel) into DRL.
I am using the fluent API

One issue I am currently facing is how to handle Enums.

I created a simple example table, which looks like this:

Table Name: Enums
Input: Status (Enum, values are VIP, IP, NIP)
Display: String

         Status                         Display
elementOf(VIP, IP)              "Important Person"
notElementOf(VIP, IP)         "Not an Important Person"

I actually have two questions:

1.: How do I use Enums properly inside the DRL? My generated DRL is not working and looks as follows:

package com.signavio.drools 

declare Enums 

    status : Enum  
    display : String  

end


rule "enums_Rule_1"
    no-loop 
when
    $enums : Enums(  )  
then
    modify( $enums ){ 
        setDisplay("Important Person") 
    };
end

rule "enums_Rule_2"
    no-loop 
when
    $enums : Enums( status != "VIP", status != "IP" )  
then
    modify( $enums ){ 
        setDisplay("Not an Important Person") 
    };
end



2. How do I actually set a value to test my rules when I have no classes to back the enum up. Let's say at this point I have no choice but not to use backing classes. Here's the Code:


public void thatEnumsAreHandledCorrectly(String input, String expected) throws Exception {

KnowledgeBuilder knowledgeBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
knowledgeBuilder.add(ResourceFactory.newFileResource(drlFile), ResourceType.DRL);
KieBase knowledgeBase = knowledgeBuilder.newKnowledgeBase();
KieSession session = knowledgeBase.newKieSession();
FactType enums = knowledgeBase.getFactType("com.signavio.drools", "Enums");
Object enumObject = enums.newInstance();
enums.set(enumObject, "status", input);
session.insert(enumObject);
session.fireAllRules();
String result = (String) enums.get(enumObject, "display");
assertEquals(result, expected)
;
session.dispose();
}


Is there any way I can achieve this? I am also glad for pointers to the right documentation.

Thanks!

- Sascha

sascha.s...@signavio.com

unread,
Mar 2, 2015, 4:48:34 AM3/2/15
to drools...@googlegroups.com
Maybe I can rephrase my question a little:

How do I define an Enum in DRL?

Something like

declare enum Status
    VIP
    IP
    NIP
end

declare Enums
    status
: Status
    display
: String
end


so that I can then use it in my rules like so

when
    $enums : Enums(status == Status.VIP or status == Status.IP )

then
    modify( $enums ){
        setDisplay
("Important Person")
   
};
end

Can I do this? And if so, how would I do this correctly? I do not have the option to create a backing Java class.

Thanks!

- Sascha

Davide Sottara

unread,
Mar 2, 2015, 6:36:29 AM3/2/15
to drools...@googlegroups.com
Comma-separated values, with a semicolon at the end.

declare enum Status
   VIP, IP, PIP;
end

Simple args are supported too, using the classic declare style

declare enum Status
   VIP( "Vip" ), IP( "Imp" );

   descr : String
end

Hope this helps
Davide


--
You received this message because you are subscribed to the Google Groups "Drools Usage" group.
To unsubscribe from this group and stop receiving emails from it, send an email to drools-usage...@googlegroups.com.
To post to this group, send email to drools...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/drools-usage/aa33712a-3404-45cd-8f9f-eb1ef6664cb8%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

sascha.s...@signavio.com

unread,
Mar 2, 2015, 7:47:52 AM3/2/15
to drools...@googlegroups.com
Hi Davide,

thanks, that already helped quite a bit. Weirdly, IntelliJ gives me two errors on your code:

1. it underlines VIP (cannot resolve)
2. it underlines end (unexpected)

Now still assuming I don't have Java Classes, I need to test that my rules are correct by firing them with the code from the first post.

How would I set the Enum.status to VIP correctly in Java?
This obviously won't work as a String cannot be cast into an Enum:

enums.set(enumObject, "status", "Status.VIP");

I also tried this:

FactType status = knowledgeBase.getFactType("com.signavio.drools", "Status");
Object statusObject = status.newInstance();
Object VIPStatus = status.get(statusObject, "VIP");
....
enums
.set(enumObject, "status", VIPStatus);

But I am getting a java.lang.InstantiationException: com.signavio.drools.Status

How would I go about doing this?

Thanks so much!

- Sascha

Davide Sottara

unread,
Mar 2, 2015, 7:53:50 AM3/2/15
to drools...@googlegroups.com
the Drools IntelliJ plugin (a 3rd party plugin) is likely not up to date, and won't recognize valid DRL files.

Second, Drools creates valid enums, so you can use e.g. valueOf(...). There is no "reflective" method
for enums in FactType, though, so you may need some reflection

sascha.s...@signavio.com

unread,
Mar 2, 2015, 8:02:00 AM3/2/15
to drools...@googlegroups.com
Does that mean I'd have to dynamically create it at runtime for my test?

Could you possibly give me a simple example?

Thanks! 

Mark Proctor

unread,
Mar 2, 2015, 9:15:09 AM3/2/15
to drools...@googlegroups.com
patterns match objects, what ever you insert will be matched. Enums are just objects, once instantiated. Although i wouldn’t recommend you use Enums as facts, they really should just be used as properties in other classes.

There must be a class or interface for any Pattern type you wish to match.

Mark

Mark Proctor

unread,
Mar 2, 2015, 1:12:08 PM3/2/15
to drools...@googlegroups.com
I’d actually recommend you stick with java classes, probably easier. We encapsulate all the user objects and rules inside of a kjar, and that is now the unit of deployment.

Lots of examples here, and each is documented. It shows how to dynamically load a jar - that contains your models and rules:
On 2 Mar 2015, at 13:02, sascha.s...@signavio.com wrote:

sascha.s...@signavio.com

unread,
Mar 3, 2015, 5:36:42 AM3/3/15
to drools...@googlegroups.com
Hi Mark,

thanks for your reply.
My problem is I can't instantiate an Enum. 

I got it to work now (for the sake of my test) by providing the Enum as Java class and it worked.
Now I have to figure out how to declare the Enum in the DRL using the Fluent API. There is an enumerative builder, but so far I had no luck.

My code looks like this:
@Test
public void enumDeclaration() {
   
PackageDescrBuilder packageBuilder = DescrFactory.newPackage();
    packageBuilder
.name("com.test");
    packageBuilder
.newDeclare()
           
.enumerative().name("Status")
               
.newEnumLiteral("VIP").end()
               
.newEnumLiteral("IP").end()
               
.newEnumLiteral("NIP").end()
           
.end();
    packageBuilder
.newRule().end();
   
DrlDumper dumper = new DrlDumper();
   
System.out.println(dumper.dump(packageBuilder.getDescr()));
}


But unfortunaly it only outputs this:


package com.test 

rule "null"
when
then
end

What am I doing wrong?

Thanks so much!

- Sascha

Davide Sottara

unread,
Mar 3, 2015, 11:08:36 AM3/3/15
to drools...@googlegroups.com
Looks like a bug, which version are you using again?

sascha.s...@signavio.com

unread,
Mar 3, 2015, 11:16:02 AM3/3/15
to drools...@googlegroups.com
I'm on 6.1.0 Final

Davide Sottara

unread,
Mar 3, 2015, 11:59:17 AM3/3/15
to drools...@googlegroups.com
it works in master / 6.2, it was a bug fixed more recently than 6.1

Message has been deleted

Davide Sottara

unread,
Mar 4, 2015, 3:43:40 AM3/4/15
to drools...@googlegroups.com
There were two bugs associated to enums. One is just relative to the DrlDumper: the package would contain the declared enum, it would simply not printed by the dumper.
The other was related to the loading of an enum from a package into an existing KieBase.

Only the latter would prevent the actual use of enums (you can pass a packageDescr to a KieBase directly, without passing from the DRL), but I don't remember when
either was fixed

On Wed, Mar 4, 2015 at 1:40 AM, <sascha.s...@signavio.com> wrote:
So I could use 6.2.0.CR4 to test it?

Problem is that our client is working with 6.1, so I may have to work around.

Thanks for the hint!

sascha.s...@signavio.com

unread,
Mar 4, 2015, 5:32:02 AM3/4/15
to drools...@googlegroups.com
Ok thanks.
I used 6.2.0 CR4 and it worked to generate the DRL correctly.
Now it seems that the API has changed a bit though, so for this line 

knowledgeBuilder.add(ResourceFactory.newFileResource(outputFile), ResourceType.DRL);

I am getting the following exception:

java.lang.NoSuchMethodError: org.kie.internal.builder.conf.LanguageLevelOption.useJavaAnnotations()Z
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.normalizeTypeDeclarationAnnotations(KnowledgeBuilderImpl.java:2203)
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.mergePackage(KnowledgeBuilderImpl.java:1489)
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.addPackage(KnowledgeBuilderImpl.java:890)
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.addPackageFromDrl(KnowledgeBuilderImpl.java:433)
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.addKnowledgeResource(KnowledgeBuilderImpl.java:653)
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.add(KnowledgeBuilderImpl.java:2164)
at org.drools.compiler.builder.impl.KnowledgeBuilderImpl.add(KnowledgeBuilderImpl.java:2153)
at com.signavio.droolsexport.integration.DiagramToDRLEndToEndTest.thatEnumsAreHandledCorrectly(DiagramToDRLEndToEndTest.java:188)

Where would I find the documentation for this version so I can load the file correctly?

Thanks,

- Sascha

sascha.s...@signavio.com

unread,
Mar 4, 2015, 5:39:07 AM3/4/15
to drools...@googlegroups.com
Forgot to mention, the DRL is the end product that I have to deliver. Everything else (the whole java stuff) is just to test the validity of the rules and the DRL.
So the DRL is essential, but so are the tests.


On Wednesday, March 4, 2015 at 9:43:40 AM UTC+1, Davide Sottara wrote:

Davide Sottara

unread,
Mar 4, 2015, 7:41:44 PM3/4/15
to drools...@googlegroups.com
Did you update the version of kie-api too?

sascha.s...@signavio.com

unread,
Mar 5, 2015, 5:26:31 AM3/5/15
to drools...@googlegroups.com
I completely forgot that. Updating the kie-api and kie-internal to the same version as drools solved my issue.
Still can't instantiate an enum from a DRL using FactType though (I suppose this is expected behaviour?}

Mark Proctor

unread,
Mar 5, 2015, 8:45:04 AM3/5/15
to drools...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages