I use Spring Roo + jpa + hibernate and I would like to implement cross-validation (validation of several fields at the same time) in my application.
I am not sure how to go about implementing it. Can anyone please advise me and/or direct me to relevant documentation?
Have a look at Hibernate Validator, which allows entity validation (using annotations).
http://www.hibernate.org/subprojects/validator.html
In short, you annotate your field constraints by placing hibernate validator/ JPA annotations above them. (E.g. #Min(10)) and use the following piece of code to find any invalid fields;
ValidatorFactory factory = Validation.byDefaultProvider().configure().traversableResolver(new CustomTraversableResolver() ).buildValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<BaseValidationObject>> constraintViolations = Validator.validate(myEntityToValidate);
If you need to validate specific relationships between entities, you can write custom validators to fit that need.
Related
It is possible to apply a filter to results with annotations instead of extending method name?
For instance:
#Repository
public interface JobRepository extends JpaRepository<Job, Long> {
List<Job> findAllByUserAndEnabledIsTrue(User u);
}
Here I apply filter 'enabled == true'. But assume we have a lot of methods. Writing them with extended names is inconvenient. Could I apply this filter to whole repository?
I found
#FilterDef but I don't know how to use and also if spring support this annotation.
As far as I know Spring Data JPA is not Hibernate dependent, and it can work with any JPA implementation. Hibernate's #Filters is not a JPA standard, so the simple answer is no! Spring JPA does not support #Filters.
But you can apply #Filters using AOP, and simply applying aspects on your repository methods.
By the way I believe the better solution is to have hand written queries using Spring Data JPA's #Query annotation. Because this way you can name methods after their context meaning, and not about their internal implementation.
For example you can name your method findActiveJobsForUser which could be more meaningful and readable.
I have a controller with a method like
#PostMapping(value="/{reader}")
public String addToReadingList(#PathVariable("reader") String reader, Book book) {
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/readingList/{reader}";
}
When I run a static code analysis with Sonarqube I get a vulnerability report stating that
Replace this persistent entity with a simple POJO or DTO object
But if I use a DTO (which has exactly the same fields as the entity class, then I get another error:
1 duplicated blocks of code must be removed
What should be the right solution?
Thanks in advance.
Enric
You should build a new separate class which represents your Entity ("Book" ) as Plain Old Java Object (POJO) or Data Transfer Object (DTO). If you use JSF or other stateful technology this rule is important. If your entity is stateful there might be open JPA sessions etc. which may modify your database (e.g. if you call a setter in JSF on a stateful bean).
For my projects I ignore this Sonar rule because of two reasons:
I alway you REST and REST will map my Java Class into JSON which can be seen as a DTO.
REST is stateless (no server session) so no database transaction will be open after the transformation to JSON
Information obtained from sonarsource official documentation.
On one side, Spring MVC automatically bind request parameters to beans
declared as arguments of methods annotated with #RequestMapping.
Because of this automatic binding feature, it’s possible to feed some
unexpected fields on the arguments of the #RequestMapping annotated
methods.
On the other end, persistent objects (#Entity or #Document) are linked
to the underlying database and updated automatically by a persistence
framework, such as Hibernate, JPA or Spring Data MongoDB.
These two facts combined together can lead to malicious attack: if a
persistent object is used as an argument of a method annotated with
#RequestMapping, it’s possible from a specially crafted user input, to
change the content of unexpected fields into the database.
For this reason, using #Entity or #Document objects as arguments of
methods annotated with #RequestMapping should be avoided.
In addition to #RequestMapping, this rule also considers the
annotations introduced in Spring Framework 4.3: #GetMapping,
#PostMapping, #PutMapping, #DeleteMapping, #PatchMapping.
See More Here
I'm new to spring & hibernate, please suggest a best way to provide validation to spring mvc & hibernate projects. I tried hibernate validator but i don't know how to use it when there is relationship(like #OneToOne) between entity objects. If there is any examples, please provide the link.
Your #OneToOne relationship is not clear enough. Could you please give a concrete scenario?
In Spring MVC you have three types of validations:
JSR-303 bean validation (hibernate validator)
Custom validation
Spring validation
JSR-303 works great for simple validations on single fields. You have standard annotations like (#Max, #Min, #NULL, #Pattern, etc.). It does not seem enough for you in this case.
Custom validation is used in a more complex scenario. For instance, what if we need to validate that the newly added product ID is not the same as any of the existing product IDs?
Spring validation represents cross-field validation.
For instance, it's used when we want to compare two or more fields to see if
their values can be considered as valid when combined.
you can use spring validation method.
using valid annotion in controller classes infront of modelattribute annotaion.
then you can use validaions in the model class.
below is an example for controller and bean classes.
this is a many to one configuration inside a bean class:
#ManyToOne(targetEntity = UserType.class)
#JoinColumn(name = "user_type", referencedColumnName = "id")
#NotNull
private UserType userTypeTb;
this is a method inside controller class with valid and modelattribute annotaion:
public ModelAndView home(#Valid #ModelAttribute("user") User user, BindingResult result,
HttpServletRequest request) {
//
//
}
I want to use JSR 303 (Hibernate Validator) in my JSF 2 project. However, I have complicated forms and field-level validation is not sufficient. I need to use many #ScriptAssert annotations at class-level of my model and its child beans.
So I want to validate form models manually (inside bean action method for example). But I could not understand how I can preserve which validation message should be shown at which field (as it works automatically when field-level validation is on and processed by JSF).
Also I'll need to specify for some of class-level annotations that their messages are to be shown at specific fields. I do not see a straight way to manage it...
Could you please provide a link to explanations of these questions (or tell me that I am doing something wrong?). I think I fail in googling it because internet is bloating with keywords JSF and validation, sorry.
The most idiomatic way to do that is to create custom Bean Validation validator for your class.
You need to create validation annotiation that you would put at the class level (not field level) and associated with that class validator class.
See for instance:
http://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-usingvalidator.html (Example "Class level constraint")
How can I validate two or more fields in combination?
Validation inside managed bean is also possible, you can throw in your action methods proper validation exception, but usually it is cumbersome, hard to reuse and mixes business logic code with validation.
I'm just wondering about data validation in Spring. Spring is offering two (maybe more) validation options. First option is to use Validator interface and create whole validation on my own. Second option is to use annotation validation (JSR 303).
And now I'm really confused :) which validation I should chose. What I need is to check if recieved Data Object is correct (by correct i mean all required fields are filled) and this can be done by JSR 303 validation or by my own validator with "Validator instance". But I also need to check if is this Data Object valid against some database constraints (validator is required to check some data in database, eq. is user with this ID registered or not ...) and this can be done only by my own validator.
I don't know which way should be the best. Combine both or create my own validator ?
I will be thankful for any advice ...
Update (relocated from comments)
Ok, I followed Ryan's example and I think I was successful. I created my own implementation of spring Validator and in this Validator I #Autowire-d javax JSR 303 instance. But there was problem with that injection. I had in my configuration and this piece of code caused some exceptions, because spring did not know which Validator I want to inject. So I removed that code.
At the end I also removed the spring Validator implementation, because I dont know where I can get Errors property, which is required as second parameter in "validate" method :). I'm triggering that validation manually from service layer and I really don't know, where I can obtain that Error object.
BTW Well, I found another solution how to implement that validation. I'm thinking about to extend my validator class by LocalValidatorFactoryBean. LocalValidatorFactoryBean class implementing both Validator interfaces (Spring Validator + JSR 303). But i'm not sure if is this good approach. This approach also require Error object, which I don't know where to find/get.
Update
The Error object is coming from "BindException".
FooObjectVO myObject = new FooObjectVO();
BindException errors = new BindException("fooObject", myObject);
They're not really separate options--more like two available implementations of validation. Since Spring's JSR 303 support also implements its own Validator interface, you don't really have to pick one or the other. You can mix and match the implementations in whatever way makes it easiest to get the job done.
In cases such as this I prefer to combine both. I like to use JSR 303 validation for whatever I can. I supplement it with my own validators.