Home » Eclipse Projects » Eclipse Scout » Validation rules(User defined validation at server side only)
Validation rules [message #776521] |
Sun, 08 January 2012 12:08  |
Eclipse User |
|
|
|
If you are setting mandatory to true or define a max length on a field, at runtime validation rules are created and executed. Default they are only executed at the client but you can make them execute at the server (See http://wiki.eclipse.org/Scout/Concepts/Communication).
I need additional rules that are only executed at the server, because I have to check the database.
What I already did is create a check at the server side and throw a VetoException. This works fine but is not a very nice integration into the Scout framework. A problem with this is that or the "standard" Scout exceptions are thrown or my VetoException is thrown but they are not collected and presented in one list of errors.
So the question is, can I create my own validation rules that are only excuted at the server side and that are well integrated in the Scout framework.
regards Bertin
|
|
| |
Re: Validation rules [message #777337 is a reply to message #776584] |
Tue, 10 January 2012 05:00   |
Eclipse User |
|
|
|
Hi,
checking at the client side is very usefull for the end user and means direct feedback.
On the server however, I want to be absolutely sure, that whatever I store in the database is correct. So right before the data is stored in the database I do some checks. If a mandatory value is empty, often this means that I, as a developer, have made a mistake in my client application.
But what if I expose the same service in another way like a webservice. Who checks the input then. The only point to be absolutely sure that the data is valid is checking it just before you save it into the database.
So what I do now in the ProcessService is:
@Override
public AccountFormData store(AccountFormData formData) throws ProcessingException {
if (!ACCESS.check(new UpdateAccountPermission())) {
throw new VetoException(Texts.get("AuthorizationFailed"));
}
Validation.validateBeforeUpdate(new AccountValidator(), formData);
SQL.update(
"UPDATE account SET" +
" name = :naam," +
" valid_through = :geldigTot," +
" fk_medewerker = :medewerker," +
" fk_client = :client, " +
" active = :aktief" +
" WHERE id = :accountNr", formData);
return formData;
}
The AccountValidator makes sure that everything is correct. It can check the database, collect multiple errors and at the end it throws an VetoException. It works OK but the only drawback is that there is no real integration with the Scout validation. So the user will get messages from the scout validation or from my own validation even if they are both run server-side.
I was curious if there is some integration possible and if there is a way to add my server-side business rules and or validations to the scout framework.
regards Bertin
|
|
| | |
Re: Validation rules [message #779630 is a reply to message #777993] |
Mon, 16 January 2012 03:18  |
Eclipse User |
|
|
|
Hi Bertin,
What you write is absolutely right in the following semantics:
Client form validation is a user convenience to not unnecessarily query the back-end.
Central input validation takes place in the server using a IValidator.
It is based on annotations done on service interface method parameters such as
@Mandatory, @MinValue, @MaxValue,...
For FormData objects there is an additional layer of input validation that is based on security methods
directly placed in the form data itself.
This means, a form data that is used in a webservice is checked in the scout server the same way as it is checked when it is used in a form. Provided that is contains the correpsonding rule maps inside the formdata class.
For your code and in particular when using webservices I would suggest that you add a custom annotation to the parameter in the service,
where you perform your custom checks.
@Override
public AccountFormData store(@ValidateAccountUpdate AccountFormData formData) throws ProcessingException {
SQL.update(
...
return formData;
}
The annotation ValidateAccountUpdate can be written similar to org.eclipse.scout.rt.shared.validate.annotations.Mandatory.
All following is just customizing of default input validation handling for your project(s), for simplicity i will prefix it with "Bki".
Override ServiceTunnelServlet
public class BkiTransactionDelegate extends ServiceTunnelServlet {
...
@Override
protected ServiceTunnelResponse runServerJobTransactionWithDelegate(ServiceTunnelRequest req, Bundle[] loaderBundles, Version requestMinVersion, boolean debug) throws Exception {
return new BkiTransactionDelegate(loaderBundles, requestMinVersion, debug).invoke(req);
}
}
Override DefaultTransactionDelegate this is where your BkiValidator is effectively integrated.
public class BkiTransactionDelegate extends DefaultTransactionDelegate {
public BkiTransactionDelegate(Bundle[] loaderBundles, Version requestMinVersion, boolean debug) {
super(loaderBundles, requestMinVersion, debug);
}
@Override
protected void validateInput(IValidationStrategy validationStrategy, Object service, Method op, Object[] args) throws Exception {
new BkiValidator(validationStrategy).validateMethodCall(op, args);
}
}
Subclass DefaultValidator to integrate the custom annotation 'ValidateAccountUpdate'
public class BkiValidator extends DefaultValidator {
public BsiCrmValidator(IValidationStrategy validationStrategy) {
super(validationStrategy);
}
@Override
protected void addCheckFromAnnotation(ValidateCheckSet localSet, ValidateCheckSet subtreeSet, Annotation a, Object value) throws Exception {
if (a.annotationType() == ValidateAccountUpdate.class) {
ValidateAccountUpdate x = (ValidateAccountUpdate) a;
(x.subtree() ? subtreeSet : localSet).addCheck(new ValidateAccountUpdateCheck());
return;
}
super.addCheckFromAnnotation(localSet, subtreeSet, a, value);
}
Finally ValidateAccountUpdateCheck is the implementation of your server-side check.
public class ValidateAccountUpdateCheck implements IValidateCheck {
public static final String ID = "validateAccountUpdate";
public ValidateAccountUpdateCheck() {
}
@Override
public String getCheckId() {
return ID;
}
@Override
public boolean accept(Object obj) {
return obj instanceof AccountFormData;
}
@Override
public void check(Object obj) throws Exception {
AccountFormData formData=(AccountFormData)obj;
//XXX check the form data
}
@Override
public String toString() {
return getClass().getSimpleName();
}
}
|
|
|
Goto Forum:
Current Time: Wed Jul 23 14:15:14 EDT 2025
Powered by FUDForum. Page generated in 0.04346 seconds
|