简体   繁体   English

从有状态的流口水中获取事实

[英]Fetching fact from stateful session of drools

I'm trying to get the new inserted fact from the rules: 我正在尝试从规则中获取新插入的事实:

import com.neu.als.thesis.db.beans.FLTBean
import com.neu.als.thesis.db.beans.StudentBean

rule "Excellent"
    no-loop

    when
        $m: FLTBean ( listeningScore > 85 && listeningScore < 101 )
    then
        StudentBean studentBean = new StudentBean();
        studentBean.setKnowledgeLevel( "Excellent" );
        insert( studentBean );
end

To get something from the stateful session I should do this: 要从有状态会话中获取一些信息,我应该这样做:

protected Collection<Object> findFacts( final StatefulKnowledgeSession session, final String factClass )
{
    ObjectFilter filter = new ObjectFilter()
    {
        @Override
        public boolean accept( Object object )
        {
            return object.getClass().equals( factClass );
        }
    };
    Collection<Object> results = session.getObjects( filter );
    return results;
}

Given the fact that I already set the code to read the rules the next step I did is this: 鉴于我已经设置了代码以读取规则,因此下一步是:

protected void processFacts( KnowledgeBase aKnowledgeBase, Object aBean )
{
    StatefulKnowledgeSession ksession = aKnowledgeBase.newStatefulKnowledgeSession();

    ksession.insert( aBean );
    ksession.fireAllRules();

    Collection<Object> result = findFacts( ksession, "StudentBean" );

    ksession.dispose();

    for( Object test : result )
    {
        System.out.println( test == null );
        System.out.println( test );
    }
}

Why I don't get any response from the object? 为什么我没有从该对象得到任何响应? It doesn't print anything. 它不会打印任何内容。 No stacktrace, no error. 没有堆栈跟踪,没有错误。 I even check it if its null. 我什至检查它是否为空。 But still no response. 但是仍然没有回应。 What am I doing wrong? 我究竟做错了什么?

Update: 更新:

This is the method that read the .drl file. 这是读取.drl文件的方法。

protected KnowledgeBase readKnowledgeBase( String aRuleFileName ) throws Exception
{
     KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
     kbuilder.add( ResourceFactory.newClassPathResource( aRuleFileName, getClass() ), ResourceType.DRL );
     KnowledgeBuilderErrors errors = kbuilder.getErrors();

     if( errors.size() > 0 )
     {
        for( KnowledgeBuilderError error : errors )
        {
            System.err.println( error );
        }
            throw new IllegalArgumentException( "Could not parse knowledge." );
     }

   KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
   kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
   return kbase;
}

The one that calls the processFacts method is this 调用processFacts方法的是这个

public String evaluateConceptKnowledgeLevel( double FLTmark )
{
   String knowledgeLevel = null;

   // test
   InferenceEngine ie = new InferenceEngine();
   KnowledgeBase kbase;
   try
   {
       kbase = ie.readKnowledgeBase( "KnowledgeLevel.drl" );
       FLTBean bean = new FLTBean();
       bean.setListeningScore( FLTmark );

       ie.processFacts( kbase, bean );
   }
   catch( Exception e )
   {
       e.printStackTrace();
   }
   // up to here

   return knowledgeLevel;
}

A few options... 一些选择...

Pass in the simple name instead of the full class name. 传入简单名称而不是完整的类名称。

Change 更改

Collection<Object> result = findFacts( ksession, "com.neu.als.thesis.db.beans.StudentBean" );

to

Collection<Object> result = findFacts( ksession, "StudentBean" );

Change the 'accept' method to compare the full class name. 更改“接受”方法以比较完整的类名。

Change 更改

     public boolean accept( Object object ) {
         return object.getClass().getSimpleName().equals( factClass );
     }

to

     public boolean accept( Object object ) {
         return object.getClass().getName().equals( factClass );
     }

Change the findFacts method to take the actual class as an argument and compare to that. 更改find​​Facts方法以将实际的类作为参数并与之进行比较。

Change 更改

protected Collection<Object> findFacts( 
        final StatefulKnowledgeSession session, 
        final String factClass ) {
    ObjectFilter filter = new ObjectFilter() {
    @Override
        public boolean accept( Object object ) {
            return object.getClass().getSimpleName().equals( factClass );
        }
    };

    Collection<Object> results = session.getObjects( filter );
    return results;
}

to

protected Collection<Object> findFacts( 
        final StatefulKnowledgeSession session, 
        final Class factClass ) {
    ObjectFilter filter = new ObjectFilter() {
    @Override
        public boolean accept( Object object ) {
            return object.getClass().equals( factClass );
        }
    };

    Collection<Object> results = session.getObjects( filter );
    return results;
}

Assuming that your facts are all Java classes, then the 3rd option of comparing the class is a better option. 假设您的事实都是Java类,那么比较类的第三个选择是一个更好的选择。 If you use declared types, then the simple name is useful, as you are unlikely to have a reference to the actual class that Drools generates. 如果使用声明的类型,则简单名称很有用,因为您不太可能引用Drools生成的实际类。

An additional note for when you're testing these things, the Drools API also provides the session.getObjects() method with no arguments. 关于您在测试这些东西时的补充说明,Drools API还提供了不带参数的session.getObjects()方法。 By calling that you will get a reference to all facts that are in working memory, no matter what they are. 通过调用,您将获得对工作内存中所有事实的引用,无论它们是什么。 When writing filters, it's not a bad idea to use that to prove to yourself that the expected facts are in working memory, and then to add filtering, so that you can pick out specific facts according to their class and their properties. 在编写过滤器时,使用它向自己证明期望的事实在工作内存中,然后添加过滤器,这不是一个坏主意,以便您可以根据它们的类和属性来挑选特定的事实。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM