creating resource automatically from editors

20 views
Skip to first unread message

Patrick Julien

unread,
Oct 2, 2010, 10:15:13 AM10/2/10
to google-web-tool...@googlegroups.com
What does it take exactly?

If I look at dynatblerf sample, there is an AddressEditor in a
PersonEditor and it just seems to work.

I have the same thing, I have a SecuritySettingsEditor inside another
Editor and when I get the EntityProxy back, the security settings
field is always null. What does it take for the editor to generate
the value?

Thomas Broyer

unread,
Oct 2, 2010, 10:38:25 AM10/2/10
to Google Web Toolkit Contributors
The DynatableRF sample's Person never has a 'null' Address; it might
be an "empty" Address instance, but never the null value. It might be
the reason.

Patrick Julien

unread,
Oct 2, 2010, 11:00:55 AM10/2/10
to google-web-tool...@googlegroups.com
But I am getting null for my child objects, that is the question, must
I make sure all child entities are created before given them to the
root editor? That doesn't make much sense to me

> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors

Patrick Julien

unread,
Oct 2, 2010, 12:02:10 PM10/2/10
to google-web-tool...@googlegroups.com
Even if I put in things manually, let's say

EditorContainer<OfficeHandle, HashSet<OfficeHandle>, OfficeEditor> offices;

which is a CompositeEditor

public class EditorContainer<T, C extends Collection<T>, E extends
Editor<T>> extends FlowPanel implements CompositeEditor<C, T, E>

I can set new up and place the HashSet<> manually inside the parent of
the office because it will get squashed the next time the editor is
flushed since EditorContainer gets setValue called with null

Patrick Julien

unread,
Oct 2, 2010, 4:42:07 PM10/2/10
to google-web-tool...@googlegroups.com
If anyone is hurting with this, it's because all values need to be set
to non null before they can be part of the editor framework, unless
you're using a composite

If you're using a composite, the idea is to set a non null container
value like so:


domainHandle = requests.create(DomainHandle.class);
r = requests.domainRequest().persist(getSessionId(), domainHandle);
driver = GWT.create(Driver.class);
driver.initialize(requests, view);
domainHandle = r.edit(domainHandle);
domainHandle.setOffices(new HashSet<OfficeHandle>()); // This
creates the empty set
domainHandle.setSecuritySettings(requests.create(SecuritySettingsHandle.class));

Then your composite will get called via the setValue method, this is
the set or list you newed up in your handle if you setup is OK

@Override
public void setValue(final C value) {
this.collection = value;
}

Then, when you're ready to flush, flush gets called, you just insert
whatever value you need in your collection

@Override
public void flush() {
for (int i = 0, j = editors.size(); i < j; i++) {
E subEditor = editors.get(i);
T value = chain.getValue(subEditor);

if (backing.get(i) != value)
backing.set(i, value);

collection.add(value);

BobV

unread,
Oct 2, 2010, 7:31:13 PM10/2/10
to google-web-tool...@googlegroups.com
It's possible to set a null field to a non-null value by making a Leaf
CompositeEditor. I'll update the DynaTableRf sample with something
better than this, but I think it demonstrates the point. The
assumption is that PersonProxy.getManager() returns null in the
default dataset.


public class ManagerSelector extends Composite implements
CompositeEditor<PersonProxy, PersonProxy, NameLabel>,
LeafValueEditor<PersonProxy> {

private EditorChain<PersonProxy, NameLabel> chain;
private NameLabel nameLabel = new NameLabel(new SimpleEventBus());
private PersonProxy manager;

public ManagerSelector() {
FlowPanel fp = new FlowPanel();
Button b = new Button("Choose randomly");

b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
DynaTableRequestFactory rf = DynaTableRf.getRequestFactory();

int i = new Random().nextInt(100);
rf.schoolCalendarRequest().getPeople(i, 1).to(
new Receiver<List<PersonProxy>>() {
@Override
public void onSuccess(List<PersonProxy> response) {
assert response.size() == 1;
setValue(response.get(0));
}
}).fire();
}
});

fp.add(b);
fp.add(nameLabel);
initWidget(fp);
}

public void flush() {
}

public String getPathElement(NameLabel subEditor) {
return "";
}

public PersonProxy getValue() {
return manager;
}

public void onPropertyChange(String... paths) {
}

public void setDelegate(EditorDelegate<PersonProxy> delegate) {
}

public void setEditorChain(EditorChain<PersonProxy, NameLabel> chain) {
this.chain = chain;
}

public void setValue(PersonProxy value) {
this.manager = value;

if (manager != null) {
chain.attach(manager, nameLabel);
}
}


--
Bob Vawter
Google Web Toolkit Team

Patrick Julien

unread,
Oct 2, 2010, 8:12:28 PM10/2/10
to google-web-tool...@googlegroups.com
This actually makes sense to me but if the composite editor is set or
a list, the framework will still be able to construct those types?

You have

>    CompositeEditor<PersonProxy, PersonProxy, NameLabel>,
>    LeafValueEditor<PersonProxy> {

But if the generic parameter was a collection, wouldn't the fact that
it's a leaf editor prevent the framework from entering sub-editors?

> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors

BobV

unread,
Oct 2, 2010, 8:34:36 PM10/2/10
to google-web-tool...@googlegroups.com
> But if the generic parameter was a collection, wouldn't the fact that
> it's a leaf editor prevent the framework from entering sub-editors?

Hence the explicit chain.attach() call. If you wanted to edit an
optional list, you could replace the nameLabel with the ListEditor
adaptor class. Assuming that a PersonMight have a list of mentors:

// That's editor.client.adapters.ListEditor
MentorSelector implements LeafValueEditor<List<Person>>,
CompositeEditor<List<Person>, List<Person>, ListEditor<Person,
NameLabel>>

Patrick Julien

unread,
Oct 2, 2010, 8:45:22 PM10/2/10
to google-web-tool...@googlegroups.com
thank you for the clarification, I get it

I don't suppose you have advice for using a mutable CellTable in the
editor framework?

> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors

BobV

unread,
Oct 2, 2010, 9:07:07 PM10/2/10
to google-web-tool...@googlegroups.com
On Sat, Oct 2, 2010 at 8:45 PM, Patrick Julien <pju...@gmail.com> wrote:
> thank you for the clarification, I get it

I'm adding a new adapter class to handle this case, since optional
fields seems like a common thing to see and implementing it manually
requires a lot of boilerplate.

> I don't suppose you have advice for using a mutable CellTable in the
> editor framework?

Does the HasDataEditor adapter work for you?

Patrick Julien

unread,
Oct 2, 2010, 9:20:17 PM10/2/10
to google-web-tool...@googlegroups.com
On Sat, Oct 2, 2010 at 9:07 PM, BobV <bo...@google.com> wrote:
> On Sat, Oct 2, 2010 at 8:45 PM, Patrick Julien <pju...@gmail.com> wrote:
>> thank you for the clarification, I get it
>
> I'm adding a new adapter class to handle this case, since optional
> fields seems like a common thing to see and implementing it manually
> requires a lot of boilerplate.

I think it will see a lot of use.

>
>> I don't suppose you have advice for using a mutable CellTable in the
>> editor framework?
>
> Does the HasDataEditor adapter work for you?
>

It doesn't, because each row can be edited... but cell table doesn't
give you access to its rows, only a column format. Here, the editor
are actually the cells. So a button cell is a remove button. A edit
text cell is the number and a selection cell is the phone type.

I can just make a table but cell table added all this work to with
keyboard, mouse, blur, etc., events.

Patrick Julien

unread,
Oct 3, 2010, 10:24:09 AM10/3/10
to google-web-tool...@googlegroups.com
The biggest problem I have so far with HasDataEditor is that it
completely ignores HasDataEditor mutation of the data source.

so

HandlerRegistration addRangeChangeHandler(RangeChangeEvent.Handler handler);

HandlerRegistration addRowCountChangeHandler(
RowCountChangeEvent.Handler handler);

aren't used. Because of that, it's not able to handle the scenarios
of the inline list that adds or remove items. In this case, a simple
list of phones. This list changes if we create a row and it also
changes if we hit the remove button on a row

BobV

unread,
Oct 3, 2010, 10:54:30 AM10/3/10
to google-web-tool...@googlegroups.com
On Sun, Oct 3, 2010 at 10:24 AM, Patrick Julien <pju...@gmail.com> wrote:
> The biggest problem I have so far with HasDataEditor is that it
> completely ignores HasDataEditor mutation of the data source.

This is intentional. HasDataEditor and its superclass, ListEditor
require that mutations of the structure of the list occur through the
wrapper retrieved from ListEditor.getList().

Patrick Julien

unread,
Oct 3, 2010, 10:57:34 AM10/3/10
to google-web-tool...@googlegroups.com
Any sample somewhere then because I am not getting how to use this
class properly

> --
> http://groups.google.com/group/Google-Web-Toolkit-Contributors

Thomas Broyer

unread,
Oct 3, 2010, 11:13:20 AM10/3/10
to Google Web Toolkit Contributors


On Oct 3, 4:57 pm, Patrick Julien <pjul...@gmail.com> wrote:
> Any sample somewhere then because I am not getting how to use this
> class properly

There's sample code in ListEditor.getList()'s javadoc; but I think
HasDataEditor might be missing a call to the HasData's setRowCount
method. And/or maybe HasDataEditor should internally use a
ListDataProvider so that changes to the list are reflected in the
HasData? (or are *we* rather supposed to wrap the ListEditor#getList()
in a ListDataProvider to add/remove values?)

(disclaimer: haven't yet took the time to code a sample, still only
judging by my reading of the code)

BobV

unread,
Oct 3, 2010, 11:21:35 AM10/3/10
to google-web-tool...@googlegroups.com
On Sun, Oct 3, 2010 at 10:57 AM, Patrick Julien <pju...@gmail.com> wrote:
> Any sample somewhere then because I am not getting how to use this
> class properly

The FavoritesWidget in the DynaTableRf sample uses ListEditor. See
the uses of the displayedList field. It works this way so that
re-ordering operations on the list (like calling Collections.sort())
will keep both the backing data and the displayed list of editors in
sync.

Patrick Julien

unread,
Oct 3, 2010, 11:43:18 AM10/3/10
to google-web-tool...@googlegroups.com

I'm aware of this widget but I'm trying to use HasDataEditor with a
CellTable so it doesn't exactly translate 1:1

BobV

unread,
Oct 3, 2010, 12:25:22 PM10/3/10
to google-web-tool...@googlegroups.com
> There's sample code in ListEditor.getList()'s javadoc; but I think
> HasDataEditor might be missing a call to the HasData's setRowCount
> method.

The HasDataEditorSource is indeed missing a call to setRowCount(). It
should check to see if the size of the exported list has changed
whenever create() or dispose() is called.

Patrick Julien

unread,
Oct 3, 2010, 12:28:14 PM10/3/10
to google-web-tool...@googlegroups.com
I have this almost going.

I hit a bug in public

SimpleEntityProxyId.equals

boolean equals(Object o) {
if (!(o instanceof SimpleEntityProxyId<?>)) {
return false;
}
SimpleEntityProxyId<?> other = (SimpleEntityProxyId<?>) o;
if (!proxyClass.equals(other.proxyClass)) {
return false;
}
return (clientId != NEVER_EPHEMERAL && clientId == other.clientId)
|| serverId.equals(other.serverId);
}

both entities here were created locally.

So here I'll have clientId == 12 and other.clientId == 13 for example.

So that part is OK but then it goes into the ||

serverId here is null because it never got into the server, so it throws an NPE.

Patrick Julien

unread,
Oct 3, 2010, 12:54:13 PM10/3/10
to google-web-tool...@googlegroups.com
Reduced test case:

PhoneHandle handle1 = rc.create(PhoneHandle.class);
PhoneHandle handle2 = rc.create(PhoneHandle.class);

assert !handle1.equals(handle2);

throws because serverId is null in SimpleEntityProxyId

Reply all
Reply to author
Forward
0 new messages