JSR 303 Validation with Spring (MVC) on WebSphere
Asked Answered
B

2

2

I'm trying to do JSR 303 bean validation with a Spring MVC Controller in WAS 8.5.5.12 Full Profile.

I'm validating just a single @RequestParam, not a full bean:

@RequestMapping(method=RequestMethod.GET)
public String initializeCheckIn(
    @Valid @Pattern(regexp = "^[\\p{Alnum}]*$")
    @RequestParam("officeid") String officeId, HttpSession session, Model model) {

Before I added some Spring-specific configuration, no validation was occurring, but neither were any errors. Presumably, the validation wasn't being attempted at all.

Now that I've added the necessary @Validated class annotation and bean definition:

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

I get the following error:

[8/9/17 10:33:40:588 CDT] 000000a7 ServletWrappe E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception root cause Spring MVC Dispatcher: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: org.hibernate.validator.method.MethodConstraintViolationException
...
Caused by: java.lang.NoClassDefFoundError: org.hibernate.validator.method.MethodConstraintViolationException
        at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:152)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
        at my.package.web.CheckInController$$EnhancerBySpringCGLIB$$d385737c.initializeCheckIn(<generated>)

Based on

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/validation/beanvalidation/MethodValidationPostProcessor.html

Spring should auto-detect an available JSR-303 provider, which this version of WebSphere (8.5.5.12 full profile) should have. It appears it's failing to find that JSR-303 provider, so it's falling back to a default.

So any ideas why the WebSphere version is not found or how to make it found?

Botfly answered 22/8, 2017 at 13:52 Comment(0)
B
0

I think I finally found a working solution. It appears that I need to explicitly tell the Spring MethodValidationPostProcessor bean to use the container-provided javax.validation.ValidatorFactory, which apparently I can get from a JNDI lookup of "java:comp/ValidatorFactory".

<jee:jndi-lookup id="validatorFactory" jndi-name="java:comp/ValidatorFactory" resource-ref="false"/>

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
    <property name="validatorFactory" ref="validatorFactory"/>
</bean>

(Incidentally, based on this simple JNDI lookup JSP, in this version of WebSphere, the implementation class is org.apache.bval.jsr303.ApacheValidatorFactory)

Edit: I wrote up this whole process at Blog entry: https://dougbreaux.github.io/2018/05/23/springmvc-jsr303-websphere.html

Botfly answered 16/5, 2018 at 18:7 Comment(1)
No longer certain this is correct/sufficient. My success was with validating a bean, not a single parameter. Now getting the same earlier behavior on a single parameter again. Adding @Validated produces the Hibernate NoClassDef; not adding it bypasses the JSR validation annotations...Botfly
R
0

First af all, you have to force to use shipped Hibernate Validator 5 instead of WebLogic one. Just add WEB-INF/validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<validation-config
    xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration http://www.jboss.org/xml/ns/javax/validation/configuration/validation-configuration-1.0.xsd">

    <default-provider>org.hibernate.validator.HibernateValidator</default-provider>
</validation-config>

Most probably, you need to set classloaderMode to PARENT_LAST in deployment.xml. In case of EAR, it should look like

<?xml version="1.0" encoding="UTF-8"?>
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi" xmi:id="Deployment_1">
  <deployedObject xmi:type="appdeployment:ApplicationDeployment" xmi:id="ApplicationDeployment_1" deploymentId="0" startingWeight="1">
    <modules xmi:type="appdeployment:WebModuleDeployment" xmi:id="WebModuleDeployment_1" deploymentId="1" startingWeight="10000" uri="foureyes-ri.war" classloaderMode="PARENT_LAST"/>
  </deployedObject>
</appdeployment:Deployment>

I am not sure, but I pack validation-api 1.1.0 to WAR and it works for me.

Resilience answered 5/3, 2018 at 14:28 Comment(1)
But I don't want to use the Hibernate Validator, I want to use the one provided by WebSphere.Botfly
B
0

I think I finally found a working solution. It appears that I need to explicitly tell the Spring MethodValidationPostProcessor bean to use the container-provided javax.validation.ValidatorFactory, which apparently I can get from a JNDI lookup of "java:comp/ValidatorFactory".

<jee:jndi-lookup id="validatorFactory" jndi-name="java:comp/ValidatorFactory" resource-ref="false"/>

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
    <property name="validatorFactory" ref="validatorFactory"/>
</bean>

(Incidentally, based on this simple JNDI lookup JSP, in this version of WebSphere, the implementation class is org.apache.bval.jsr303.ApacheValidatorFactory)

Edit: I wrote up this whole process at Blog entry: https://dougbreaux.github.io/2018/05/23/springmvc-jsr303-websphere.html

Botfly answered 16/5, 2018 at 18:7 Comment(1)
No longer certain this is correct/sufficient. My success was with validating a bean, not a single parameter. Now getting the same earlier behavior on a single parameter again. Adding @Validated produces the Hibernate NoClassDef; not adding it bypasses the JSR validation annotations...Botfly

© 2022 - 2024 — McMap. All rights reserved.