Test case:
public void test() { ResetBasicData.reset(); List<Customer> custs = Ebean.find(Customer.class).findList(); Customer customer = Ebean.find(Customer.class) .setId(custs.get(0).getId()) .select("name") .findUnique(); BeanState beanState = Ebean.getBeanState(customer); Assert.assertTrue(!beanState.isNew()); Assert.assertTrue(!beanState.isDirty()); Assert.assertTrue(!beanState.isNewOrDirty()); Assert.assertNotNull(beanState.getLoadedProps()); customer.setName("dirtyNameProp"); Assert.assertTrue(beanState.isDirty()); Assert.assertTrue(beanState.getChangedProps().contains("name")); customer.setStatus(Customer.Status.INACTIVE); Assert.assertTrue(beanState.isDirty()); Assert.assertTrue(beanState.getChangedProps().contains("state")); Assert.assertTrue(beanState.getChangedProps().contains("name")); }
The final Assert fails as the change to the "name" property is lost (due to a reset of the bean state as part of the lazy load that is invoked when setting the "state" property (which was not part of the initial load)).
Fixed in HEAD.
The issue was in SqlTreeNodeBean.
For lazy loading and refreshing beans... we need to turn off interception temporarily ... and then turn it back on when finished.
The bug was that instead of turning back on ONLY interception, the code instead setLoaded() which turns on interception but also resets the internal bean state and specifically we lose the 'changedProps'.
The fix was to JUST turn back on interception (and not use setLoaded()).