Spring validation: regex annotation does not work - regex

When executing the controller method I receive this log:
OBJECT: [Field error in object 'catalog' on field 'name': rejected value [safasf]; codes [Pattern.catalog.name,Pattern.name,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [catalog.name,name]; arguments []; default message [name],[Ljavax.validation.constraints.Pattern$Flag;#5f32f731,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute#2180fe7e]; default message [muss auf Ausdruck "[A-Za-z]" passen]]
Regex: [A-Za-z]
Input: safasf
The code:
...
#NotNull
#Size(min=1, max=8)
#Pattern(regexp = "[A-Za-z]")
private String name;
...
The controller:
#PostMapping(ADD_CATALOG)
public String addCatalog(#Valid #ModelAttribute Catalog catalog, BindingResult result){
if(result.hasErrors()){
logAction("addCatalog", "Validation of "+catalog.getName()+" failed: ", result.getAllErrors().toString());
return "redirect:/catalog/addCatalog/";
}
catalogProviderComponent.addOrUpdateCatalogEntity(catalogComponent.catalog2catalogEntity(catalog));
logAction("addCatalog","catalog", catalog);
return "redirect:/catalog/addCatalog/";
}
When I go to regex101.com everything seems to be fine. Beside that I tried few regex but none seem to work out properly.

To allow for one or more lowercase or uppercase letter, you should append + to the end of the pattern:
#NotNull
#Size(min=1, max=8)
#Pattern(regexp = "[A-Za-z]+")
private String name;

Related

how to validate with regex input field in spring boot

i'm trying to do a validation of only positive numbers inside the request in spring boot
Public ResponseEntity getId(#RequestParam(value =“idPer”)#Pattern(regexp=“^[0-9]*$”),message = “the value is negative”)
#NotNull(message = “the value is empty ”) Long idPer){
}
in my exceptionhandler I get this exception
no validator could be found for constraint 'javax.validation.constraints.pattern' validatingtype long
I have the #validated above my controller class
what am I doing wrong?
Check documentation of #Pattern. It is applicable to CharSequence i.e. String bur not allowed for Long which is what you are using in your method.
You may refactor your code like this:
public ResponseEntity getId (
#Pattern(regexp="^[0-9]+$", message="the value must be positive integer")
#RequestParam("idPer") final String idPerStr) {
Long idPer = Long.valueOf(idPerStr);
// rest of your handler here
}
Also note that #NotNull is not required because we are using + quantifiers that allows only 1 or more digits in pattern.

Regex data annotation validation not working

I'm trying to use the "RegularExpression" DataAnnotation validaiton in my model. My problem is even for the valid input I provide for the field containing the validation, the regex doesn't match and it fails.
I try to test the same valid input with the regex in a stand-alone console app and I find it gets through.
My point is, when regex is being used in dataannotation as validation, it considers all input as bad input. What am I missing here?
My regex is for checking comma-seperated email IDs. Here is my model:
public partial class BuildModel
{
public Int64 ConfigID { get; set; }
[Required(ErrorMessage = "Please select a stream!")]
public String Name{ get; set; }
[RegularExpression(#"^(([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*(;|,)\s*|\s*$))", ErrorMessage = "Please enter valid email IDs separated by commas")]
public string EmailIDs { get; set; }
public bool IsActive { get; set; }
}
Note: The "Required" data-annotation validation works just fine. It is just the Regex one, that won't work!
As far as i understand you just have problem within your Regex.
To validate emails separated by comma you can use this regex:
^( *[\w+-.%]+#[\w-.]+\.[A-Za-z]{2,4}( *, *)? *)+$
Check in in here.
You must the jquery.validate.min.js and jquery.validate.unobtrusive.min.js in your page without these libraries required annotation would not works.

Spring-Boot #RequestMapping and #PathVariable with regular expression matching

I'm attempting to use WebJars-Locator with a Spring-Boot application to map JAR resources. As per their website, I created a RequestMapping like this:
#ResponseBody
#RequestMapping(method = RequestMethod.GET, value = "/webjars-locator/{webjar}/{partialPath:.+}")
public ResponseEntity<ClassPathResource> locateWebjarAsset(#PathVariable String webjar, #PathVariable String partialPath)
{
The problem with this is that the partialPath variable is supposed to include anything after the third slash. What it ends up doing, however, is limiting the mapping itself. This URI is mapped correctly:
http://localhost/webjars-locator/angular-bootstrap-datetimepicker/datetimepicker.js
But this one is not mapped to the handler at all and simply returns a 404:
http://localhost/webjars-locator/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css
The fundamental difference is simply the number of components in the path which should be handled by the regular expression (".+") but does not appear to be working when that portion has slashes.
If it helps, this is provided in the logs:
2015-03-03 23:03:53.588 INFO 15324 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/webjars-locator/{webjar}/{partialPath:.+}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity app.controllers.WebJarsLocatorController.locateWebjarAsset(java.lang.String,java.lang.String)
2
Is there some type of hidden setting in Spring-Boot to enable regular expression pattern matching on RequestMappings?
The original code in the docs wasn't prepared for the extra slashes, sorry for that!
Please try this code instead:
#ResponseBody
#RequestMapping(value="/webjarslocator/{webjar}/**", method=RequestMethod.GET)
public ResponseEntity<Resource> locateWebjarAsset(#PathVariable String webjar,
WebRequest request) {
try {
String mvcPrefix = "/webjarslocator/" + webjar + "/";
String mvcPath = (String) request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
String fullPath = assetLocator.getFullPath(webjar,
mvcPath.substring(mvcPrefix.length()));
ClassPathResource res = new ClassPathResource(fullPath);
long lastModified = res.lastModified();
if ((lastModified > 0) && request.checkNotModified(lastModified)) {
return null;
}
return new ResponseEntity<Resource>(res, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
I will also provide an update for webjar docs shortly.
Updated 2015/08/05: Added If-Modified-Since handling
It appears that you cannot have a PathVariable to match "the remaining part of the url". You have to use ant-style path patterns, i.e. "**" as described here:
Spring 3 RequestMapping: Get path value
You can then get the entire URL of the request object and extract the "remaining part".

Define Regular Expression Validation for custom DataType in MVC4

I upgraded a project from MVC3 to MVC4 and noticed that one of my validators wasn't triggering anymore. I chased it down to a custom DataType in the Shared/EditorTemplates folder that is used for capturing Social Security numbers in various forms across the site. (We only show the last 4 digits when the page is loaded after a save, to explain the regex.)
SSN.cshtml
#{
var ssn = (string)ViewData.TemplateInfo.FormattedModelValue;
if (!String.IsNullOrWhiteSpace(ssn)){
ssn = "###-##-" + Model.Substring(Model.Length - 4, 4);
}
}
#Html.TextBox("", ssn, new { #class = "text-box single-line ssn", pattern = #"^(\d{3}|###)-(\d{2}|##)-\d{4}$", placeholder = "###-##-####", title = "Expected pattern is ###-##-####" })
It seems like in MVC4 the unobtrusive validation wants to look for data-val-regex-pattern as an attribute of the rendered text box, not just pattern. Has anyone ran into this before?
Note: I'd like to keep the validation on the custom data type so I don't have to always remember to add it to each model.
Thanks!
You can have your own custom validator and put it in the model property. here is an example
public class SocialSecurityAttribute : RegularExpressionAttribute
{
public SocialSecurityAttribute () : base(#"^(\d{3}|###)-(\d{2}|##)-\d{4}$") { }
}
Then register it in the global asax.cs Application start as follows
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(SocialSecurityAttribute), typeof(RegularExpressionAttributeAdapter));
When you use it , it will be like any other built in attributes
[SocialSecurity(ErrorMessage ...)]
public string SocialSecurityNumber{get;set;}
I like implementing like this as the code can be reused . Otherwise you can just use RegularExpressionAttribute passsing the regex
I found out that in order to get MVC4 to render the correct data attributes to the input field, I'd need to replace the hyphens with underscores in the anonymous object passed to the TextBox helper. Here's the code that I ended up with:SSN.cshtml
#{
var ssn = (string)ViewData.TemplateInfo.FormattedModelValue;
if (!String.IsNullOrWhiteSpace(ssn) && ssn.Length == 11)
{
ssn = "###-##-" + Model.Substring(Model.Length - 4, 4);
}
else {
ssn = "";
}
}
#Html.TextBox("", ssn,
new
{
#class = "text-box single-line ssn",
data_val = "true",
data_val_regex_pattern = #"^(\d{3}|###)-(\d{2}|##)-\d{4}$",
data_val_regex = "Expected pattern is ###-##-####",
placeholder = "###-##-####"
}
)

Multiple Regex #Pattern's for 1 Field?

I was attempted to apply multiple #Pattern annotations to a single field:
#Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit.")
#Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter.")
#Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter.")
#Pattern(regexp = "(?=\S+$)", message = "Password must contain no whitespace.")
private String password;
However, I cannot do this. I want individual messages per violated regex constraint on the password field. Is this possible?
My alternative is to use JSF 2.0 f:validatorRegex tags.
You can use the inner #List annotation of #Pattern:
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter."),
#Pattern(regexp = "(?=\\S+$)", message = "Password must contain no whitespace.")
})
private String password;
Gunnar's solution won't work for me... '.+' in his regexp seem to be missing.
However, i'm using Michal's patternList and it works like a charm for me. (Play 2.3.x / Ebean-ORM)
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one upper letter."),
#Pattern(regexp = "(?=.*[!##$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
#Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
#Constraints.Required()
public String password1;
You might want to look into constraint composition. You would build one annotation per password constraint composed from the #Pattern annotation, and then finally build one composed annotation using the previously defined four. This would require no extra java code.
http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#validator-customconstraints-compound
Otherwise, build (with accompanying java code) a custom annotation called #PasswordValidator.
I tend to like composed validators, as it makes the purpose of the validation annotations clear on their purpose, instead of having many disjoint annotations.
I modified Gunnar answer and write composite constraint and this now seems to work correctly on 4 unit tests:
#NotNull
#Size(min=6, max=45)
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one uppercase letter."),
#Pattern(regexp = "(?=.*[!##$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
#Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
#Constraint(validatedBy = {}) // constraints composition
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
public #interface StrongPassword {
String message() default "Password doesn't match bean validation constraints.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}