I'd like to disable Hibernate validation for a single entity in my application, which I validate manually. The rest of entites should continue to use the standard Hibernate validation on persist.
The standard solution is to disable all validation via javax.persistence.validation.mode: none but this doesn't apply here as I just want to bypass it for a single entity.
So far the solutions appear to be:
Add Hibernate groups to every single annotation on the entity - this is error prone and cumbersome as the entity has 50+ annotations on it.
Replace or override BeanValidationEventListener to skip validation for my entity - there doesn't appear to be a clean way to override this listener with Spring Boot 2.0.
Are there other, simpler ways to do this with Hibernate and Spring?
Related
guys!
I've generated an application using JHipster v7.9.3. However, when this app was evaluated by my SonarQube server, it failed.
One of the most common critical issues is the: RSPEC-4684 Persistent entities should not be used as arguments of "#RequestMapping" methods. This rule states the following:
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.
This issue is related to CWE-915
Checking out JHipster docs, I found out this page clarifying that they really uses its domain objects (typically JPA entities) directly in its REST endpoints with the intention to make the code simpler.
I wonder if this rule is still valid or if it doesn't apply anymore for more recent Spring Boot versions (v2.7.*) and I could safely disable rule 4684 at my SonarQube.
The only reference to this rule is this one on Sonar's Jira and it is shown still as Active.
I have a project using Kotlin in Spring Boot. The tables have the standard audit fields 'createdBy', 'createdDt'. Is there a way to handle setting these fields in some way that doesn't involve passing these fields around? Ideally I'd like to intercept every transaction before commit and just set the fields on the entities.
Using JPA and Hibernate, an AuditAware bean could be used to pass the current Principal along with using annotations. Is there a similar integration available or easily implemented? I've looked at the EntityHooks class and don't see an easy way to change data.
for example I have entity with 20 properties, most of them have validators. Can I somehow disable validators? Ofc I can comment them or just remove but when You have many entities this would take a lot of time and in dev mode I would like to mock dummy data
You can use the property:
spring.jpa.properties.javax.persistence.validation.mode=none
as stated here:
How to disable Hibernate validation in a Spring Boot project
Spring MVC offers form validation through both annotations on the forms (for example #NotNull) to do a simple check of the value of a field, and custom Validators, which help you do cross-field validations (verifying two password fields contain the same value, etc).
I am looking for the recommended way to do validations that go a bit further, however. For example verify if a username is not used already, which requires a call to the database. I assume I can simply inject my PersonRepository into the custom validator (which is an #Component) after all, but I doubt it'll be transactionally safe..or very clean.
What is the recommended way to do this, that requires the least amount of duplicated code? Or should I simply write my own validation layer, that throws some ValidationException with a list of validationmessages, which I have to map to the bindingresult?
To just clearify: Spring MVC don't offers form validation by itself. It integrates with Java Bean validation vendors (like Hibernate Validator).
You're right: If you configure LocalValidatorFactoryBean as a bean in your application context, you benefit from dependency management in your custom validators. In my opinion there is no need to implement a custom validation layer within your setup, since you already have a powerful and generic abstraction of validation which even conforms to Java standards.
If you worry about whether calling your repository in validator is transaction safe or not see http://docs.spring.io/spring-data/jpa/docs/1.8.2.RELEASE/reference/html/#transactions for details. CRUD operations are transactional by default. If you need a more sophisticated validation logic with needs a transaction context, you could either make your isValid(...) method transactional by annotating it, or you could autowire a business service with likely is transactional by itself. This perfectly integrate with the concepts of Spring.
Use the same business transaction
If you need to handle validation and business logic (check whether a user name is already used and insert a new if not) in the same transaction you could think about restricting those validations in Controller layer to the basic ones (#NotNull for example). This will ensure, that only syntactic correct requests make their way to your service layer.
In the service you will use an autowired validator and trigger the entire validation constraints manually. If you have a combination Hibernate as JPA vendor and Hibernate as Validation vendor you could even make use of the integration of both (pre persit and pre update events) which will cause the validation to occur automatically before the changes are written to the database.
However you decide, you will likely use validation groups to split the constraints into two groups 'syntactic' and 'semantic' for example. If you call the validator manually you can pass the groups you want to take into account. If you use integrated validation with Hibernate you can control the groups for the different events by specifying the following properties:
javax.persistence.validation.group.pre-persist
javax.persistence.validation.group.pre-update
If you decide for this way you will simply call your transactional business service method from your controller. Business logic and validation will participate in the same transaction this way.
I am planning to use Spring 3 validations in my Web Application. I was considering that since I already have the properties of my JPA entities annotated with some standard validations like nullable="false" or length="50". Is there any way I could reuse JPA validations in Spring 3 Backing forms?
I feel a better idea would be to recode the validations on the Spring form as we can have more helpful error messages. What do you think -
Is it possible in a clean way to reuse JPA validations in Spring forms?
What is a better design - reimplement the validations or reuse the basic ones and code more specific validations separately?
In my experience, as soon as you write a custom Validator you're responsible for validating all fields regarding Spring's WebDataBinder. Validation constraint annotations still throw exceptions though if violated.