Monday, January 31, 2011

RequestFactory strange behavior.

WHAT I HAVE:

I have a form who contains some ValueBoxEditorDecorator elements (who are text boxes).
In one of that element's, customer write his private number. Customer private number is validated with JSR303 validation. I use gwt 2.1.1.

I have 3 cases:
1. If customer number isn't valid, message is displayed near input box.
2. If number is valid and customer didn't exist in database, server throws an exception and enable register customer button so customer can be registered in the system.
3. If customer is found, customer data is loaded in other fields and we are all happy :)

The code who do the whole thing is:

class CustomerEditorView extends Composite implements Editor<CustomerProxy> {
interface Driver extends RequestFactoryEditorDriver<CustomerProxy, CustomerEditorView>{}
Driver driver = GWT.create(Driver.class);
@UiField
ValueBoxEditorDecorator<String> firstName;

@UiField
ValueBoxEditorDecorator<String> surname;

@UiField
ValueBoxEditorDecorator<String> code;

CustomerRequest request;
CustomerProxy customer;

public CustomerEditorViewImpl() {
initWidget(uiBinder.createAndBindUi(this));
driver.initialize(this);
}
........

public void edit(CustomerProxy customer) {
// create request who will manage this proxy
request = requestFactory.customerRequest();

// if customer is null create new empty proxy
if (customer == null || Strings.empty(customer.getCode())) {
customer = request.create(CustomerProxy.class);
}

if (this.customer != customer) {
customer = CustomerProxyCopier.copy(customer, request); // create new proxy and make a deep copy
}

this.customer = customer;
driver.initialize(this);
driver.edit(this.customer, request);
}

// this method need to check if customer is registered in the system
// if customer is registered then return customer data and fill another fields
// if customer is not registered catch exception and enable register customer button.
// if customer code isn't valid show validation error message
public void onCheckCustomerButtomPressed(String code){
driver.flush();

request.getCustomerByCode(String code).fire(new Receiver<CustomerProxy>(){
@Override
public void onSuccess(CustomerProxy response) {
edit(response); // calls upper method
}

@Override
public void onFailure(ServerFailure error) {
enableRegisterButton();

// adds customer to edit again BECAUSE
// if not added again proxy is locked, cant be modified,
// method driver.flush() can't be called
// newly added customer information can't be loaded from editor to proxy
display(customer);
}

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

THE STORY:

When the form is loaded for first time, CustomerEditorView.edit() method is called with null parameter. That method gets new Request, create new empty proxy and add proxy to the editor driver. Customer write his code in code field, and press check button. Check button calls method onCheckCustomerButtomPressed() and give customer code as parameter. Request factory send code to the server. But customer make a mistake and wrote wrong code. JSR303 validation validate the code and return validation error message Receiver.onViolation() method is called, and message is displayed on the screen. Customer see the error, make code correction and press check button. Now the code is valid and system check if user exists in database. When user doesn't exist, system throws exception and Receiver.onFailure() method is called. When this method is called, proxy is locked and can't be edited. So edit method is called again to create new proxy with which I can work with. Now customer fill another field's and press the registerbutton. However customer edit and his code and again the code validation fail. System return validation message and Receiver.onViolation() method is called again and driver.setViolations(errors); is executed again.

THE PROBLEM:
The problem is that when driver.setViolations(errors) is called, errors isn't displayed on the screen. In my investigation I get to:
class AbstractRequestFactoryEditorDriver line 163-164
....
// Only attach the error to the first delegate in a co-editor chain.
leafDelegates.get(0).recordError(error.getMessage(), null, error);
....

in this code, the first element from leafDelagates is allways used to show violation errors. But when another object is given to the editor, he is added in leafDelegates array as second element. (or N element if user reuse driver N times driver.edit()). But when violation errors is loaded they are allways dispatched to first leafElement. The error isn't displayed because error is given to wrong delegate and proxy is different. I try to call driverInitialize before driver edit method but without efect.
Does we allways need to get first element from leaf and give him errors? What if we get the last element, that one who is last added and proxy points to him? 

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-web-toolkit@googlegroups.com.
To unsubscribe from this group, send email to google-web-toolkit+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

No comments:

Post a Comment