Spring Validation with Hibernate Validation - java

I want to combine Hibernate and Spring Validators. I came across this link:
http://www.mkyong.com/spring-mvc/combine-spring-validator-and-hibernate-validator/
And it is working as expected. However to get it to work have to comment out InitBinder, enter the method and throw an exception within method itself if there are errors in the BindingResult.
I would prefer for it to be like #Validated where it throws the exception prior to even entering the method
#Validated is for Spring and throws MethodArgumentNotValidException if any errors come up.
Is there a way to use invoke Hibernate validate as part of Spring Validator class or call both and bind them to the same Result

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/beanvalidation/SpringValidatorAdapter.html
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html
Came across the above classes: Adapter that takes a JSR-303 javax.validator.Validator and exposes it as a Spring Validator while also exposing the original JSR-303 Validator interface itself.
This solved the issue. I created a SpringValidatorAdapter bean and am injected it into my Spring Validators and calling validate on the object

Related

`#Transactional` not working for Spring 2 controller

I have an old controller within my app that is defined as a spring bean in xml and makes use of Spring's SimpleFormController. I've tried to make the processes within the onSubmit method of the controller transactional by adding the #Transactional annotation but it doesn't work. According to this guide the invocation of the annotation must happen "outside of the bean", does this mean that the annotation cannot be used in old Spring controllers like mine? Are there any alternatives or workarounds?
The reason I know it's not working is because 1) changes to the db are not rolled back on error (this is despite the fact that I have defined rollbackFor = Exception.class, and even in some instances used TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();, in this instances where it tries to use the latter it throws an error stating there is no transaction present. 2) I've added breakpoints to where #Transactional is instantiated within Spring and none of them get hit.
EDIT: So people are asking for reproducible examples of code. The problem doesn't lie within the business logic code, I'm looking for clarity on the usage of the annotation within a Spring 2 controller. So what I have for example is this:
public class ImportController extends SimpleFormController {
#Override
#Transactional(rollbackFor = Exception.class)
public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
...
}
}
You are right. #Transactional will not work here because onSubmit is invoked by the same bean.
And in this case the call is done directly and the default spring transaction handling does not work.
See answers in this question for a detailed explanation of the options you have

Spring data jpa with multiple entities not rolling back - PostgreSQL

I am using spring-data-jpa in one of my projects. In service layer, I have annotated a private method with #Transactional and also enabled #EnableTransactionManagement in application. When one of the save method of entities throws an exception, the rest of the entities which were saved before are not rolling back. BTW I am using PostgreSQL.
Please let me know if I am missing anything here.
Spring transaction will only work with public method. As it need to inject code using proxy classes for transactions. So making your method public will resolve your issue. Have a look on documentation of proxy mechanism of spring.
Spring by default will rollback only for Runtime Exceptions (https://docs.spring.io/spring/docs/2.5.x/reference/transaction.html#transaction-declarative).
If you want to rollback for any exception, you could try adding:
#Transactional(rollbackFor = Exception.class)

Bean Validation with groups using Spring in Service Layer

I am developing a service(not a web application) using Spring-3.1.0.GA. I want to use hibernate-validator along with Spring to validate my service inputs.
I have enabled the bean validation support with:
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
I have annotated my service interface with #Validated and method parameters with #NotNull, #Size, #Valid etc and it is working fine.
But I have to validate my parameter, say Customer, based on validation group(s).
If I annotate method parameter with #Validated or #Validated(Group1.class) Spring is not performing any validation.
If I annotate with #Valid then validations are happening but with Default validation group(as expected).
I can't annotate #Validate(Group1.class) at interface level because various methods operate on various groups.
How can I perform service layer validations using Spring and hibernate-validator with groups support?
I have gone through Spring Source code and why the validation groups on method params are not being picked...As per the code it is picking the validation groups configuration only from #Validated on interface level, not on method level.
But I haven't gone through how it is working in SpringMVC context, I haven't checked yet.
Also in this process I came to know If you configure MethodValidationPostProcessor in child application context it is not picked up by Spring. I mean if you are using SpringMVC, MethodValidationPostProcessor will be registered only if you configure it in [servlet-name]-servlet.xml. If you configure in any child context configuration files that are picked by ContextLoaderListener Spring won't register MethodValidationPostProcessor. Also I am not sure it is only for MethodValidationPostProcessor or for any BeanPostProcessors also.
I get the following code working, I need to attach the #Validated at the method header and #Valid in the method parameters.
#Validated(Default.class)
public UserDto updateUser(#Valid UserDto userDto) {
In Spring 3.1.0+ you can use groups directly in #Valid annotation. E.g.:
#Valid(groups={Default.class, Group1.class})

Spring #Controller and custom MethodNameResolver

I have several controllers in a spring mvc application. They are regular beans that inherit from MultiActionController. They also have a custom MethodNameResolver that inspects a certain request parameter.
Now I am trying to use a new controller - a pojo with #Controller annotation. I am using #RequestMapping to resolve methods.
I am not sure if I understand this correctly, but as explained here in the spring reference, it is possible to use #RequestMapping with various filters (e.g. GET vs POST) without specifying a path, and then if a url applies to several methods then Spring falls back to InternalPathMethodNameResolver to decide which method to invoke.
How can I tell Spring to fall back to my custom MethodNameResolver? Is it enough to inject the resolver to my pojo controller?
(my controller doesn't inherit from any Spring specific class)
I guess you need to declare AnnotationMethodHandlerAdapter bean and set its methodNameResolver property.

Is there a standard way to enable JSR 303 Bean Validation using annotated method arguments

I've been looking a around for a while now with no luck. I'n not using Spring MVC but still want to use #javax.validation.Valid to enable validation of method arguments. To give an example
public class EventServiceImpl implements IEventService {
#Override
public void invite(#Valid Event event, #Valid User user) { ... }
}
Using MVC, this is enabled for #Controller annotated beans with a simple <mvc:annotation-driven/> (see 5.7.4.3 Configuring a JSR-303 Validator for use by Spring MVC).
Using AOP should be quite trivial. Nevertheless, I suspect there's some standard way to do this. Hence the question: Is there a similar thing for non-MVC applications and non-controller beans to enable input validation for annotated beans?
Method level validation is not part of the Bean Validation specification (JSR 303). Method level validation is a suggestion in the spec added in appendix C.
Hibernate Validator 4.2 (a beta is out already) is implementing this suggestion and allows to place JSR 303 annotations on method parameters and return values. Of course you will still need some Spring glue code, but that should not be too hard.
Also Bean Validation 1.1 will add method level validation officially to the spec (not just as appendix/recommendation). See also http://beanvalidation.org/
Using MVC, this is enabled for #Controller annotated beans
#Valid is just a marker in Controller beans that hides the code that does the validation and puts all constraint violations in Errors in a nice way. Spring designers could have invented their own annotation to do the same thing.
The real use of #Valid annotation is in the class (bean) that you are validating with JSR 303 validator and its primary use is to validate the object graph. Meaning one bean can have other
bean references with #Valid annotation to trigger validation recursively.
Outside the MVC, you can use configured validator to validate any bean that uses JSR 303 annotations but, unlike the nicely populated Errors in controller, you will have to decide yourself what you are going to do with constraint violations.
So, to answer your question, there is no standard way. To have the same appearance as in a controller, you could use #Valid annotation (or create a new one) to run AOP advice to validate a bean and populate a 'ViolationCollector' (something like Errors in MVC) that must be passed to a method.
The answers seem to be quite old. As of now, you can utilize #Validated and MethodValidationPostProcessor for method inline validation of any Spring beans. They are basically responsible for creating pointcut-like behavior for Spring managed beans of any tier, not Controllers specifically.
Also see my other answer.

Categories

Resources