MTable.getPO cache for model factory wrongly removing from cache when PO is not found

Description

With ticket the method MTable.getPO is caching the model class related to every table.

However the implementation has a flaw, the model class is detected by one of the factories and added to the cache, but when a PO cannot be read, the model class is removed from the cache.

The cache must still be valid, even if the model class cannot find a record and returns null.

Environment

None

Activity

Show:

Heng Sin Low April 18, 2023 at 5:53 AM

hi , I’ve approved 1788 and for GenericPO, I will looks at that later but for me, that’s a very low priority item as it is a very rare use case.

Carlos Ruiz April 17, 2023 at 7:48 PM

Hi - I was testing the IDEMPIERE 5567 ticket and found this case.

The MTable.getPO looks very inefficient when a record cannot be read, as you can see in the test case, it is trying MTest three times and then trying GenericPO.

I think when a service class is proved to manage a table, because it returns a non-null PO then the cache can stick to that service.

Can you please check the pull request 1788?

I implemented the suggested change, but still I think is inefficient when there is not a model class and it needs to be managed using GenericPO, because every time the getPO is called for such table all the services are tested again to fallback to GenericPO (see the TODO comment in line 610).

How can we add GenericPO to the s_modelFactoryCache? Can you please suggest a patch that implements that, I’m not sure how to do it.

Regards,

Carlos Ruiz

Carlos Ruiz April 17, 2023 at 7:35 PM

Test case:

  • Login as System Administrator

  • Open Test window

  • Create a record, fill the name with any value and save

  • Immediately delete the record

  • Open Change Audit window and select all records

  • The console log must show something like this:


14:14:48.795===========> MTest.loadPO: NO Data found for Test_ID=1000000 [2285]
java.lang.Exception
at org.compiere.model.PO.loadPO(PO.java:1594)
at org.compiere.model.PO.load(PO.java:1509)
at org.compiere.model.PO.load(PO.java:1460)
at org.compiere.model.PO.<init>(PO.java:252)
at org.compiere.model.PO.<init>(PO.java:165)
at org.compiere.model.X_Test.<init>(X_Test.java:42)
at org.compiere.model.MTest.<init>(MTest.java:50)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.adempiere.base.AbstractModelFactory.getPO(AbstractModelFactory.java:95)
at org.adempiere.base.AnnotationBasedModelFactory.getPO(AnnotationBasedModelFactory.java:204)
at org.compiere.model.MTable.getPO(MTable.java:574)
at org.adempiere.webui.editor.WRecordIDEditor.propertyChange(WRecordIDEditor.java:275)
at java.desktop/java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:343)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:335)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:268)
at org.compiere.model.GridField.setValue(GridField.java:2028)
at org.compiere.model.GridTab.setCurrentRow(GridTab.java:2565)
at org.compiere.model.GridTab.query(GridTab.java:739)

14:14:48.798===========> MTest.loadPO: NO Data found for Test_ID=1000000 [2285]
java.lang.Exception
at org.compiere.model.PO.loadPO(PO.java:1594)
at org.compiere.model.PO.load(PO.java:1509)
at org.compiere.model.PO.load(PO.java:1460)
at org.compiere.model.PO.<init>(PO.java:252)
at org.compiere.model.PO.<init>(PO.java:165)
at org.compiere.model.X_Test.<init>(X_Test.java:42)
at org.compiere.model.MTest.<init>(MTest.java:50)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.adempiere.base.AbstractModelFactory.getPO(AbstractModelFactory.java:95)
at org.adempiere.base.AnnotationBasedModelFactory.getPO(AnnotationBasedModelFactory.java:204)
at org.compiere.model.MTable.getPO(MTable.java:594)
at org.adempiere.webui.editor.WRecordIDEditor.propertyChange(WRecordIDEditor.java:275)
at java.desktop/java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:343)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:335)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:268)
at org.compiere.model.GridField.setValue(GridField.java:2028)
at org.compiere.model.GridTab.setCurrentRow(GridTab.java:2565)
at org.compiere.model.GridTab.query(GridTab.java:739)

14:14:48.801===========> MTest.loadPO: NO Data found for Test_ID=1000000 [2285]
java.lang.Exception
at org.compiere.model.PO.loadPO(PO.java:1594)
at org.compiere.model.PO.load(PO.java:1509)
at org.compiere.model.PO.load(PO.java:1460)
at org.compiere.model.PO.<init>(PO.java:252)
at org.compiere.model.PO.<init>(PO.java:165)
at org.compiere.model.X_Test.<init>(X_Test.java:42)
at org.compiere.model.MTest.<init>(MTest.java:50)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.adempiere.base.AbstractModelFactory.getPO(AbstractModelFactory.java:95)
at org.adempiere.base.AbstractModelFactory.getPO(AbstractModelFactory.java:45)
at org.compiere.model.MTable.getPO(MTable.java:594)
at org.adempiere.webui.editor.WRecordIDEditor.propertyChange(WRecordIDEditor.java:275)
at java.desktop/java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:343)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:335)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:268)
at org.compiere.model.GridField.setValue(GridField.java:2028)
at org.compiere.model.GridTab.setCurrentRow(GridTab.java:2565)
at org.compiere.model.GridTab.query(GridTab.java:739)

14:14:48.805===========> GenericPO.loadPO: NO Data found for Test_ID=1000000 [2285]
java.lang.Exception
at org.compiere.model.PO.loadPO(PO.java:1594)
at org.compiere.model.PO.load(PO.java:1509)
at org.compiere.model.PO.load(PO.java:1460)
at org.compiere.model.PO.<init>(PO.java:252)
at org.compiere.model.PO.<init>(PO.java:188)
at org.adempiere.model.GenericPO.<init>(GenericPO.java:75)
at org.compiere.model.MTable.getPO(MTable.java:611)
at org.adempiere.webui.editor.WRecordIDEditor.propertyChange(WRecordIDEditor.java:275)
at java.desktop/java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:343)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:335)
at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:268)
at org.compiere.model.GridField.setValue(GridField.java:2028)
at org.compiere.model.GridTab.setCurrentRow(GridTab.java:2565)
at org.compiere.model.GridTab.query(GridTab.java:739)


Details

Assignee

Reporter

Fix versions

Priority

Created April 17, 2023 at 7:29 PM
Updated November 28, 2023 at 9:57 AM