RequestFactoryEditorDriver remains dirty

169 views
Skip to first unread message

Alexander Orlov

unread,
Mar 26, 2012, 6:50:32 AM3/26/12
to google-we...@googlegroups.com
I followed the Editor example using RequestFactoryEditorDriver for RF-driven persistence. But it doesn't work for me. 

When I call 

public class EmployeeEditor extends Composite implements Editor<EmployeeProxy> 

the model data is transfered into the Composite and all UiBinder fields get their values. 

I use this code 

    void edit(EmployeeProxy employee) {
        driver.initialize(cf.getRF(), employeeEditor);
        final EmployeeReqCtx reqCtx = cf.getRF().employeeReqCtx();
        driver.edit(employee, reqCtx);

        cf.getLogger().log(Level.INFO, "driver.isDirty: " + driver.isDirty());
    }

to achieve this.The driver

interface Driver extends RequestFactoryEditorDriver<EmployeeProxy, EmployeeEditor> 

is clean at this point. As soon as I call

    void save() {
        cf.getLogger().log(Level.INFO, "driver.isDirty: " + driver.isDirty());
        final RequestContext reqCtx = driver.flush();
        if (driver.hasErrors()) {
            cf.getLogger().log(Level.INFO, "DRIVER HAS ERRORS.");
        }
        cf.getLogger().log(Level.INFO, "driver.isDirty: " + driver.isDirty());


        // Send the request
        reqCtx.fire(new Receiver<Void>() {
            @Override
            public void onConstraintViolation(Set<ConstraintViolation<?>> errors) {
                cf.getLogger().log(Level.SEVERE, "ERRORS DETECTED ON THE SERVER" + errors.size());
            }

            @Override
            public void onSuccess(Void response) {
                cf.getLogger().log(Level.SEVERE, "SUCCESS!");
                cf.getLogger().log(Level.INFO, "driver.isDirty: " + driver.isDirty());
            }
        });
        cf.getLogger().log(Level.INFO, "driver.isDirty: " + driver.isDirty());
    }

the driver becomes dirty and the "SUCCESS!" message appears. So the entity has been persisted at this point? However the subsequent log message in onSuccess() reports that the driver is still dirty. And when I call save() again, the 

Caused by: java.lang.IllegalStateException: A request is already in progress

exception is thrown.

My persistence framework is Objectify and the corresponding RequestFactory using JUnit tests are working and modify the entities as expected.

Thomas Broyer

unread,
Mar 26, 2012, 7:49:59 AM3/26/12
to google-we...@googlegroups.com
Whether you use RequestFactory or not is independent of isDirty in the EditorDriver.

When you edit() an object, the EditorDriver immediatly collects the values of the LeafValueEditor-s and keeps them in a private field.
When you call isDirty(), it collects the values again and compares them with the ones collected at edit() time: if there's a difference, then some editor has changed, which means the editor is "dirty" (the edited object is not in sync with the sub-editors' values, so flush()ing the driver will modify the edited object).
Complex editors can participate in this check by explicitly calling setDirty() on the EditorDelegate (you'd do that if you have a ValueAwareEditor that changes the edited object on flush() based on some condition: when the condition triggers, you can call setDirty(true) to signal flush() *will* modify the edited object).

The private field storing the LeafValueEditor's values is only initialized in edit(), so in your case you have to call edit() again from your onSuccess.

Alexander Orlov

unread,
Mar 26, 2012, 10:18:19 AM3/26/12
to google-we...@googlegroups.com
On Monday, March 26, 2012 1:49:59 PM UTC+2, Thomas Broyer wrote:
The private field storing the LeafValueEditor's values is only initialized in edit(), so in your case you have to call edit() again from your onSuccess.

Thx, for the clarification in respect to isDirty(). In fact isDirty() become clean after I've called edit() again. But my actual problem was that the modifications I've made were also not been persisted. I've found a way to persist them doing something like 

  final EmployeeReqCtx reqCtxDriver = (EmployeeReqCtx) cf.getDriver().flush();
  reqCtxDriver.put(employee).fire(new Receiver<Void>() {
    // persists the edited employee 
  }

instead of 

  final RequestContext reqCtxDriver =  cf.getDriver().flush();
  reqCtxDriver.fire(new Receiver<Void>() {  
    // ... doesn't work at all for editing entities(?) although it's mentioned in the Editor example
  }

in save(). Although I can't imagine that one needs explicit casting to edit an entity..., it works.

Thomas Broyer

unread,
Mar 26, 2012, 10:22:27 AM3/26/12
to google-we...@googlegroups.com


On Monday, March 26, 2012 4:18:19 PM UTC+2, Alexander Orlov wrote:
On Monday, March 26, 2012 1:49:59 PM UTC+2, Thomas Broyer wrote:
The private field storing the LeafValueEditor's values is only initialized in edit(), so in your case you have to call edit() again from your onSuccess.

Thx, for the clarification in respect to isDirty(). In fact isDirty() become clean after I've called edit() again. But my actual problem was that the modifications I've made were also not been persisted. I've found a way to persist them doing something like 

  final EmployeeReqCtx reqCtxDriver = (EmployeeReqCtx) cf.getDriver().flush();
  reqCtxDriver.put(employee).​fire(new Receiver<Void>() {
    // persists the edited employee 
  }

instead of 

  final RequestContext reqCtxDriver =  cf.getDriver().flush();
  reqCtxDriver.fire(new Receiver<Void>() {  
    // ... doesn't work at all for editing entities(?) although it's mentioned in the Editor example
  }


It's works very well... provided you previously queued a call to your put() method in the RequestContext !
The example does this just before calling edit() on the EditorDriver.

Alexander Orlov

unread,
Mar 26, 2012, 11:28:37 AM3/26/12
to google-we...@googlegroups.com
Thx again, your hint simplified my code a lot!
Reply all
Reply to author
Forward
0 new messages