Copilot commented on code in PR #7127:
URL: https://github.com/apache/incubator-kie/pull/7127#discussion_r4088793965


##########
drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/ProtobufInputMarshaller.java:
##########
@@ -425,12 +425,43 @@ public static void readFactHandles( 
ProtobufMarshallerReaderContext context,
                 assertHandleIntoOTN( context, wm, handle, pctxs );
             }
 
+            reattachPropertyChangeListener( entryPoint, handle, 
_handle.getIsDynamic() );
+
             if (handle.isExpired()) {
                 wm.addPropagation(new 
WorkingMemoryReteExpireAction((DefaultEventHandle) handle));
             }
         }
     }
 
+    /**
+     * Re-registers the entry point as the fact's JavaBeans {@code 
PropertyChangeListener}, which
+     * is what makes a fact dynamic. Marshalling cannot carry that 
registration: the listener is
+     * the entry point itself, which is not serializable, so {@link 
java.beans.PropertyChangeSupport}
+     * drops it and the restored fact reaches the engine with an empty 
listener list. Without this
+     * the fact still holds the right values, but a setter no longer notifies 
the session and the
+     * rules matching it are never re-evaluated.
+     *
+     * <p>Only facts that were dynamic in the marshalled session are 
re-registered: those inserted
+     * with {@link org.kie.api.runtime.rule.EntryPoint#insert(Object)}'s 
dynamic variant, recorded
+     * per handle in the blob, and those whose type is declared {@code 
@propertyChangeSupport},
+     * which is derivable from the knowledge base. This mirrors what
+     * {@code NamedEntryPoint.insert} does on a live insertion.</p>
+     */
+    private static void reattachPropertyChangeListener( EntryPoint entryPoint,
+                                                        InternalFactHandle 
handle,
+                                                        boolean dynamic ) {
+        Object object = handle.getObject();
+        if ( object == null || !(entryPoint instanceof NamedEntryPoint) ) {
+            return;
+        }
+        NamedEntryPoint namedEntryPoint = (NamedEntryPoint) entryPoint;
+        ObjectTypeConf typeConf = 
namedEntryPoint.getObjectTypeConfigurationRegistry()
+                .getOrCreateObjectTypeConf( namedEntryPoint.getEntryPoint(), 
object );
+        if ( dynamic || typeConf.isDynamic() ) {
+            namedEntryPoint.addPropertyChangeListener( handle, dynamic );

Review Comment:
   Reattaching an explicitly dynamic fact also repopulates `dynamicFacts`, but 
deletion still detaches listeners only when `typeConf.isDynamic()` 
(`NamedEntryPoint.deleteStated`, lines 480–483). For a fact made dynamic solely 
by `insert(fact, true)`, deleting the restored fact therefore leaves this entry 
point registered; the next setter call reaches `propertyChange` after the 
handle is gone and throws “handle not found.” Update the deletion condition to 
also recognize `isDynamicFact(handle)` and add a round-trip/delete regression 
case.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to