[rules-users] NullPointerException when using Drools rule template
Wolfgang Laun
wolfgang.laun at gmail.com
Thu Nov 11 03:56:14 EST 2010
[Note: I see that template parsing is rather wobbly. The JIRA has to
be fixed in
org.drools.template.parser.DefaultTemplateContainer, and I think there are other
"holes" in the parseTemplate method.]
Roger,
while my previous suggestion avoids the NPE, it may not be the
adequate solution for your situation. I see that you have several
rules which classify ContractRule w.r.t. season and hourType. These do
not rely on template parameters, and they would be better off in a
separate simple .drl file.
Now let's look at your reduced original template
template contract_rate
rule "Summer on peak primary rate"
when
$r : ContractRule( season == "summer" && hourType == "onPeak" &&
type == "primary")
then
$r.setRate(@{summerOnPeakPrimaryRate});
end
end template
>From the other parameter names I can imagine that you have similar
hand-written rules for all
other combinations of these three field values; templating is just
used to insert the rate values
programmatically rather than hand-coded. (I suppose good old
properties would solve this task
quite well!)
But templating may be used to save you the trouble of writing and
maintaining all the set-rate
rules themselves. (Just imagine of the Contractor comes up with the
notion of adding a rebate
for groups: You'll have to double your rules manually!)
Here's the template to achieve everything with a single rule:
template header
theSeason
theHour
theType
theRate
package resource
import resource.ContractRule
template contract_rate
rule "@{theSeason} @{theHour} @{theType} rate" ### DO NOT INDENT
THIS LINE. ARRGH!
when
$r : ContractRule( season == "@{theSeason}" && hourType ==
"@{theHour}" && type == "@{theType}")
then
$r.setRate(@{theRate});
end
end template
Now you'll have to use more than one parameter map - one for each such
combination. [[Aside: Adding
the "group" rebate can be done by
* adding the template parameter,
* adding the restriction to the template rule
* extending the rule name
* extend addParamMap
* write the additional addParamMap() calls ]]
Collection<Map<String,Object>> paramMaps = new ArrayList<Map<String,Object>>();
private void addParamMap( String season, String hour, String type, int rate ){
Map<String,Object> params = new HashMap<String,Object>();
params.put( "theSeason", season );
params.put( "theHour", hour );
params.put( "theType", type );
params.put( "theRate", rate );
paramMaps.add( params );
}
addParamMap( "summer", "onPeak", "primary", 299 );
addParamMap( "summer", "onPeak", "secondary", 524 );
addParamMap( "summer", "semiPeak", "primary", 176 );
addParamMap( "summer", "semiPeak", "secondary", 305 );
addParamMap( "summer", "offPeak", "primary", 139 );
addParamMap( "summer", "offPeak", "secondary", 243 );
addParamMap( "winter", "onPeak", "primary", 249 );
addParamMap( "winter", "onPeak", "secondary", 438 );
addParamMap( "winter", "semiPeak", "primary", 176 );
addParamMap( "winter", "semiPeak", "secondary", 305 );
addParamMap( "winter", "offPeak", "primary", 139 );
addParamMap( "winter", "offPeak", "secondary", 243 );
String drl = converter.compile(paramMaps, dis);
And here we go: This is the generated DRL text:
package resource
import resource.ContractRule
rule "winter offPeak secondary rate"
when
$r : ContractRule( season == "winter" && hourType == "offPeak" &&
type == "secondary")
then
$r.setRate(243);
end
rule "winter offPeak primary rate"
when
$r : ContractRule( season == "winter" && hourType == "offPeak" &&
type == "primary")
then
$r.setRate(139);
end
rule "winter semiPeak secondary rate"
when
$r : ContractRule( season == "winter" && hourType == "semiPeak" &&
type == "secondary")
then
$r.setRate(305);
end
rule "winter semiPeak primary rate"
when
$r : ContractRule( season == "winter" && hourType == "semiPeak" &&
type == "primary")
then
$r.setRate(176);
end
rule "winter onPeak secondary rate"
when
$r : ContractRule( season == "winter" && hourType == "onPeak" &&
type == "secondary")
then
$r.setRate(438);
end
rule "winter onPeak primary rate"
when
$r : ContractRule( season == "winter" && hourType == "onPeak" &&
type == "primary")
then
$r.setRate(249);
end
rule "summer offPeak secondary rate"
when
$r : ContractRule( season == "summer" && hourType == "offPeak" &&
type == "secondary")
then
$r.setRate(243);
end
rule "summer offPeak primary rate"
when
$r : ContractRule( season == "summer" && hourType == "offPeak" &&
type == "primary")
then
$r.setRate(139);
end
rule "summer semiPeak secondary rate"
when
$r : ContractRule( season == "summer" && hourType == "semiPeak" &&
type == "secondary")
then
$r.setRate(305);
end
rule "summer semiPeak primary rate"
when
$r : ContractRule( season == "summer" && hourType == "semiPeak" &&
type == "primary")
then
$r.setRate(176);
end
rule "summer onPeak secondary rate"
when
$r : ContractRule( season == "summer" && hourType == "onPeak" &&
type == "secondary")
then
$r.setRate(524);
end
rule "summer onPeak primary rate"
when
$r : ContractRule( season == "summer" && hourType == "onPeak" &&
type == "primary")
then
$r.setRate(299);
end
-W
2010/11/10 Roger Smith <rogersmith1711 at gmail.com>:
> Wolfgang -
> Thank you!!
>
> On Wed, Nov 10, 2010 at 11:07 AM, Wolfgang Laun <wolfgang.laun at gmail.com>
> wrote:
>>
>> If you move the
>> template contract_rate
>> up in front of the first rule "holiday july 4th" the NPE is gone. I
>> haven't been able to validate the (presumably) generated rule set, but
>> you should be able to do that now.
>>
>> Nevertheless, this warrants a JIRA, which I'll create forthwith. Also,
>> the docs should indicate what is permitted up front, preceding the
>> "template" statement.
>>
>> -W
>>
>>
>> 2010/11/10 Roger Smith <rogersmith1711 at gmail.com>:
>> > Wolfgang,
>> >
>> > I have enclosed the template. For debugging purpose, I have removed all
>> > but
>> > one rule.
>> >
>> > Thanks,
>> >
>> > Roger
>> >
>> > - O -
>> >
>> > template header
>> > summerOnPeakPrimaryRate
>> > summerOnPeakSecondaryRate
>> > summerSemiPeakPrimaryRate
>> > summerSemiPeakSecondaryRate
>> > summerOffPeakPrimaryRate
>> > summerOffPeakSecondaryRate
>> > winterOnPeakPrimaryRate
>> > winterOnPeakSecondaryRate
>> > winterSemiPeakPrimaryRate
>> > winterSemiPeakSecondaryRate
>> > winterOffPeakPrimaryRate
>> > winterOffPeakSecondaryRate
>> >
>> > package tradex.contract.sde
>> >
>> > import tradex.process.ruler.server.ContractRule
>> >
>> > rule "holiday july 4th"
>> > when
>> > $r : ContractRule( year == 2010 && month == 7 && day == 4 && holiday
>> > ==
>> > false)
>> > then
>> > modify($r){
>> > setHoliday(true)
>> > }
>> > end
>> >
>> > rule "holiday xmas"
>> > when
>> > $r : ContractRule( year == 2010 && month == 12 && day == 25 && holiday
>> > ==
>> > false)
>> > then
>> > modify($r){
>> > setHoliday(true)
>> > }
>> > end
>> >
>> > rule "Season summer"
>> > when
>> > $r : ContractRule( dayOfYear >= 121 && dayOfYear <= 273 && season ==
>> > "undefined")
>> > then
>> > modify($r){
>> > setSeason("summer")
>> > }
>> > end
>> >
>> > rule "Season winter"
>> > when
>> > $r : ContractRule( (dayOfYear >= 274 || dayOfYear <= 120) && season ==
>> > "undefined")
>> > then
>> > modify($r){
>> > setSeason("winter")
>> > }
>> > end
>> >
>> >
>> > rule "On peak hour"
>> > when
>> > $r : ContractRule( holiday == false && dayOfWeek >= 1 && dayOfWeek <=
>> > 6
>> > && hourOfDay >= 1400 && hourOfDay <= 2000 &&
>> > hourType == "undefined")
>> > then
>> > modify($r){
>> > setHourType("onPeak")
>> > }
>> >
>> > end
>> >
>> > rule "Semi peak hour"
>> > when
>> > $r : ContractRule( holiday == false && dayOfWeek >= 1 && dayOfWeek <=
>> > 6
>> > && (hourOfDay >= 600 && hourOfDay < 1400 ||
>> > hourOfDay > 2000 && hourOfDay <= 2200) && hourType == "undefined")
>> > then
>> > modify($r){
>> > setHourType("semiPeak")
>> > }
>> > end
>> >
>> > rule "Off peak hour"
>> > when
>> > $r : ContractRule( (holiday == true || dayOfWeek == 7 || hourOfDay <
>> > 600
>> > || hourOfDay > 2200) && hourType == "undefined" )
>> > then
>> > modify($r){
>> > setHourType("offPeak")
>> > }
>> > end
>> >
>> > template contract_rate
>> > rule "Summer on peak primary rate"
>> > when
>> > $r : ContractRule( season == "summer" && hourType == "onPeak" &&
>> > type ==
>> > "primary")
>> > then
>> > $r.setRate(@{summerOnPeakPrimaryRate});
>> > end
>> > end template
>> >
>> >
>> >
>> >
>> > 2010/11/9 Wolfgang Laun <wolfgang.laun at gmail.com>
>> >>
>> >> Seeing the template .drl would help to resolve this. Are all
>> >> @{parameter}s
>> >> declared in the template header?
>> >> -W
>> >>
>> >> 2010/11/9 Roger Smith <rogersmith1711 at gmail.com>
>> >>>
>> >>>
>> >>> All -
>> >>>
>> >>> I tried out Drools rule template with a with a proptotype app. Drools
>> >>> is
>> >>> throwing NullPointerException as below. I would much appreciate if
>> >>> someone
>> >>> on this list can help.
>> >>> java.lang.NullPointerException
>> >>> at
>> >>>
>> >>> org.drools.template.parser.DefaultTemplateColumn.createCellCondition(DefaultTemplateColumn.java:68)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.DefaultTemplateColumn.addCondition(DefaultTemplateColumn.java:91)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.DefaultTemplateRuleBase.createColumnConditions(DefaultTemplateRuleBase.java:105)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.DefaultTemplateRuleBase.createTemplateRule(DefaultTemplateRuleBase.java:98)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.DefaultTemplateRuleBase.getDTRules(DefaultTemplateRuleBase.java:85)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.DefaultTemplateRuleBase.<init>(DefaultTemplateRuleBase.java:64)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.TemplateDataListener.<init>(TemplateDataListener.java:76)
>> >>> at
>> >>>
>> >>> org.drools.template.parser.TemplateDataListener.<init>(TemplateDataListener.java:52)
>> >>> at
>> >>>
>> >>> org.drools.template.ObjectDataCompiler.compile(ObjectDataCompiler.java:44)
>> >>>
>> >>>
>> >>> Here is my code
>> >>>
>> >>> KnowledgeBuilder kBuilder =
>> >>> KnowledgeBuilderFactory.newKnowledgeBuilder();
>> >>> ObjectDataCompiler converter = new ObjectDataCompiler();
>> >>> InputStream dis = new FileInputStream( new File(
>> >>> "/home/pranab/Projects/gridx/ct11_1.drl" ) );
>> >>> if (null == dis){
>> >>> System.out.println("null rule template stream");
>> >>> return;
>> >>> }
>> >>>
>> >>> Collection<Map<String,Object>> paramMaps = new
>> >>> ArrayList<Map<String,Object>>();
>> >>>
>> >>> Map<String,Object> params = new HashMap<String,Object>();
>> >>>
>> >>> params.put("summerOnPeakPrimaryRate", new Integer(299));
>> >>> params.put("summerOnPeakSecondaryRate", new Integer(524));
>> >>> params.put("summerSemiPeakPrimaryRate", new Integer(176));
>> >>> params.put("summerSemiPeakSecondaryRate", new Integer(305));
>> >>> params.put("summerOffPeakPrimaryRate", new Integer(139));
>> >>> params.put("summerOffPeakSecondaryRate", new Integer(243));
>> >>> params.put("winterOnPeakPrimaryRate", new Integer(249));
>> >>> params.put("winterOnPeakSecondaryRate", new Integer(438));
>> >>> params.put("winterSemiPeakPrimaryRate", new Integer(176));
>> >>> params.put("winterSemiPeakSecondaryRate", new Integer(305));
>> >>> params.put("winterOffPeakPrimaryRate", new Integer(139));
>> >>> params.put("winterOffPeakSecondaryRate", new Integer(243));
>> >>> paramMaps.add(params);
>> >>>
>> >>> String drl = converter.compile(paramMaps, dis);
>> >>> Reader rdr = new StringReader( drl );
>> >>> kBuilder.add( ResourceFactory.newReaderResource(rdr),
>> >>> ResourceType.DRL);
>> >>>
>> >>>
>> >>> The line in blue is throwing the exception. This code is very similar
>> >>> to
>> >>> the example code in Drools Expert guide.
>> >>>
>> >>> Best,
>> >>>
>> >>> Roger
>> >>>
>> >>> _______________________________________________
>> >>> rules-users mailing list
>> >>> rules-users at lists.jboss.org
>> >>> https://lists.jboss.org/mailman/listinfo/rules-users
>> >>>
>> >>
>> >>
>> >> _______________________________________________
>> >> rules-users mailing list
>> >> rules-users at lists.jboss.org
>> >> https://lists.jboss.org/mailman/listinfo/rules-users
>> >>
>> >
>> >
>> > _______________________________________________
>> > rules-users mailing list
>> > rules-users at lists.jboss.org
>> > https://lists.jboss.org/mailman/listinfo/rules-users
>> >
>> >
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
>
More information about the rules-users
mailing list