KieBase.getFactType throws UnsupportedOperationException with a class created in Workbench

371 views
Skip to first unread message

Ronak Patel

unread,
Nov 13, 2014, 1:52:58 PM11/13/14
to drools...@googlegroups.com
Using the KIE API 6.1.0.Final. The following call throws an UnsupportedOperationException:

FactType poReqType = kBase.getFactType("com.hp.pa.sample.po", "PoRequest");

kBase is a valid org.kie.api.KieBase and com.hp.pa.sample.po.PoRequest is a simple class created using the Drools Workbench 6.1 data modeler. Yet, this call results in the following exception:

java.lang.UnsupportedOperationException: KieBase.getFactType should only be used to retrieve declared beans. Class com.hp.pa.sample.po.PoRequest exists outside DRL.

Executing this exact same code using the KIE API 6.0.1.Final with no other changes works fine with no exceptions or other problems, even when the data model and rules are created using the 6.1 Workbench.

Any ideas on why this doesn't work in the new version? I'm thinking this is this a regression in 6.1.0.Final.

Thanks.

Davide Sottara

unread,
Nov 13, 2014, 7:33:34 PM11/13/14
to drools...@googlegroups.com
This was debated in response to a JIRA ticket (I'll try to find it later).
The "getFactType" can now ONLY be used to access *declared DRL types*.
The workbench creates full-fledged java classes, available at compile time.
You can use those classes directly, or worst case use normal java reflection.

In 6.0.1 you could indeed retrieve the class definition even for non-declared types,
but that was (necessarily) a partial and inconsistent definition, so we decided
to prevent it from being used.

Please let us know if there is a use case that is not covered and we may revisit
the decision
Thanks
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/a7e2d594-1c72-4247-a98f-25e140e99511%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Bill T

unread,
Jan 16, 2015, 12:56:18 PM1/16/15
to drools...@googlegroups.com
I am in a similar situation with some code I am developing. I am getting the same exception. I have a Java class/model that I am using as a base class and trying to extend in a .drl file that is compiled and used at run-time. However, I am seeing what I think is conflicting information regarding support of this functionality and I would like some clarification. This link to 6.1.0.Final documentation seems to indicate that we can extend a Java Model in a DRL file, yet the exception and the response below indicate otherwise.  Please provide some clarity.

Bill T

unread,
Jan 16, 2015, 12:58:03 PM1/16/15
to drools...@googlegroups.com

--
You received this message because you are subscribed to a topic in the Google Groups "Drools Usage" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/drools-usage/9MfVYmUANtQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to drools-usage...@googlegroups.com.

To post to this group, send email to drools...@googlegroups.com.

Davide Sottara

unread,
Jan 16, 2015, 5:04:42 PM1/16/15
to drools...@googlegroups.com
The documentation talks about "declared types" - that is, classes defined implicitly inside the DRL using the "declare" construct.
The classes created using the data modeller in the workbench are not "declares", but full java source files compiled into java classes.
You will have them available at compile time (unlike the "declares", which are only available at runtime - hence the need for the FactType API):
is there any specific reason why you need to call getFactType?

Previously, the getFactType API did allow to retrieve both native and declared class types, but for the former the resulting information was
partial and could lead to worse exceptions. Hence the decision to restrict the API functionality.
That may be undone, but it would require a strong use case.

Feel free to ask for more clarifications
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.

Bill T

unread,
Jan 16, 2015, 6:45:06 PM1/16/15
to drools...@googlegroups.com
I have an application that completely wraps the drools run-time. The code creates rules, compiles them and manages the run-time.  Currently I am using statically defined Java classes for events.  I am trying to develop some dynamically created events that use a Java Class as its base to be as efficient as possible in terms of memory usage. I have a database with several thousand columns, I would like to provide functionality that would allow the selection of a subset of columns in a set of tables and persist rules facts based on the selection.  So, I would like to dynamically create the event rules, the reason rules,  populate events and insert them using Java.  The reasoning rules would use the getters and setters while the insertion code would use the FactType API.  I almost had a prototype working in 6.0.1.Final.  I ran into a couple of inconsistencies, namely the FactType.getField() API call was not returning the FieldDefinition for one ArrayList and one HashSet field from my Java base class. I moved up to 6.1.0.Final and hit the UnsupportedOperationException exception outlined in this post.


On Thursday, November 13, 2014 at 10:52:58 AM UTC-8, Ronak Patel wrote:

Davide Sottara

unread,
Jan 16, 2015, 7:31:47 PM1/16/15
to drools...@googlegroups.com
"statically defined" java classes should be available through normal java reflection, if you can't use them at compile time.
Would this work for you?

--
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.

Bill T

unread,
Jan 16, 2015, 7:44:47 PM1/16/15
to drools...@googlegroups.com
Sorry, if I was not clear. I have statically defined Java classes, that I would like to extend dynamically in rules based on a columns from data base tables that are user selectable. The intention of this approach is to be very flexible and efficiently use memory in drools.


On Thursday, November 13, 2014 at 10:52:58 AM UTC-8, Ronak Patel wrote:

Davide Sottara

unread,
Jan 16, 2015, 7:50:39 PM1/16/15
to drools...@googlegroups.com
Oh I see, the data modeler issue was reported by another user.
I am not completely sure what you mean by "extend a class dynamically in rules".. are you generating DRL "declares" on the fly?

If your classes are "declared" inside DRL, the FactType API should work regardless of whether they extend other classes or not.
That is, you should be able to use getFactType with no exception, and you should be able to access all the fields there.
If you are having issues with this, it may be a bug and a detailed description / reproducer would be appreciated to fix it
Thanks
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.

Bill T

unread,
Jan 16, 2015, 8:20:24 PM1/16/15
to drools...@googlegroups.com
Yep, I am generating DRL files, compiling compiling them and adding them to the container - on the fly.  I am trying to use 'extends' in my generated DRL to extend the imported static base class.

Let me see if I can put together a small set of code to reproduce the issue.  


On Thursday, November 13, 2014 at 10:52:58 AM UTC-8, Ronak Patel wrote:

A. Craig West

unread,
Nov 25, 2015, 3:30:13 PM11/25/15
to Drools Usage
On Friday, 16 January 2015 19:50:39 UTC-5, Davide Sottara wrote:
Oh I see, the data modeler issue was reported by another user.
I am not completely sure what you mean by "extend a class dynamically in rules".. are you generating DRL "declares" on the fly?

If your classes are "declared" inside DRL, the FactType API should work regardless of whether they extend other classes or not.
That is, you should be able to use getFactType with no exception, and you should be able to access all the fields there.
If you are having issues with this, it may be a bug and a detailed description / reproducer would be appreciated to fix it
Thanks
Davide

Hi, I am trying to switch my Drools engine to Drools 6.3 from 5.5, andf am running across this error. Like the original poster, I am building Drools type dynamically with DRL, with a POJO base class. An example definition is:
declare Drools_applications extends ProfileSettingGroup

    drools_app_external : String
    drools_lc_app_external : String
    drools_app_memory : String
    drools_numeric_app_memory : double
    drools_app_package : String
    drools_lc_app_package : String
    drools_app_cache_storage : String
    drools_numeric_app_cache_storage : double
    drools_app_icon_url : String
    drools_lc_app_icon_url : String
    drools_app_version : String
    drools_lc_app_version : String
    drools_app_name : String
    drools_lc_app_name : String
    drools_app_system : String
    drools_lc_app_system : String
    drools_app_vcode : String
    drools_numeric_app_vcode : double
    drools_app_total_storage : String
    drools_numeric_app_total_storage : double
    drools_app_data_storage : String
    drools_numeric_app_data_storage : double
    drools_app_code_storage : String
    drools_numeric_app_code_storage : double
    drools_app_status : String
    drools_lc_app_status : String
end

In this case, ProfileSettingGroup is a POJO that has methods used in the DRL.

My code uses getFactType and newInstance to create facts to insert. While it is possible to use reflection, my code has not been doing so, and I really am not looking forwards to rewriting my code base to deal with this.
 

Mark Proctor

unread,
Nov 25, 2015, 4:23:25 PM11/25/15
to drools...@googlegroups.com
--
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.

A. Craig West

unread,
Nov 30, 2015, 3:20:28 PM11/30/15
to Drools Usage
It turns out that the exception is relatively valid, in that I was using an empty declare section for the POJO, which would result in this exception, I think. I believe the reason I had the empty declare section was due to another bug. It appears to use the extends keyword to extend a class, unless that class is declared in the same package as drl is declared with.

Davide Sottara

unread,
Nov 30, 2015, 3:49:13 PM11/30/15
to drools...@googlegroups.com
The distinction between "bug" and "feature" is subtle here :)

The problem is that the behavior has evolved over years, but the need to be backward compatible has made the semantics
of "declare" possibly ambiguous. The goal is to fix it in the next major release with a new, improved system.

I would still like to see a full reproducer, because in general there are explicit workarounds to obtain a desired behavior.

A. Craig West

unread,
Dec 2, 2015, 7:04:26 PM12/2/15
to Drools Usage
I managed to reproduce the failure again. It appears that the empty declare section is used as a placeholder, because otherwise it is not possible to subclass a POJO that is not in the same package as the new fact type.
So far I am reproducing it in a fairly minimal set of classes, but not a test case yet.
The important elements to reproduce are:
1) The types are declared in a separate package and drl from the rules. If they are in the same package it works. Unfortunately, I need to be able to create separate packages for the rules, so this doesn't help me.
The type name seems to be important, but can't be the only factor. On my production system both the names Drools_root and Drools_applications fails, while in my test case, Drools_root (and Drools_root_applications) work, but Drools_applications still fails. This happens even when the types are reduced to a bare minumum:
The POJO (com/foobar/rules/BaseClass.java):
package com.foobar.rules;

public class BaseClass {
}

The declaration DRL Sample2.drl):
package com.foobar.rules

import com.foobar.rules.BaseClass;

declare Drools_applications extends BaseClass
    drools_app_name : String
end

declare Drools_root_applications extends BaseClass
    drools_app_name : String
end

The rules DRL (Sample_rules.drl):
package com.sample

rule "R2"
    when
        $app : com.foobar.rules.Drools_applications( drools_app_name != "" )
    then
        System.out.println( "rule: R2" );
        System.out.println( $app.getDrools_app_name() );
end

rule "R3"
    when
        $root : com.foobar.rules.Drools_root_applications( drools_app_name != "" )
    then
        System.out.println( "rule: R3" );
        System.out.println( $root.getDrools_app_name() );
end


The code to create the KnowledgeBase:
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("Sample2.drl"), ResourceType.DRL);
        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());

        KnowledgeBuilder kbuilder2 = KnowledgeBuilderFactory.newKnowledgeBuilder(kbase);
        kbuilder2.add(ResourceFactory.newClassPathResource("Sample_rules.drl"), ResourceType.DRL);
        // This line may not be necessary
        kbase.addKnowledgePackages(kbuilder2.getKnowledgePackages());

The code to trigger the exception
            FactType rootType = kbase.getFactType("com.foobar.rules", "Drools_root_applications"); // No exception
            Object root = rootType.newInstance();
            rootType.set(root, "drools_app_name", "1");
            ksession.insert(root);
            FactType test2Type = kbase.getFactType("com.foobar.rules", "Drools_applications"); // Exception HERE!!!!!
            Object test2 = test2Type.newInstance();
            test2Type.set(test2, "drools_app_name", "appName");
            ksession.insert(test2);
            ksession.fireAllRules();
reproducer.zip

Mark Proctor

unread,
Dec 2, 2015, 10:02:55 PM12/2/15
to drools...@googlegroups.com
--
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.

For more options, visit https://groups.google.com/d/optout.
<reproducer.zip>

A. Craig West

unread,
Dec 3, 2015, 5:32:10 PM12/3/15
to Drools Usage
I am trying to convert the code I posted earlier to use the Kie api, but it is a pain. Is there any good reason why incrementalBuild isn't available in KieBuilder? I find it hard to believe that the use case of a large, continuously updated rule knowledgebase isn't fairly common, but the new API's seem to treat it as a fringe case with very little support...

A. Craig West

unread,
Dec 3, 2015, 6:33:19 PM12/3/15
to Drools Usage
I have a partial pull request: https://github.com/droolsjbpm/drools/pull/575
This replicates my issue with extending a POJO in a different package from the fact type, and includes a non-incremental version of the code that throws the UnsupportedOperationException. This version does not do it incrementally, so it does not throw the exception, but seems a valid test case


On Wednesday, 2 December 2015 22:02:55 UTC-5, Mark Proctor wrote:

A. Craig West

unread,
Dec 4, 2015, 5:24:20 PM12/4/15
to Drools Usage
I have updated the code in the pull request. There are now three failing tests. If I use the Drools 6 API with incrementalBuild instead of using the KnowledgeBuilder API, it works.
There are now 3 tests that fail:
testDeclarationWithPojoExtensionMultiplePackages, which is the failure I started with;
testDeclarationWithPojoExtensionDifferentPackage, which is an error extending a POJO in a different package;
testDeclarationWithPojoExtension, where setting a property from the POJO through the FactType doesn't work, although it IS a bean. I don't know if that should work or not, though. Even if it shouldn't work, I would expect it to fail with an error instead of failing silently

Should I create drools Jira tickets for each of these?

rea.a...@gmail.com

unread,
Jul 25, 2017, 10:32:47 AM7/25/17
to Drools Usage
Hello,

I am seeing that it has been a while since you have last posted for this issue, however I will give it a shot.

I am currently using Drools 7 and I am facing the error that was initially mentioned in this post. In order to solve this I have used declared types in order to define my facts.
But, I was wondering if there is any way that a fact that is defined using the Data modeller to be identified as a declared type and to be retrieved when KieBase.getFactType() method is used.
Has anyone managed to do something similar?

I would like to use the functionality that is available through Data modeller as it is more user friendly for business users but also for those facts to be available at the rule engine.

Thanks.
Reply all
Reply to author
Forward
0 new messages