[jboss-jira] [JBoss JIRA] (DROOLS-645) Accumulate returned fact causing NPE
Mario Fusco (JIRA)
issues at jboss.org
Tue Nov 11 09:37:01 EST 2014
[ https://issues.jboss.org/browse/DROOLS-645?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Mario Fusco resolved DROOLS-645.
--------------------------------
Resolution: Cannot Reproduce Bug
I tried both accumulate syntax with the test case I am pasting below and they both work correctly. I cannot reproduce this issue, but if there's something that I am missing with my reproducer please let me know and eventually reopen this ticket.
Moreover there's another couple of things to notice:
1. Apparently the accumulate class you attached has a bug. Indeed it throws a CCE saying:
Caused by: java.lang.ClassCastException: org.drools.compiler.integrationtests.AccumulateTest$StatusMessage cannot be cast to java.util.List
at org.drools.compiler.integrationtests.AccumulateTest$RetryOldestCallTimeAccumulateFunction.accumulate(AccumulateTest.java:2853)
As you can see in my test case I changed
data.addAll((List<StatusMessage>) value);
with
data.add((StatusMessage) value);
let me know if this is ok and corresponds to what you wanted to achieve.
2. Apparently you're using that custom accumulate only to retrieve the StatusMessage with the lowest callTime. If that's true there's a more efficient way to obtain the same result with a simple not as it follows:
$message: StatusMessage( /* add constraints here */ )
not StatusMessage( callTime.before($message.callTime) )
{code}
@Test
public void testSortingAccumulate() throws Exception {
String drl =
"package org.foo.bar\n" +
"global java.util.List list\n" +
"import " + StatusMessage.class.getCanonicalName() + "\n" +
"import accumulate " + RetryOldestCallTimeAccumulateFunction.class.getCanonicalName() + " oldestRetry\n" +
"rule X when\n" +
//" accumulate($sm: StatusMessage(campaignName==\"test\"), $message:oldestRetry( $sm )) \n" +
" $message: StatusMessage() from accumulate($sm: StatusMessage(campaignName==\"test\"), oldestRetry( $sm )) \n" +
"then\n" +
" modify($message) { setCampaignName(\"notest\") };" +
"end\n";
KieSession ksession = new KieHelper().addContent(drl, ResourceType.DRL)
.build()
.newKieSession();
List<StatusMessage> list = new ArrayList<StatusMessage>();
ksession.setGlobal("list", list);
ksession.insert(new StatusMessage("test", 3));
ksession.insert(new StatusMessage("test", 2));
ksession.insert(new StatusMessage("test", 4));
ksession.fireAllRules();
assertEquals(1, list.size());
assertEquals(2, list.get(0).getCallTime());
}
public static class StatusMessage {
private String campaignName;
private final int callTime;
public StatusMessage(String campaignName, int callTime) {
this.campaignName = campaignName;
this.callTime = callTime;
}
public int getCallTime() {
return callTime;
}
public String getCampaignName() {
return campaignName;
}
public void setCampaignName(String campaignName) {
this.campaignName = campaignName;
}
}
public static class RetryOldestCallTimeAccumulateFunction implements AccumulateFunction {
private static final Comparator<StatusMessage> callTimeComparator = new Comparator<StatusMessage>() {
@Override
public int compare(StatusMessage s1, StatusMessage s2) {
return s1.getCallTime() - s2.getCallTime();
}
};
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
}
/* (non-Javadoc)
* @see org.kie.api.runtime.rule.AccumulateFunction#createContext()
*/
@Override
public Serializable createContext() {
return new ArrayList<StatusMessage>();
}
/* (non-Javadoc)
* @see org.kie.api.runtime.rule.AccumulateFunction#init(java.lang.Object)
*/
@Override
public void init(Serializable context) throws Exception {
@SuppressWarnings("unchecked")
List<StatusMessage> data = (List<StatusMessage>) context;
data.clear();
}
/* (non-Javadoc)
* @see org.kie.api.runtime.rule.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public void accumulate(Serializable context, Object value) {
List<StatusMessage> data = (List<StatusMessage>) context;
// data.addAll((List<StatusMessage>) value); <-- CCE
data.add((StatusMessage) value);
}
/* (non-Javadoc)
* @see org.kie.api.runtime.rule.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
*/
@Override
public void reverse(Serializable context, Object value) throws Exception {
}
/* (non-Javadoc)
* @see org.kie.api.runtime.rule.AccumulateFunction#getResult(java.lang.Object)
*/
@Override
public Object getResult(Serializable context) throws Exception {
@SuppressWarnings("unchecked")
List<StatusMessage> data = (List<StatusMessage>) context;
if (data.size() > 1) {
Collections.sort(data, callTimeComparator);
}
return data.get(0);
}
/**
* (non-Javadoc)
*
* @see org.kie.api.runtime.rule.AccumulateFunction#supportsReverse()
*/
@Override
public boolean supportsReverse() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public Class<?> getResultType() {
return StatusMessage.class;
}
}
{code}
> Accumulate returned fact causing NPE
> ------------------------------------
>
> Key: DROOLS-645
> URL: https://issues.jboss.org/browse/DROOLS-645
> Project: Drools
> Issue Type: Bug
> Affects Versions: 6.2.0.Beta2
> Environment: Mac OSX (maverick)
> Reporter: Roger Lefebvre
> Assignee: Mario Fusco
> Attachments: RetryOldestCallTimeAccumulateFunction.java, RetryOldestCallTimeAccumulateFunction.java
>
>
> The issue is discussed in https://groups.google.com/forum/?hl=en-GB#!topic/drools-usage/aZU5mXSgHMI.
> Here is the gist of it....
> I changed the accumulator to the following and it worked:
> accumulate($sm:StatusMessage(campaignName==$campaign.campaignName, status==ManagerCallState.CALLER_FAILURE, attempts<3, sent==true), $message:oldestRetry( $sm ))
> The previous approach was this:
> $message:StatusMessage() from accumulate($sm:StatusMessage(campaignName==$campaign.campaignName, status==ManagerCallState.CALLER_FAILURE, attempts<3, sent==true), oldestRetry( $sm ))
> which I thought was the correct or acceptable syntax option. Is there something I have overlooked in the second one ("from"??). It does give me a StatusMessage object but it lacks the underlying properties to allow the subsequent modify to work.
--
This message was sent by Atlassian JIRA
(v6.3.8#6338)
More information about the jboss-jira
mailing list