A user of GWT-VL asked me if it is possible to use GWT-VL in conjunction with the Restlet-GWT project. The answer was ambivalent. Because you could already use GWT-VL as a client side only validation library with Restlet-GWT, but you could not profit from the connection between server side and client side, which is surely one of the strong points of the GWT-VL library. Before the 0.7 release line of GWT-VL the library was only able to connect server and client side with throwing ValidationException’s that would be sent back to the client with the use of RPC. The good thing with that is, that you stay on the Java road in that you will catch RuntimeExceptions of type ValidationException which should feel quite naturally to a Java programmer. Anyway, the problem with that approach is that it only works if you connect your client side via RPC to the server side. Clearly, Restlet-GWT doesn’t do that. So I decided to think about a way how I could integrate the server to client connection without the use of RPC. What I came up with is not exactly an Restlet-GWT integration but a general way of connecting the server and the client side of GWT-VL. The idea is to just pack the validation messages into Strings and pass them from the server side to the client side. With this approach I think virtually every framework will be able to make use of GWT-VL. So if you have choosen to communicate with your services via RPC, you just use the RuntimeException mechanism. If you do not use RPC than you are now able to let GWT-VL serialize its server side ValidationException’s into Strings that you can send back to your client. The client side has added functionality that allows it to process these Strings the same way it would process the ValidationException’s sent via RPC.
So enough with talking, lets dive into how you can gain the benefits of the use of a sophisticated validation library named GWT-VL while using RestletGWT on the backend.
The validation specifics on the client side have already been initially described on the first two posts about GWT-VL so if you haven’t read them by now I would advise you on reading them first here (Part 1) and here (Part 2).
Lets assume we have a page with two input fields which we try to validate on the client and on the server. The client side code could look something like this:
-
final TextBox codewordBox = new TextBox();
-
final TextBox tokenBox = new TextBox();
-
-
validator.addValidators("codeword",
-
new IntegerValidator(codewordBox)
-
.addActionForFailure(new StyleAction("redBorder"))
-
);
-
-
validator.addValidators("token",
-
new IntegerValidator(tokenBox)
-
.addActionForFailure(new StyleAction("redBorder"))
-
);
This is not different from the usual way of using the GWT-VL library. Differences arise when we start facilitating the server side. First we call the server side from the client side and handing over some input to the server side.
-
button.addClickListener(new ClickListener() {
-
public void onClick(Widget sender) {
-
if(!validator.validate())
-
return; //Some client side validation errors occured, validator actions are fired automatically
-
// Add an AJAX call to the server
-
final Client client = new Client(Protocol.HTTP);
-
Form form = new Form();
-
form.add("codeword", codewordBox.getText());
-
form.add("token", tokenBox.getText());
-
client.post("http://localhost:8888/validate", form.getWebRepresentation(), new Callback() {
-
@Override
-
-
if(!validator.processSerializedValidationErrorsSilently(ret)) {
-
//The server side signaled a validation error.
-
//All the actions will have been automatically invoked by
-
//the ValidationProcessor (as usual), so just return.
-
-
return;
-
}
-
-
//If we get here no validation errors were received from the server side
-
//We would now direct the user to some other page, show him a success message, etc.
-
}
-
});
-
}
-
});
Here we see the standard GWT-VL stuff like: validator.validate() that just invokes all the client side validators and triggers the specific actions if an error occured. One thing that is new is the validator.processSerializedValidationErrorsSilently method. But before we come to that let me explain how the call to the server works. We use RestletGWT functionality for passing the value of the text boxes to the REST service. We use the POST method to post the data to the server side service. After the service returns its data, we feed whatever came from the service to the validator.processSerializedValidationErrorsSilently method. This method will automatically check whether the returned string denotes a serialized validation exception that the ValidationProcessor should consume or not. If it finds out that the returned String denotes a ValidationException in serialized form, it will be parsed and all the actions specified on the client side for the fields that the server side has deemed errorneous are invoked. If it sees that the returned String is not a serialized ValidationException, it just silently (thus the name) returns true and the code can assume that no error came from the server side (at least no GWT-VL validation error).
So let’s see what exactly happens on the server side. We have a Restlet resource that supports the POST method and validates the input:
-
public class ValidateResource extends Resource {
-
-
super(context, request, response);
-
getVariants().add(new Variant(MediaType.TEXT_PLAIN));
-
this.setModifiable(true); //Needed to support POST
-
}
-
-
@Override
-
public void acceptRepresentation(Representation entity) throws ResourceException {
-
Form form = new Form(entity);
-
//Get the values from the post
-
-
int codeword = -1;
-
int token = -1;
-
-
//We convert the strings coming from the form to their intended type
-
//Note: If we would use RPC we wouldn’t need this step ;>
-
-
try {
-
try {
-
ServerValidation.exception("noInteger", "codeword", text1);
-
}catch(ValidationException ex2) {
-
getResponse().setEntity(getValidationRepresentation(ex2));
-
return;
-
}
-
}
-
-
try {
-
try {
-
ServerValidation.exception("noInteger", "token", text1);
-
}catch(ValidationException ex2) {
-
getResponse().setEntity(getValidationRepresentation(ex2));
-
return;
-
}
-
}
-
-
try {
-
new ServerValidation(false)
-
.inRange(codeword,0, 100, "codeword")
-
.inRange(token,0, 100, "token")
-
.validate();
-
}catch(ValidationException ex) {
-
//Ok, we got an validation error we talk that back to the client and quit the server side processing
-
getResponse().setEntity(getValidationRepresentation(ex));
-
return;
-
}
-
StringRepresentation str = new StringRepresentation("Success");
-
getResponse().setEntity(str);
-
}
-
-
private StringRepresentation getValidationRepresentation(ValidationException ex) {
-
String serializedException = null;
-
-
//Serialize the validation exception to a string which can be send over the wire to the client
-
serializedException = ServerValidation.serializeValidationException(ex);
-
-
return new StringRepresentation(serializedException);
-
}
-
}
Of course you probably have some code to make the parsing easier to write. You should create a method that will do this for you. But for clarity reasons I did go the “verbose” way. So you see what exactly needs to be done.
That’s basically all there is to do to get server and client side validation to act together as a a pair like you are used to when using GWT-VL and all without RPC.
The first release to provide the forementioned features is the 0.7a release (but you really should download the newest 0.7b) wich you can get from Sourceforge.
Note: The new release also features support for parameterized custom validation messages.
So, thanks for listening and if you have comments, questions or feature requests do not hesitate to drop me a mail or use the Tracker and Forums on Sourceforge.
Kind regards,
Anatol Mayen
