Uploaded image for project: 'Drools'
  1. Drools
  2. DROOLS-236

NPE when ksession is serialized with facts logically inserted

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • None
    • 6.0.0.CR1
    • None
    • None

    Description

      Reproduce steps:

      Assuming Employee is a subclass of Person...

      1. Insert an Employee (say, 'Alice')
      2. InsertLogical a Person (say, 'Bob')
      3. Serialize and deserialize ksession
      4. Insert an Employee (say, 'Claire')
      5. Update 'Claire'

      It throws an NEP:

      Exception executing consequence for rule "Promote" in defaultpkg: java.lang.NullPointerException
      	at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
      	at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1026)
      ...
      Caused by: java.lang.NullPointerException
      	at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:434)
      	at org.drools.core.base.DefaultKnowledgeHelper.update(DefaultKnowledgeHelper.java:367)
      	at defaultpkg.Rule_Promote139773612.defaultConsequence(Rule_Promote139773612.java:9)
      	at defaultpkg.Rule_Promote139773612DefaultConsequenceInvokerGenerated.evaluate(Unknown Source)
      	at defaultpkg.Rule_Promote139773612DefaultConsequenceInvoker.evaluate(Unknown Source)
      	at org.drools.core.common.DefaultAgenda.fireActivation(DefaultAgenda.java:1016)
      	... 37 more
      
      

      In the step 2, ClassObjectTypeConf of Person[Bob] enables TMS. But at that time, Employee[Alice] creates its EqualityKey and put it to TMS.

      NamedEntryPoint.java:

          private void enableTMS(Object object, ObjectTypeConf conf) {
      
              
              final Rete source = this.ruleBase.getRete();
              final ClassObjectType cot = new ClassObjectType( object.getClass() );
              final Map<ObjectType, ObjectTypeNode> map = source.getObjectTypeNodes( EntryPointId.DEFAULT );
              final ObjectTypeNode node = map.get( cot );
              final ObjectHashSet memory = ((ObjectTypeNodeMemory) this.wm.getNodeMemory( node )).memory;
            
              // All objects of this type that are already there were certainly stated,
              // since this method call happens at the first logical insert, for any given type.
              org.drools.core.util.Iterator it = memory.iterator();
      
              for ( Object obj = it.next(); obj != null; obj = it.next() ) {
                
                  org.drools.core.util.ObjectHashSet.ObjectEntry holder = (org.drools.core.util.ObjectHashSet.ObjectEntry) obj;
          
                  InternalFactHandle handle = (InternalFactHandle) holder.getValue();
                  
                  if ( handle != null) {
                      EqualityKey key = new EqualityKey( handle );
                      handle.setEqualityKey( key );
                      key.setStatus(EqualityKey.STATED);
                      getTruthMaintenanceSystem().put(key);
                  }
              }
            
              // Enable TMS for this type.
              conf.enableTMS();
            
          }
      

      Then during deserialization, ProtobufInputMarshaller enables TMS for ClassObjectTypeConf of Employee[Alice] and ClassObjectTypeConf of Person[Bob].

      ProtobufInputMarshaller.java:

          public static void readTruthMaintenanceSystem( MarshallerReaderContext context, 
                                                         RuleData _session ) throws IOException {
      
              TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
              ProtobufMessages.TruthMaintenanceSystem _tms = _session.getTms();
              
              for( ProtobufMessages.EqualityKey _key : _tms.getKeyList() ) {
                  InternalFactHandle handle = (InternalFactHandle) context.handles.get( _key.getHandleId() );
      
                  // ObjectTypeConf state is not marshalled, so it needs to be re-determined
                  ObjectTypeConf typeConf = context.wm.getObjectTypeConfigurationRegistry().getObjectTypeConf( ((NamedEntryPoint)handle.getEntryPoint()).getEntryPoint(),
                                                                                                               handle.getObject() );
                  if (!typeConf.isTMSEnabled()) {
                      typeConf.enableTMS();
                  }
      

      Finally, Employee(Claire) is updated. ClassObjectTypeConf of Employee is under TMS but Claire doesn't have EqualityKey hence NPE is thrown.

      Attachments

        Activity

          People

            etirelli@redhat.com Edson Tirelli
            rhn-support-tkobayas Toshiya Kobayashi
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: