Editor not flush values of subeditors

105 views
Skip to first unread message

Cristian Rinaldi

unread,
Oct 25, 2011, 12:07:06 PM10/25/11
to google-we...@googlegroups.com
Hello:
  I am working in a project with GWT (RF, Editors, MVP).
  I have an error with bind of Editor

 The error itself, is that address property is not sent, not sent values with flush is called in method save of TerceroNewEditorPresenter. The unique values that are sent, are those that correspond to Tercero (name and lastName). 

 Attached files to see and guide me in the error.

 Thank you very much and sorry for my English.



A.U.S Cristian Rinaldi

Teléfono Móvil: (0342) 155 238 083

www.logikas.com

Lisandro de la Torre 2643 Of 5 - 3000 - Santa Fe

Teléfono Fijo: (0342) 483 5138





AddressView.java
TerceroEditor.ui.xml
TerceroNewEditorPresenter.java
AddressNewPresenter.java
SelectorCityPresenter.java
SelectorCityView.java
TerceroNewView.java
View.java
AddressEditor.java
AddressEditor.ui.xml
SelectorCityWidget.java
SelectorCityWidget.ui.xml
TerceroEditor.java

Thomas Broyer

unread,
Oct 25, 2011, 2:16:14 PM10/25/11
to google-we...@googlegroups.com, cristian...@logikas.com
AddressView (which is the type used in TerceroEditor) extends neither Editor nor IsEditor, so the "address" property isn't edited.

Did I miss something in your code? (I only looked at TerceroNewEditorPresenter, TerceroEditor and AddressView)

Cristian Rinaldi

unread,
Oct 25, 2011, 4:33:55 PM10/25/11
to google-we...@googlegroups.com
Thomas, thanks for the fast responce. I will see if this is causing the error.
 
AddressWidget implements AddressView and Editor for AddressProxy, you say that the AddressView must be extend Editor?


Now, one design question. 

I love MVP, this pattern is very powerfull but, with Activities and Place some thing are dificult.

Activities are for when you need navigation, but if want each view has a Presenter, I thought the following:
  
   One interface Presenter for each View, where "View" delegate the logic in the presenter implementation.
   Now, presenter is not Activity. When I need navigation, I make a Activity that inject the presenter and delegate in this the logic of View.

   I want keep separate in the best forms the concepts of view and presenter, but I want to know if inject the presenter in view is ok.
  The presenter have a method called onCreate(T) where T is a View. That method is called when View is initialized after make UiBinder interface.
  In the onCreate(T) I inicialize the editor driver, etc.

  When I precise a Activity, in the start method I obtain the view, by example, with AsyncProvider, how the View inject Presenter, the Activity delegate logic to Presenter.

 I started think this for nested complex widget, for example, load Employees associated with bank accounts, where the Widgets for list of selection and creation bank account is a widget that delegate logic in a presenter that is not Activity.
 But, i can use this widget alone in other view where is necesary one Activity.

  All this is fine or I've gone crazy? 

  Sorry for my english.

A.U.S Cristian Rinaldi

Teléfono Móvil: (0342) 155 238 083

www.logikas.com

Lisandro de la Torre 2643 Of 5 - 3000 - Santa Fe

Teléfono Fijo: (0342) 483 5138







2011/10/25 Thomas Broyer <t.br...@gmail.com>

Thomas Broyer

unread,
Oct 26, 2011, 6:47:43 AM10/26/11
to google-we...@googlegroups.com, cristian...@logikas.com


On Tuesday, October 25, 2011 10:33:55 PM UTC+2, Cristian Rinaldi wrote:
Thomas, thanks for the fast responce. I will see if this is causing the error.
 
AddressWidget implements AddressView and Editor for AddressProxy, you say that the AddressView must be extend Editor?

I'm saying that the type of the "address" field in type TerceroEditor does not implement Editor (or IsEditor), so the Editor framework does not treat it as an editor. You'll either have to change it to AddressWidget, or make AddressView extend Editor.

Now, one design question. 

I love MVP, this pattern is very powerfull but, with Activities and Place some thing are dificult.

Activities are for when you need navigation, but if want each view has a Presenter, I thought the following:
  
   One interface Presenter for each View, where "View" delegate the logic in the presenter implementation.
   Now, presenter is not Activity. When I need navigation, I make a Activity that inject the presenter and delegate in this the logic of View.

   I want keep separate in the best forms the concepts of view and presenter, but I want to know if inject the presenter in view is ok.
  The presenter have a method called onCreate(T) where T is a View. That method is called when View is initialized after make UiBinder interface.
  In the onCreate(T) I inicialize the editor driver, etc.

  When I precise a Activity, in the start method I obtain the view, by example, with AsyncProvider, how the View inject Presenter, the Activity delegate logic to Presenter.

 I started think this for nested complex widget, for example, load Employees associated with bank accounts, where the Widgets for list of selection and creation bank account is a widget that delegate logic in a presenter that is not Activity.
 But, i can use this widget alone in other view where is necesary one Activity.

  All this is fine or I've gone crazy?

I'm not sure I understood what you're coming with. All I can say is that my activities are presenters, and in a few cases where a complex "component" is to be reused, I have a presenter and view for it that's not an activity. I also inject my views within my presenters in their constructors, and the presenters "inject themselves" into their view when needed (when the activity starts, in my case); this allows the views to have longer lifetime as the presenters, because I use short-lived presenters and singleton views.

Cristian Rinaldi

unread,
Oct 26, 2011, 7:51:46 AM10/26/11
to google-we...@googlegroups.com
Tanks Thomas for response.
The rare is that AddressView implements Editor<AddreessProxy>

I put the codes below:

Extract for TerceroNewView

public interface TerceroNewView extends View, Editor<TercerosProxy> {
  public interface Presenter extends MutablePresenter<TerceroNewView>{
    
  }

  RequestFactoryEditorDriver<TercerosProxy, ? extends Editor<TercerosProxy>> createEditorDriver(
      RequestFactory rf);
}


Extract for TerceroEditor
 
public class TerceroEditor implements TerceroNewView {

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

  interface TerceroEditorUiBinder extends UiBinder<SimplePanel, TerceroEditor> {
  }

  interface Driver extends RequestFactoryEditorDriver<TercerosProxy, TerceroEditor> {
  }

  private SimplePanel root;

  @UiField
  ClientResource res;

  @UiField
  ValueBoxEditorDecorator<String> name;

  @UiField
  ValueBoxEditorDecorator<String> lastName;

  @UiField(provided = true)
  AddressView address;
 
  private final TerceroNewView.Presenter presenter;

  @Inject
  public TerceroEditor(
      AsyncProvider<AddressView> addressView,
      @Named(Constans.TerceroNewPresenter) TerceroNewView.Presenter presenter) {

    this.presenter = presenter;
    
    addressView.get(new AsyncCallback<AddressView>() {
      @Override
      public void onSuccess(AddressView result) {
        address = result;
        ini();
        
      }
      @Override
      public void onFailure(Throwable caught) {
      }
    });
  }
  
  private void ini(){
    root = uiBinder.createAndBindUi(this);
    res.erpLgkStyle().ensureInjected();
    presenter.onCreate(this);
  }

  .....
  .....
}

Extract for AddressView:

  public interface AddressView extends View, Editor<AddressProxy>{
  
     public interface Presenter extends MutablePresenter<AddressView>{
    
     }
  
     HasConstrainedValue<CityProxy> getCitys(); 
  }

Extract for AddressEditor:
 
public class AddressEditor implements AddressView {

  interface AddressWidgetUiBinder extends UiBinder<HTMLPanel, AddressEditor> {
  }
  
  interface Driver extends RequestFactoryEditorDriver<AddressProxy, AddressEditor> {
  }
  
  private static AddressWidgetUiBinder uiBinder = GWT.create(AddressWidgetUiBinder.class);

  private HTMLPanel root;

  private AddressView.Presenter presenter;

  @UiField
  ValueBoxEditorDecorator<String> address;

  @UiField
  ValueBoxEditorDecorator<Integer> number;

  @UiField
  ValueBoxEditorDecorator<String> code;

  @UiField(provided = true)
  SelectorCityView city;
  

  @Inject
  public AddressEditor(
      AsyncProvider<SelectorCityView> selectorCity,
      @Named(Constans.AddressNewPresenter) AddressView.Presenter presenter) {
    
    this.presenter = presenter;
    
    // TODO ver si hay otra forma de inicializar las vistas
    selectorCity.get(new AsyncCallback<SelectorCityView>() {
      @Override
      public void onSuccess(SelectorCityView result) {
        city = result;
        init();
      }

      @Override
      public void onFailure(Throwable caught) {
      }
    });
  }
  
  private void init(){
    root = uiBinder.createAndBindUi(this);
    presenter.onCreate(this);
  }
...
...
}

Extract for TerceroNewPresenter 

public class TerceroNewEditorPresenter implements TerceroNewView.Presenter {

  private final PlaceController placeController;
  private final ErpRequestFactory requestFactory;

  private RequestFactoryEditorDriver<TercerosProxy, ? extends Editor<TercerosProxy>> terceroDriver;

  @Inject
  public TerceroNewEditorPresenter(final AddressNewPresenter addressPresenter,
      final ErpRequestFactory requestFactory, final PlaceController placeController) {

    this.placeController = placeController;
    this.requestFactory = requestFactory;
  }

  @Override
  public void goTo(Place place) {
    placeController.goTo(place);
  }

  @Override
  public void save() {

    RequestContext context = terceroDriver.flush();

    boolean hasClientErrors = terceroDriver.hasErrors();

    if (!hasClientErrors) {

      context.fire(new Receiver<Void>() {

        @Override
        public void onSuccess(Void response) {
          placeController.goTo(new DefaultPlace());
        }

        @Override
        public void onViolation(Set<Violation> errors) {
          terceroDriver.setViolations(errors);
        }

        @Override
        public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
          terceroDriver.setConstraintViolations(violations);
        }

      });
    }
  }

  @Override
  public void onCreate(final TerceroNewView view) {

    terceroDriver = view.createEditorDriver(requestFactory);

    TercerosRequest context = requestFactory.getTercerosRequest();

    TercerosProxy tercero = context.create(TercerosProxy.class);

    AddressProxy address = context.create(AddressProxy.class);

    tercero.setAddress(address);

    context.persist(tercero).with(terceroDriver.getPaths());

    terceroDriver.edit(tercero, context);
  }
...
...
}
  
   
Extract for GIN configurations:
   
bind(TerceroNewView.class).to(TerceroEditor.class).in(Singleton.class);
bind(AddressView.class).to(AddressEditor.class).in(Singleton.class);


Data sent by Client to Server

{"F":"com.logikas.erp.shared.request.ErpRequestFactory","O":[{"T":"oNrI9YUtkvx6RRVjmYN2ooLeKvQ=","P":{"lastName":"Rinaldi","address":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"name":"Cristian"},"C":1,"R":"1","O":"PERSIST"},{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","C":2,"R":"1","O":"PERSIST"}],"I":[{"P":[{"T":"oNrI9YUtkvx6RRVjmYN2ooLeKvQ=","R":"1","C":1}],"R":["address"],"O":"tNTGSDAwvU0DpOikzbM$SKIPFQw="}]}
   
Data sent by Server to Client

{"X":[{"T":"{javax.validation.constraints.NotNull.message}","P":"code","R":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"L":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"M":"no puede ser null"},
{"T":"{javax.validation.constraints.NotNull.message}","P":"address","R":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"L":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"M":"no puede ser null"},
{"T":"{javax.validation.constraints.NotNull.message}","P":"number","R":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"L":{"T":"jVTUhBxMFgABvM07abYHRgwY8ps=","R":"1","C":2},"M":"no puede ser null"}]}

About other question, tanks for sugestion.

Regards

A.U.S Cristian Rinaldi

Teléfono Móvil: (0342) 155 238 083

www.logikas.com

Lisandro de la Torre 2643 Of 5 - 3000 - Santa Fe

Teléfono Fijo: (0342) 483 5138







2011/10/26 Thomas Broyer <t.br...@gmail.com>

Cristian Rinaldi

unread,
Oct 26, 2011, 11:27:11 PM10/26/11
to google-we...@googlegroups.com
To test I created a new view for Address without presenter injected into constructor. 
And the Address View is not injected into the TerceroEditor view.

And things are just fine.

This works well:

   @UiField
  AddressEditor2 address;  //AddressEditor is a concrete class.
 
  private final TerceroNewView.Presenter presenter;

  @Inject
  public TerceroEditor(  //Note: not inject sub-view AddressView, UiBinder make a implementation 
      @Named(Constans.TerceroNewPresenter) TerceroNewView.Presenter presenter) {

    this.presenter = presenter;
    ini();
  }
  
  private void ini(){
    root = uiBinder.createAndBindUi(this);
    res.erpLgkStyle().ensureInjected();
    presenter.onCreate(this);
  }


TerceroNewEditor.ui.xml part:
   ...
   ...
   <l:AddressEditor2 ui:field="address"></l:AddressEditor2>
   ...
   ...

//AddressView implements Editor<AddressProxy>

public class AddressEditor2 extends Composite implements AddressView {

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

  interface AddressEditor2UiBinder extends UiBinder<Widget, AddressEditor2> {
  }

  private HTMLPanel root;

  private AddressView.Presenter presenter;

  @UiField
  ValueBoxEditorDecorator<String> address;

  @UiField
  ValueBoxEditorDecorator<Integer> number;

  @UiField
  ValueBoxEditorDecorator<String> code;
  
  public AddressEditor2() {
    initWidget(uiBinder.createAndBindUi(this));
  }
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

If you inject the View with a Provider or AsyncProvider or directly not send the information of Address.
This does not work:

   @ UiField (provided = true)
   AddressView address //AddressView is a interface that Implements Editor<AddressProxy>
 
   private final TerceroNewView.Presenter presenter;

@Inject
public TerceroEditor(
      Provider<AddressView> addressView,
      @Named(Constans.TerceroNewPresenter) TerceroNewView.Presenter presenter) {

    this.address = addressView.get();
    this.presenter = presenter;
    ini();
 }

private void ini(){
    root = uiBinder.createAndBindUi(this);
    res.erpLgkStyle().ensureInjected();
    presenter.onCreate(this);
}


  TerceroNewEditor.ui.xml part:
   ...
   ...
   <l:AddressView ui:field="address"></l:AddressView>
   ...
   ...

//AddressView implemens Editor<AddressProxy>
public class AddressEditor implements AddressView {

  interface AddressWidgetUiBinder extends UiBinder<HTMLPanel, AddressView> {
  }
  
  private static AddressWidgetUiBinder uiBinder = GWT.create(AddressWidgetUiBinder.class);

  private HTMLPanel root;

  private AddressView.Presenter presenter;

  @UiField
  ValueBoxEditorDecorator<String> address;

  @UiField
  ValueBoxEditorDecorator<Integer> number;

  @UiField
  ValueBoxEditorDecorator<String> code;

  @Inject
  public AddressEditor(
      @Named(Constans.AddressNewPresenter) AddressView.Presenter presenter) {
    
    this.presenter = presenter;
    init();
  }
  
  private void init(){
    root = uiBinder.createAndBindUi(this);
    presenter.onCreate(this);
  }

  @Override
  public Widget asWidget() {
    return root;
  }
}

Gin Module

public class ViewModule extends AbstractGinModule {

  @Override
  protected void configure() {
    ....
    ....

    bind(AddressView.class).to(AddressEditor.class).in(Singleton.class);
    bind(TerceroNewView.class).to(TerceroEditor.class).in(Singleton.class);
   
    .....
    .....
   
 bind(TerceroNewView.Presenter.class).annotatedWith(Names.named(Constans.TerceroNewPresenter)).to(TerceroNewEditorPresenter.class);
    bind(AddressView.Presenter.class).annotatedWith(Names.named(Constans.AddressNewPresenter)).to(AddressNewPresenter.class);

  }
}
  


A.U.S Cristian Rinaldi

Teléfono Móvil: (0342) 155 238 083

www.logikas.com

Lisandro de la Torre 2643 Of 5 - 3000 - Santa Fe

Teléfono Fijo: (0342) 483 5138







2011/10/26 Cristian Rinaldi <cristian...@logikas.com>

Cristian Rinaldi

unread,
Oct 27, 2011, 6:25:18 PM10/27/11
to google-we...@googlegroups.com, cristian...@logikas.com
The error is when I declare an interface instead of a particular class implementation.
By example:

@UiField(provided = true)
AddressView address;  //Interface (not a concrete class)

Note that into file ui.xml the inclusion of widget also is a interface

by example:

<l:AddressView ui:field="address"></l:AddressView>

Now, when inject AddressView by constructor in the container view (TerceroNewEditor), and I asign the variable before that uibinder make a interface, aren't because Editor do not send values contained inside the AddressView.

Now, if I only change the declaration:

@UiField(provided = true)
AddressView address;

by

@UiField(provided = true)
AddressEditor address;  //implementation of AddressView
 
and either way that I assign (injection or direct  creation), Editor works well.

This is an error or is not covered?

Thanks and please, sorry for my english!!

Christian Goudreau

unread,
Oct 27, 2011, 6:27:23 PM10/27/11
to google-we...@googlegroups.com
What is AddressView is extending?

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/fcFfyRmlb1cJ.

To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.



--
Christian Goudreau

Thomas Broyer

unread,
Oct 27, 2011, 6:47:26 PM10/27/11
to google-we...@googlegroups.com, cristian...@logikas.com
If AddressView is neither an Editor nor an IsEditor, that's the expected behavior, as I told you before. The generator for the EditorDriver can only looks at the declared type of the fields and declared return types of the methods, if AddressView is not an editor, then the field will smply be ignored by the Editor framework. It really doesn't matter what the field value is exactly (well, actually, most –if not all– subinterfaces of Editor are dealt with at runtime, provided the field's type extends/implements Editor to begin with), or when it's initialized/assigned.

Cristian Rinaldi

unread,
Oct 27, 2011, 6:50:07 PM10/27/11
to google-we...@googlegroups.com
Hello Christian:

"AddressView extends View and Editor<AddressProxy>"

See below: 
}




Thomas Broyer

unread,
Oct 27, 2011, 7:00:22 PM10/27/11
to google-we...@googlegroups.com
Similarly, if AddressView has no subeditors (zero-arg methods with an Editor/IsEditor return type), it's basically useless.

Keep in mind that the generator looks at your classes, not the actual instances: it runs at compile-time to generate code.

Cristian Rinaldi

unread,
Oct 27, 2011, 7:18:33 PM10/27/11
to google-we...@googlegroups.com
Thanks thomas,

I see it clearly now.

It's a shame, I wanted the container interface does not depend on the particular implementation of Address. If this changes, I just wanted to change the bind in GIN.

Thanks.!!!!!

Reply all
Reply to author
Forward
0 new messages