dur dur - 2 months ago 12
Java Question

Bean validation for JAX-RS sub resource with CXF

I try to use Bean Validation for my REST API with Apache CXF. I read Apache CXF Documentation and it works fine for root resources, but it doesn't work with sub resource locators. The constraints are ignored for sub resources.

Maven dependencies:

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-jsr</artifactId>
<version>1.1.0</version>
</dependency>


Java code:

@Named
@Path("test")
public class TestResource {

@Inject
private TestSubResource subResource;

@Path("sub")
public TestSubResource getSubResource() {
return subResource;
}

@GET
public void find(@NotNull @QueryParam("value") String value) {
}
}

@Named
public class TestSubResource {

@GET
public void find(@NotNull @QueryParam("value") String value) {
}
}


CXF configuration:

<bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider" />
<bean id="validationInInterceptor" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
<property name="provider" ref="validationProvider" />
</bean>
<jaxrs:server address="/rest" id="test" staticSubresourceResolution="true">
<jaxrs:serviceBeans>
<ref bean="testResource" />
</jaxrs:serviceBeans>
<jaxrs:inInterceptors>
<ref bean="validationInInterceptor" />
</jaxrs:inInterceptors>
</jaxrs:server>


I found following issues:



but both are about validation of return value not about validation of request parameters.

The question CXF in Karaf: how to configure bean validation on subresources (preferably using Blueprint)? is similar, but about Karaf and Blueprint and contains no solution for my question.

Answer

I would say custom invoker is the way to go. But I guess you already knew that based on your comment.

<bean id="validationProvider" class="org.apache.cxf.validation.BeanValidationProvider" />
<bean id="validationInInterceptor"
    class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInInterceptor">
    <property name="provider" ref="validationProvider" />
</bean>
<bean id="validationInvoker" class="org.apache.cxf.jaxrs.validation.JAXRSBeanValidationInvoker"></bean>

<jaxrs:server address="/rest" id="test"
    staticSubresourceResolution="true">
    <jaxrs:serviceBeans>
        <ref bean="testResource" />
    </jaxrs:serviceBeans>
    <jaxrs:inInterceptors>
        <ref bean="validationInInterceptor" />
    </jaxrs:inInterceptors>
    <jaxrs:invoker>
        <ref bean="validationInvoker" />
    </jaxrs:invoker>
</jaxrs:server>

I tried that on your example, and it works. But I think you need to use an ExceptionMapper, as you don't get proper exceptions. I think ValidationExceptionMapper would be the right one.

Edit- Updated exception mapper class based on comment