PDA

View Full Version : [FIXED] Error with Record -- cannot set a new value



posta07
28 Jul 2008, 12:57 PM
As of revision 637, the Record class has some logic that causes setting a property to fail if it's not already in the map.
Things were working fine before rev 637.

The code from line 216 in the Record class is as follows:


if (model.<Object>get(name).equals(value)) {
return;
}When changing it to this, it works:


if(model.get(name) != null && model.get(name).equals(value)) {
return;
}Is there a reason why it was changed from rev 636 to 637 to what it is at present?

To illustrate the issue, i've included the following code. It's an addition to what Grandiosa posted a few weeks ago (Thanks Grandiosa, i've learned a lot from it!!!!!)

I am using the latest build from the trunk (as of July 28, 2008) and I am running in Hosted mode.



DateTimeFormat formatter = DateTimeFormat.getFormat("dd.mm.yyyy");
ListStore<Member> store;
TextArea ta;
Integer count = 0;
boolean newRecord = false;

public class CarModel extends BaseModel implements Serializable {
public CarModel() {

}

public CarModel( String make, String model, Integer year) {


set("car_make", make);
set("car_model", model);
set("car_year", year);

}

public Integer getYear() {
return (Integer) get("car_year");
}

public String getMake() {
return (String) get("car_make");

}

public String getModel() {
return (String) get("car_model");
}

}

public class Member extends BaseModel implements Serializable {
public Member() {
}

public Member(Integer id, String name, Date birth, CarModel car) {
set("id", id);
set("name", name);
set("birth", birth);
set("car", car);
}

public Integer getId() {
return (Integer) get("id");
}

public String getName() {
return (String) get("name");
}

public Date getBirthDate() {
return (Date) get("birth");
}

public CarModel getCar() {
return (CarModel) get("car");
}

public String getFormattedBirthDate() {
return formatter.format(getBirthDate());
}


@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Member: ").append(",").append(getName());
builder.append(",").append(getFormattedBirthDate()).append(", Car:");
if(getCar() == null) {
builder.append("NULL");
}
else
{
builder.append(getCar().getMake());
}

return builder.toString();
}
}

private List<Member> getData() {
List<Member> mlist = new ArrayList<Member>();

CarModel honda = new CarModel("Honda", "Accord", 2006);
CarModel mazda = new CarModel("Mazda", "6", 2007);
CarModel mercedes = new CarModel("Mercedes", "E350", 2008);

mlist.add(new Member(count++, "Rebecca", formatter.parse("01.01.1988"), honda));
mlist.add(new Member(count++, "Farah", formatter.parse("04.08.1991"), mazda));
mlist.add(new Member(count++, "Angelina", formatter.parse("29.10.1981"), mercedes));

return mlist;
}

private List<CarModel> getCars() {
List<CarModel> cars = new ArrayList<CarModel>();

CarModel honda = new CarModel("Honda", "Accord", 2006);
cars.add(honda);

CarModel mazda = new CarModel("Mazda", "6", 2007);
cars.add(mazda);

CarModel mercedes = new CarModel("Mercedes", "E350", 2008);
cars.add(mercedes);

return cars;
}

public void onModuleLoad() {

Viewport viewport = new Viewport();
viewport.setLayout(new FitLayout());

ContentPanel panel = new ContentPanel();
panel.setFrame(true);
panel.setButtonAlign(Style.HorizontalAlignment.CENTER);
panel.setHeading("Member edit");
panel.setLayout(new BorderLayout());

LayoutContainer west = new LayoutContainer(new FitLayout());
BorderLayoutData wData = new BorderLayoutData(Style.LayoutRegion.WEST, 250);
LayoutContainer center = new LayoutContainer(new RowLayout());
BorderLayoutData cData = new BorderLayoutData(Style.LayoutRegion.CENTER);

panel.add(west, wData);
panel.add(center, cData);

final DataList list = new DataList();
list.setSelectionMode(Style.SelectionMode.SINGLE);
list.setFlatStyle(true);
list.setBorders(false);

west.add(list);

store = new ListStore<Member>();
store.setMonitorChanges(true);
store.add(getData());

final DataListBinder<Member> binder = new DataListBinder<Member>(list, store);
binder.setDisplayProperty("name");
binder.setStringProvider(new ModelStringProvider<Member>() {
public String getStringValue(Member member, String property) {
Record r = store.getRecord(member);
if (r.isDirty()) {
return "<span style='color: red'>" + r.get("id") + " - "
+ r.get("name") + "</span>";
}
else {
return "" + member.getId() + " - " + member.getName();
}
};
});
binder.init();

final TextField idText = new TextField();
idText.setFieldLabel("Id");
final TextField nameText = new TextField();

KeyListener keyl = new KeyListener() {
@Override
public void componentKeyUp(ComponentEvent event) {
if(!newRecord){
Record member = store.getRecord((Member) list.getSelectedItem()
.getModel());
member.beginEdit();
member.set("name", nameText.getValue());
member.endEdit();
}
}
};
nameText.addKeyListener(keyl);

nameText.setFieldLabel("Name");
final TextField birthText = new TextField();
birthText.setFieldLabel("Birthdate");

final ComboBox<CarModel> carComboBox = new ComboBox<CarModel>();
carComboBox.setFieldLabel("Car");
carComboBox.setDisplayField("car_make");
carComboBox.setAllowBlank(false);
ListStore<CarModel> carStore = new ListStore<CarModel>();
carStore.add(getCars());
carComboBox.setStore(carStore);


idText.setEnabled(false);
nameText.setEnabled(false);
birthText.setEnabled(false);
carComboBox.setEnabled(false);

final FormPanel form = new FormPanel();
form.setHeaderVisible(false);
form.setWidth(350);

form.add(idText);
form.add(nameText);
form.add(birthText);
form.add(carComboBox);

list.addListener(Events.SelectionChange, new Listener<ComponentEvent>() {
public void handleEvent(ComponentEvent ce) {
DataList l = (DataList) ce.component;
Record member = store.getRecord((Member) l.getSelectedItem().getModel());
idText.setValue(member.get("id"));
nameText.setValue(member.get("name"));
birthText.setValue(formatter.format((Date) member.get("birth")));
carComboBox.setValue((CarModel)member.get("car"));

nameText.setEnabled(member.isDirty());
carComboBox.setEnabled(member.isDirty());

}
});

ToolBar toolBar = new ToolBar();
TextToolItem tti1 = new TextToolItem("Edit Record");
tti1.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
if (list.getSelectedItem() != null && !newRecord) {
Record member = store.getRecord((Member) list.getSelectedItem()
.getModel()); // idempotent
member.beginEdit(); // idempotent

member.setDirty(true);
member.endEdit();
nameText.setEnabled(true);
carComboBox.setEnabled(true);

store.update((Member) member.getModel());
showRecordsUnderEditing();
}
}
});
TextToolItem tti2 = new TextToolItem("Commit Record");
tti2.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {

if(newRecord) {

Member model = new Member(count++, (String)nameText.getValue(),
formatter.parse((String)birthText.getValue()), carComboBox.getValue());


newRecord = false;




idText.setEnabled(false);
nameText.setEnabled(false);
birthText.setEnabled(false);
carComboBox.setEnabled(false);

store.add(model);
binder.setSelection(model);


showRecordsUnderEditing();

}
else {
if (list.getSelectedItem() != null) {
Record member = store.getRecord((Member) list.getSelectedItem()
.getModel()); // idempotent
if (member.isDirty()) {
member.set("name", nameText.getValue());
member.set("car", carComboBox.getValue());
member.endEdit();
member.commit(false);
nameText.setEnabled(false);
carComboBox.setEnabled(false);
store.update((Member) member.getModel());
showRecordsUnderEditing();
}
} }
}
});

TextToolItem tti3 = new TextToolItem("Commit All");
tti3.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
store.commitChanges();
nameText.setEnabled(false);
for (Member m : store.getModels()) {
store.update(m);
}
showRecordsUnderEditing();
}
});

TextToolItem tti4 = new TextToolItem("New Record");
tti4.addSelectionListener(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {


newRecord = true;




idText.setEnabled(false);
idText.reset();
nameText.setEnabled(true);
nameText.reset();

birthText.setEnabled(true);
birthText.reset();

carComboBox.setEnabled(true);
carComboBox.reset();

showRecordsUnderEditing();
}
});





toolBar.add(tti4);
toolBar.add(tti1);
toolBar.add(tti2);
toolBar.add(tti3);

ContentPanel wrapper = new ContentPanel(new FitLayout());
wrapper.setFrame(false);
wrapper.setHeaderVisible(false);
wrapper.setTopComponent(new WidgetComponent(new Label(
"Records currently under editing")));

ta = new TextArea();
wrapper.add(ta);

form.setTopComponent(toolBar);

center.add(form, new RowData(1, -1));
center.add(wrapper, new RowData(1, 1, new Margins(10)));

viewport.add(panel, new FitData(10));

RootPanel.get().add(viewport);

}

/**
* hack to force a record dirty ( we need a Record.setDirty() method)
*
* @param member
*/
private void forceDirty(Record member) {
if (member.get("__foo__") != null) {
Integer v = (Integer) member.get("__foo__");
member.set("__foo__", v + 1);
}
else {
member.set("__foo__", 0);
}
}

private void showRecordsUnderEditing() {
if (store.getModifiedRecords().isEmpty()) {
ta.setValue("");
}
else {
StringBuffer mods = new StringBuffer();
for (Record r : store.getModifiedRecords()) {
mods.append(r.getModel().toString()).append("\n");
}
ta.setValue(mods.toString());
}
}1. Paste the code into a module
2. Run the code
3. Click "New Record"
4. Type in dummy values for Name and Birthdate ONLY (leave car blank) Note the format for the date
5. Click "Commit Record"
6. Highlight the newly created record and click "Edit Record"
7. Select a car
8. Click "Commit Record"
NOTICE THE UNCAUGHT EXCEPTION IN THE HOSTED-MODE WINDOW.

gslender
28 Jul 2008, 1:28 PM
quick question - should your models implement IsSerializable (rpc) or Serializable (java.io) ??

posta07
28 Jul 2008, 1:47 PM
As they are not transmitted through a stream, I guess they do not HAVE to imlement serializable. To stay consistent (since normally I am transmitting them through RPC), I mark them as serializable.

gslender
28 Jul 2008, 3:11 PM
To stay consistent (since normally I am transmitting them through RPC), I mark them as serializable.

No problems - just thinking about the following FAQ though and was wondering if you had a "good" reason for using java.io

http://code.google.com/support/bin/answer.py?answer=55196&topic=10210

posta07
28 Jul 2008, 3:17 PM
wondering if you had a "good" reason for using java.io

Good point. Seems IsSerializable is preferred.

Since the GXT framework uses the java.io version of Serializable, I guess I was using it for consistency along those ends too(for example, BaseModelData). Switching to IsSerializable will have to be the way to go.

Cheers.

darrellmeyer
28 Jul 2008, 6:06 PM
As of revision 637, the Record class has some logic that causes setting a property to fail if it's not already in the map.
Things were working fine before rev 637.
Fix is in SVN.


quick question - should your models implement IsSerializable (rpc) or Serializable (java.io) ??
IsSerializable was needed in GWT < 1.5. With 1.5, Serializable is now supported.