I'm dealing with a Webflow application where I may have to submit the current form in order to delete a child record (complex workflow, sorry).
The problem is that if the user enters junk data into the form and then presses the "delete" button, the binding and/or validation will fail and the form will never be submitted.
Hence, if they enter junk data, they cannot delete the record.
What is the preferred way of dealing with users entering "junk" data in web forms, particularly entering non-numeric data in numeric fields? I have a Spring form backing object that looks like this:
public class MyFormInfo implements Serializable {
private String myName;
private Integer myNumber;
}
If the user enters junk in the myName field I can ignore that during validation. However if they enter junk in the myNumber field and the binding fails, I have no good way to trap that and I can't submit the form.
Anybody have a good way to deal with this?
Have a look at this answer as well, but in summary there is no good way to add an error message in the case of type mismatch at conversion time.
The mechanisms available (property editors, converters, bean validation) are not meant to deal with a type mismatch.
The best solution is probably to do the validation on the client side via Javascript via some field mask that only accepts numerics. Then on the server a type mismatch would only occur in case of a bug, so the unhandled error could be acceptable.
For doing this on the server, it's possible to add a String property to the DTO, and apply a bean validation:
#Pattern(regexp = "{A-Za-z0-9}*")
String numericField;
Then via bean validation is possible to add error messages to the page, see this example.
If you want to avoid decimal number input in Integer fields, you can do it like this:
In the HTML-form you can do:
<div class="form-outline">
<input type="number" min=1 max=100 required/>
</div>
In the Java-Form you can do:
#NotNull
#Max(value = 100)
#Min(value = 1)
#NumberFormat
private Integer countOfRooms = null;
Related
I am currently programming a REST service and a website that mostly uses this REST service.
Model:
public class User {
private String realname;
private String username;
private String emailAddress;
private String password;
private Role role;
..
}
View:
One form to update
realname
email address
username
Another form to update the role
And a third form to change the password
.
Focussing on the first view, which pattern would be a good practice?
PUT /user/{userId}
imho not because the form contains only partial data (not role, not password). So it cannot send a whole user object.
PATCH /user/{userId}
may be ok. Is a good way to implement it like:
1) read current user entity
2)
if(source.getRealname() != null) // Check if field was set (partial update)
dest.setRealname(source.getRealname());
.. for all available fields
3) save dest
POST /user/{userId}/generalInformation
as summary for realname, email, username
.
Thank you!
One problem with this approach is that user cannot nullify optional fields since code is not applying the value if (input is empty and value) is null.
This might be ok for password or other required entity field but for example if you have an optional Note field then the user cannot "clean" the field.
Also, if you are using a plain FORM you cannot use PATCH method, only GET or POST.
If you are using Ajax you might be interested in JSON Merge Patch (easier) and/or JavaScript Object Notation (JSON) Patch (most complete); for an overview of the problems that one can find in partial updates and in using PATCH see also this page.
A point is that a form can only send empty or filled value, while a JSON object property can have three states: value (update), null (set null) and no-property (ignore).
An implementation I used with success is ZJSONPATCH
Focussing on the first view, which pattern would be a good practice?
My suggestion starts from a simple idea: how would you do this as web pages in HTML?
You probably start from a page that offers a view of the user, with hyperlinks like "Update profile", "Update role", "Change password". Clicking on update profile would load an html form, maybe with a bunch of default values already filled in. The operator would make changes, then submit the form, which would send a message to an endpoint that knows how to decode the message body and update the model.
The first two steps are "safe" -- the operator isn't proposing any changes. In the last step, the operator is proposing a change, so safe methods would not be appropriate.
HTML, as a hypermedia format, is limited to two methods (GET, POST), so we might see the browser do something like
GET /user/:id
GET /forms/updateGeneralInformation?:id
POST /updates/generalInformation/:id
There are lots of different spellings you can use, depending on how to prefer to organize your resources. The browser doesn't care, because it's just following links.
You have that same flexibility in your API. The first trick in the kit should always be "can I solve this with a new resource?".
Ian S Robinson observed: specialization and innovation depend on an open set. If you restrict yourself to a closed vocabulary of HTTP methods, then the open set you need to innovate needs to lie elsewhere: the RESTful approach is to use an open set of resources.
Update of a profile really does sound like an operation that should be idempotent, so you'd like to use PUT if you can. Is there anything wrong with:
GET /user/:id/generalInformation
PUT /user/:id/generalInformation
It's a write, it's idempotent, it's a complete replacement of the generalInformation resource, so the HTTP spec is happy.
Yes, changing the current representation of multiple resources with a single request is valid HTTP. In fact, this is one of the approaches described by RFC 7231
Partial content updates are possible by targeting a separately identified resource with state that overlaps a portion of the larger resource
If you don't like supporting multiple views of a resource and supporting PUT on each, you can apply the same heuristic ("add more resources") by introducing a command queue to handle changes to the underlying model.
GET /user/:id/generalInformation
PUT /changeRequests/:uuid
Up to you whether you want to represent all change requests as entries in the same collection, or having specialized collections of change requests for subsets of operations. Tomato, tomahto.
I have a page in my application where user can enter HTML input. Now in order to avoid XSS attack i am using OWASP HTML Sanitizer to sanitize the user input. If the user input is not valid according to the policy i just want to throw the user out.
is there a way to simple check if the input html is valid against the policy without sanitizing ?
something like
public static boolean isValid(String input, Policy policy);
You can define yourself the isValid method but I'm not sure you can do it without calling the sanitize method.
// Define the policy factory
PolicyFactory polFac = new HtmlPolicyBuilder()
.allowElements("a", "p")
.allowAttributes("href").onElements("a")
.toFactory();
boolean isValid(String input, PolicyFactory polFac){
return input.equals(polFac.sanitize(input));
}
You can obtain a more robust version of isValidusing the second version of the sanitizemethod (in the PolicyFactoryclass) that reports the names of rejected element and attributes.
After having read this page I found a way of internationalizing validation messages. It is done by placing translations of each error type into ValidationMessages.properties files.
javax.validation.constraints.Size.message=The property must be between {min} and {max}
javax.validation.constraints.NotNull.message=The property must not be null
It is error type-specific and it's not what I need in my app. I need a unique message for each of my fields in validated beans. With no internationalization it can be done using annotations.
#Pattern(regexp = UiLogicUtils.EMAIL_REGEX, message = "Email is invalid.")
private String requesterEmail;
So how can I make translations of the "Email is invalid" text just for this specific field?
I don't know if this is the answer, because I have not used #Pattern, but in the docs, it says that the message field of the #Pattern is not a text, but a key into the messages file. Look here:
http://docs.oracle.com/javaee/6/api/javax/validation/constraints/Pattern.html#message()
By default message="{javax.validation.constraints.Pattern.message}" which looks like a valid key in ValidationMessages.properties file. I suppose you only have to specify a custom key and use it.
Lets say I have a form with method=POST on my page.
Now this form has some basic form elements like textbox, checkbox, etc
It has action URL as http://example.com/someAction.do?param=value
I do understand that this is actually a contradictory thing to do, but my question is will it work in practice.
So my questions are;
Since the form method is POST and I have a querystring as well in my URL (?param=value)
Will it work correctly? i.e. will I be able to retrieve param=value on my receiving page (someAction.do)
Lets say I use Java/JSP to access the values on server side. So what is the way to get the values on server side ? Is the syntax same to access value of param=value as well as for the form elements like textbox/radio button/checkbox, etc ?
1) YES, you will have access to POST and GET variables since your request will contain both. So you can use $_GET["param_name"] and $_POST["param_name"] accordingly.
2) Using JSP you can use the following code for both:
<%= request.getParameter("param_name") %>
If you're using EL (JSP Expression Language), you can also get them in the following way:
${param.param_name}
EDIT: if the param_name is present in both the request QueryString and POST data, both of them will be returned as an array of values, the first one being the QueryString.
In such scenarios, getParameter("param_name) would return the first one of them (as explained here), however both of them can be read using the getParameterValues("param_name") method in the following way:
String[] values = request.getParameterValues("param_name");
For further info, read here.
Yes. You can retrieve these parameters in your action class.
Just you have to make property of same name (param in your case) with there getters and setters.
Sample Code
private String param;
{... getters and setters ...}
when you will do this, the parameters value (passed via URL) will get saved into the getters of that particular property. and through this, you can do whatever you want with that value.
The POST method just hide the submitted form data from the user. He/she can't see what data has been sent to the server, unless a special tool is used.
The GET method allows anybody to see what data it has. You can easily see the data from the URL (ex. By seeing the key-value pairs in the query string).
In other words it is up to you to show the (maybe unimportant) data to the user by using query string in the form action. For example in a data table filter. To keep the current pagination state, you can use domain.com/path.do?page=3 as an action. And you can hide the other data within the form components, like input, textarea, etc.
Both methods can be catched in the server with the same way. For example in Java, by using request.getParameter("page").
I have a weird problem in that I am trying to edit an existing Company object through a Spring MVC Controller that has a few Validation rules on it. The validation is getting triggered using #Valid.
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(#Valid Company company, BindingResult result, SessionStatus status) {
if(result.hasErrors()) {
return view("edit");
} else {
companyService.saveCompany(company);
status.setComplete();
return redirect("?isSaved=true");
}
}
The individual validations on the Company object pass in unit tests. When used in other parts of the application, they work fine. However, for one of the forms, Spring always throws errors like "Field should not be empty" or "the phone number format is wrong", but the data is actually correct.
The worst thing about this situation is that this code has been in play for over a year - it is just a simple "Edit your company info" screen. It has suddenly just stopped working. Regardless of what I submit on the form, Spring will throw these errors.
I have checked and double-checked everything that could be going wrong. It is loading the correct Company object. It is also posting the correct values too. As a sanity check, I even display the exact error objects after I submit the form:
Field error in object 'company' on field 'phoneNumber': rejected value [451-324-3232]; codes [Pattern.company.phoneNumber,Pattern.phoneNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [company.phoneNumber,phoneNumber]; arguments []; default message [phoneNumber],[Ljavax.validation.constraints.Pattern$Flag;#2c99f9,(\()?(\d){3}(\))?(\s|-)(\d){3}(\s|-)(\d){4}]; default message [Must be of the form: ###-###-####]
Field error in object 'company' on field 'name': rejected value [somewhere]; codes [NotEmpty.company.name,NotEmpty.name,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [company.name,name]; arguments []; default message [name]]; default message [Name may not be empty]
Field error in object 'company' on field 'address.address': rejected value [135431]; codes [NotEmpty.company.address.address,NotEmpty.address.address,NotEmpty.address,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [company.address.address,address.address]; arguments []; default message [address.address]]; default message [Address may not be empty]
As you can see, the values are correct, but it's throwing the errors anyway.
Also, the company object has an ID - it's not getting lost or anything like that.
If I remove #Valid, everything works. All the values get changed, so I know it's something directly related to #Valid. But what?
I know you might be thinking that the validation rules must be wrong or something... but they aren't. How can someone mess up #NotEmpty constraints?
public class Company extends DomainObject {
#NotEmpty(message = "{company.name.notEmpty}")
private String name;
#Valid
private Address address = new Address();
#Pattern(message = "{company.phoneNumber.valid}",
regexp = "(\\()?(\\d){3}(\\))?(\\s|-)(\\d){3}(\\s|-)(\\d){4}")
private String phoneNumber = "";
private boolean isEnabled = true;
private boolean homepageViewable = true;
private int coursesCreated = 0;
#Valid
private Theme theme = new Theme();
It doesn't matter what I put into these fields - I still get the errors. Also, when testing these validations in isolation, THEY WORK. In fact, when #Valid is used for the Company object in other parts of the system (like a Registration sign-up form), it works too.
So the only part where it does not work is the Company Profile screens.
Is there any reason why Spring-MVC would do this? I am totally at a loss. I don't even know what the heck I did to cause this problem. It's not like any unit/integration tests have failed as I was making changes. I was never alerted that this was a problem until I manually tried these screens - a common annoyance when using Spring/Java because there are many cases where unit/integration tests are slightly different than using a real production container, so problems slip by anyway.
Please help.
One thought. When company validation works, is it always on a form where the company is part of something bigger? E.g., with registration, the company is part of a registration. But when you try to save the company on a company form, it fails...
Can you try attaching #ModelAttribute to the Company arg? I.e.
#ModelAttribute #Valid Company company
Does it help?