Search code examples
gwtrequestfactory

UiEditor/RequestFactory generate null delegate on ValueProxy


I have a Service.class ValueProxy in a service oriented architecture (i have a server method like "storeService(service)". I would use an Editor with RequestFactoryEditorDriver.

I expect all work, but when i call driver.edit(service) i get a null delegate exception.

Why? It's a bug?

At http://crazygui.wordpress.com/tag/editor/ i find a sample of implementation...only differece with mine is SimpleBeanRequestEditorDriver.class (i have RequestFactoryEditorDriver.class)

ServiceEditor.class

public class ServiceEditor extends Composite implements Editor<ServiceProxy>{

    private static final Logger logger = Logger.getLogger(ServiceEditor.class.getName());

    private static ServiceEditorUiBinder uiBinder = GWT
            .create(ServiceEditorUiBinder.class);

    interface ServiceEditorUiBinder extends
    UiBinder<Widget, ServiceEditor> {
    }

    //~Driver ==========================================================================================================================
    interface Driver extends RequestFactoryEditorDriver<ServiceProxy, ServiceEditor> {
    }

    Driver driver;
    //====================================================================================================================================
    @UiField
    Decorator<String> name;

    @UiField
    Decorator<String> description;

    @UiField
    Decorator<String> notes;

    @UiField
    Decorator<String> citiesString;

//  @UiField(provided=true)
//  Decorator<String> category;

//    MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();

//  @UiField(provided=true)
//  @Ignore
//    SuggestBox suggestBox = new SuggestBox(oracle);



    private BigInteger organizationId;

private EditorDelegate<ServiceProxy> delegate;

    public ServiceEditor() {
        initWidget(uiBinder.createAndBindUi(this));
        driver = GWT.create(Driver.class);
    }

    @Override
    protected void onLoad() {
        driver.initialize(ClientFactory.AppInjector.getRequestFactory(),this);
    }

    public void edit() {
        ServiceRequestContext requestContext = ClientFactory.AppInjector.getRequestFactory().getNewServiceContext();

        edit(requestContext.create(ServiceProxy.class),requestContext);
    }


    public void display(ServiceProxy p){
        driver.display(p);
    }

    public void edit(ServiceProxy p) {
        ServiceRequestContext requestContext = ClientFactory.AppInjector.getRequestFactory().getNewServiceContext();
        edit(p,requestContext);
    }   



    public void edit(ServiceProxy service,ServiceRequestContext requestContext) {
        if(service.getToken()==null) {
            requestContext.addServiceToOrganization(organizationId, service);
            //TODO: attenzione a tempistiche chiamate;
            SessionRPC.Util.getInstance().getOrganizationId(new AsyncCallback<BigInteger>() {

                @Override
                public void onSuccess(BigInteger result) {
                    organizationId = result;
                }

                @Override
                public void onFailure(Throwable caught) {

                }
            });
        }
        else 
            requestContext.updateService(service);
        driver.edit(service,requestContext);
    }   

    public RequestContext flush2(){
        return driver.flush();
    }

    public void submit(Receiver<Void> receiver){
        RequestContext context = driver.flush();
        if (driver.hasErrors()) {
            Window.alert("Driver errors!");
            return;
        }
        context.fire(receiver);
    }   

    public void notifyErrors(Set<ConstraintViolation<?>> violations) {
        driver.setConstraintViolations(violations);
        //driver.getErrors().get(0).
        logger.info("Validation Errors: /n "+driver.getErrors().toString());
    }

//  @Override
//  public void setDelegate(EditorDelegate<ServiceProxy> delegate) {
//      this.delegate = delegate;
//  }

}

ActivitySnippet...

ServiceEditor serviceEditor = GWT.create(ServiceEditor.class);
serviceEditor.display(response);

Stack trace...

Caused by: com.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot set property 'request' of undefined
at Unknown.$collect(JsArrayString.java:42)
at Unknown.fillInStackTrace_2(StackTraceCreator.java:180)
at Unknown.fillInStackTrace_0(StackTraceCreator.java:518)
at Unknown.fillInStackTrace(Throwable.java:115)
at Unknown.Throwable_0(Throwable.java:51)
at Unknown.Exception_0(Exception.java:25)
at Unknown.RuntimeException_0(RuntimeException.java:25)
at Unknown.JavaScriptException_1(JavaScriptException.java:117)
at Unknown.JavaScriptException_0(JavaScriptException.java:109)
at Unknown.getCachableJavaScriptException(Exceptions.java:45)
at Unknown.wrap(Exceptions.java:29)
at Unknown.$setRequestContext(RequestFactoryEditorDelegate.java:80)
at Unknown.$edit(AbstractRequestFactoryEditorDriver.java:168)
at Unknown.display_0(AbstractRequestFactoryEditorDriver.java:159)
at Unknown.$show_2(ServiceEditor.java:91)

This means that getDelegate() method (line 168 of AbstractRequestFactoryEditorDriver.class) return null.


Solution

  • If you call RequestFactoryEditorDriver.show, it essentially just calls RequestFactoryEditorDriver.edit, but without a requestcontext. This otherwise should follow the same basic path in terms of how the driver needs to be wired up.

    In this case, if the delegate is null, then the driver hasn't been initialized. From your code:

    public ServiceEditor() {
        initWidget(uiBinder.createAndBindUi(this));
        driver = GWT.create(Driver.class);
    }
    
    @Override
    protected void onLoad() {
        driver.initialize(ClientFactory.AppInjector.getRequestFactory(),this);
    }
    
    public void edit() {
        ServiceRequestContext requestContext = ClientFactory.AppInjector.getRequestFactory().getNewServiceContext();
    
        edit(requestContext.create(ServiceProxy.class),requestContext);
    }
    
    
    public void display(ServiceProxy p){
        driver.display(p);
    }
    

    You never listed the code that shows when edit or display are being called, so I'm mostly guessing here, but it looks like your other code looks roughly like this:

    ServiceEditor editor = new ServiceEditor();//create ui, create driver.
    
    editor.display(data);//driver.display, which calls driver.edit
    
    parentWidget.add(editor);// causes onLoad to be called if actually 
                             //attached to the dom, which causes driver.initialize
    

    This is wrong. The driver must be initialized before you attempt to edit or display, since otherwise it doesn't know which editor objects it should be working with.

    Instead, move driver.initialize to earlier than onLoad, like in the ServiceEditor constructor itself, or in some init method which allows you to call it earlier deliberately. Another option is to just call parent.add(editor) before editor.display(), though this may not work - make sure you understand what causes onLoad to be called.

    (Please note that ServiceEditor.show is in your stack trace but not in your code listing, so I can't tell if the chance would be more obvious in seeing this.)