title: cxf-codegen-plugin does not comply with cxf ValidationFeature
body: <p>According to <a href="https://cwiki.apache.org/confluence/display/CXF20DOC/ValidationFeature" rel="nofollow noreferrer">ValidationFeature documentation</a> in order for the validation to happen the operations input and output bindings must be annotated with <code>@Valid</code></p>
  
  <p>However, the webservice interface generated by cxf-codegen-plugin does not have these annotations, and I don't seem to find a command line argument or a plugin that allows to add them.</p>
  
  <p>The <code>@Valid</code> annotations cannot be put in the implementation of the webservice interface without violating Liskov substitution principle: the reference implementation of JSR-349 (Hibernate Validator) in this case produces <em>HV000151: A method overriding another method must not alter the parameter constraint configuration</em></p>
  
  <p><strong>Question:</strong> Is anybody aware of a way to annotate the cxf-generated webservice interface method parameters with <code>@Valid</code>? </p>
  
  <p>I'm aware of the existance of the <a href="https://github.com/highsource/jaxb2-annotate-plugin" rel="nofollow noreferrer">Annox plugin</a> but this does not seems to be an easy task to accomplish with it. 
  The easiest solution possible would be to manually add the <code>@Valid</code> annotation to the webservice interface but I'm not comfortable in modifying generated code</p>
  
  <p><strong>Example</strong></p>
  
  <p>pom.xml</p>
  
  <pre><code>&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
      &lt;groupId&gt;org.example.www&lt;/groupId&gt;
      &lt;artifactId&gt;webservice-test-bval&lt;/artifactId&gt;
      &lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;
      &lt;packaging&gt;war&lt;/packaging&gt;
      &lt;name&gt;Test bean validation on web service&lt;/name&gt;
  
      &lt;properties&gt;
          &lt;org.springframework.boot.version&gt;1.4.2.RELEASE&lt;/org.springframework.boot.version&gt;
          &lt;com.github.krasa.krasa-jaxb-tools&gt;1.5&lt;/com.github.krasa.krasa-jaxb-tools&gt;
          &lt;org.apache.cxf.version&gt;3.1.3&lt;/org.apache.cxf.version&gt;
          &lt;cxf-codegen-plugin.version&gt;3.0.1&lt;/cxf-codegen-plugin.version&gt;
      &lt;/properties&gt;
  
  
      &lt;dependencyManagement&gt;
          &lt;dependencies&gt;
              &lt;dependency&gt;
                  &lt;!-- Import dependency management from Spring Boot --&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
                  &lt;version&gt;${org.springframework.boot.version}&lt;/version&gt;
                  &lt;type&gt;pom&lt;/type&gt;
                  &lt;scope&gt;import&lt;/scope&gt;
              &lt;/dependency&gt;
          &lt;/dependencies&gt;
      &lt;/dependencyManagement&gt;
  
  
      &lt;dependencies&gt;
          &lt;!-- Spring boot dependencies --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
              &lt;scope&gt;provided&lt;/scope&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
              &lt;scope&gt;test&lt;/scope&gt;
          &lt;/dependency&gt;
  
  
          &lt;!-- CXF dependencies --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
              &lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;/artifactId&gt;
              &lt;version&gt;${org.apache.cxf.version}&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
              &lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt;
              &lt;version&gt;${org.apache.cxf.version}&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;!-- Schema validation --&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;com.github.krasa&lt;/groupId&gt;
              &lt;artifactId&gt;krasa-jaxb-tools&lt;/artifactId&gt;
              &lt;version&gt;${com.github.krasa.krasa-jaxb-tools}&lt;/version&gt;
              &lt;exclusions&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;javax.validation&lt;/groupId&gt;
                      &lt;artifactId&gt;validation-api&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
              &lt;/exclusions&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
              &lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
          &lt;/dependency&gt;
      &lt;/dependencies&gt;
  
      &lt;build&gt;
          &lt;finalName&gt;${project.artifactId}&lt;/finalName&gt;
          &lt;plugins&gt;
  
              &lt;plugin&gt;
                  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                  &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                  &lt;version&gt;3.1&lt;/version&gt;
                  &lt;configuration&gt;
                      &lt;source&gt;1.8&lt;/source&gt;
                      &lt;target&gt;1.8&lt;/target&gt;
                  &lt;/configuration&gt;
              &lt;/plugin&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
                  &lt;version&gt;${org.springframework.boot.version}&lt;/version&gt;
              &lt;/plugin&gt;
  
              &lt;plugin&gt;
                  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                  &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
                  &lt;configuration&gt;
                      &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
                  &lt;/configuration&gt;
              &lt;/plugin&gt;
  
              &lt;plugin&gt;
                  &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
                  &lt;artifactId&gt;cxf-codegen-plugin&lt;/artifactId&gt;
                  &lt;version&gt;${cxf-codegen-plugin.version}&lt;/version&gt;
                  &lt;executions&gt;
                      &lt;execution&gt;
                          &lt;id&gt;generate-sources&lt;/id&gt;
                          &lt;phase&gt;generate-sources&lt;/phase&gt;
                          &lt;configuration&gt;
                              &lt;sourceRoot&gt;${project.build.directory}/generated/&lt;/sourceRoot&gt;
                              &lt;wsdlOptions&gt;
                                  &lt;wsdlOption&gt;
                                      &lt;wsdl&gt;${project.basedir}/src/main/resources/wsdl/test.wsdl&lt;/wsdl&gt;
                                      &lt;wsdlLocation&gt;classpath:wsdl/test.wsdl&lt;/wsdlLocation&gt;
                                      &lt;extraargs&gt;
                                          &lt;extraarg&gt;-xjc-XJsr303Annotations&lt;/extraarg&gt;
                                      &lt;/extraargs&gt;
                                  &lt;/wsdlOption&gt;
                              &lt;/wsdlOptions&gt;
                          &lt;/configuration&gt;
                          &lt;goals&gt;
                              &lt;goal&gt;wsdl2java&lt;/goal&gt;
                          &lt;/goals&gt;
                      &lt;/execution&gt;
                  &lt;/executions&gt;
                  &lt;dependencies&gt;
                      &lt;dependency&gt;
                          &lt;groupId&gt;com.github.krasa&lt;/groupId&gt;
                          &lt;artifactId&gt;krasa-jaxb-tools&lt;/artifactId&gt;
                          &lt;version&gt;${com.github.krasa.krasa-jaxb-tools}&lt;/version&gt;
                      &lt;/dependency&gt;
                  &lt;/dependencies&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/build&gt;
  &lt;/project&gt;
  </code></pre>
  
  <p><em>src/main/resources/wsdl/</em></p>
  
  <p>test.wsdl</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;
  &lt;wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.org/test/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      name="test" targetNamespace="http://www.example.org/test/"&gt;
      &lt;wsdl:types&gt;
          &lt;xsd:schema targetNamespace="http://www.example.org/test/"&gt;
              &lt;xsd:element name="NewOperation"&gt;
                  &lt;xsd:complexType&gt;
                      &lt;xsd:sequence&gt;
                          &lt;xsd:element name="in"&gt;
                              &lt;xsd:simpleType&gt;
                                  &lt;xsd:restriction base="xsd:int"&gt;
                                      &lt;xsd:minInclusive value="10" /&gt;
                                      &lt;xsd:maxInclusive value="20" /&gt;
                                  &lt;/xsd:restriction&gt;
                              &lt;/xsd:simpleType&gt;
                          &lt;/xsd:element&gt;
                      &lt;/xsd:sequence&gt;
                  &lt;/xsd:complexType&gt;
              &lt;/xsd:element&gt;
              &lt;xsd:element name="NewOperationResponse"&gt;
                  &lt;xsd:complexType&gt;
                      &lt;xsd:sequence&gt;
                          &lt;xsd:element name="out"&gt;
                              &lt;xsd:simpleType&gt;
                                  &lt;xsd:restriction base="xsd:string"&gt;
                                      &lt;xsd:pattern value="[A-Z]+" /&gt;
                                  &lt;/xsd:restriction&gt;
                              &lt;/xsd:simpleType&gt;
                          &lt;/xsd:element&gt;
                      &lt;/xsd:sequence&gt;
                  &lt;/xsd:complexType&gt;
              &lt;/xsd:element&gt;
          &lt;/xsd:schema&gt;
      &lt;/wsdl:types&gt;
      &lt;wsdl:message name="NewOperationRequest"&gt;
          &lt;wsdl:part element="tns:NewOperation" name="parameters" /&gt;
      &lt;/wsdl:message&gt;
      &lt;wsdl:message name="NewOperationResponse"&gt;
          &lt;wsdl:part element="tns:NewOperationResponse" name="parameters" /&gt;
      &lt;/wsdl:message&gt;
      &lt;wsdl:portType name="testWS"&gt;
          &lt;jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"&gt;
              &lt;jaxws:enableWrapperStyle&gt;false&lt;/jaxws:enableWrapperStyle&gt;
          &lt;/jaxws:bindings&gt;
          &lt;wsdl:operation name="NewOperation"&gt;
              &lt;wsdl:input message="tns:NewOperationRequest" /&gt;
              &lt;wsdl:output message="tns:NewOperationResponse" /&gt;
          &lt;/wsdl:operation&gt;
      &lt;/wsdl:portType&gt;
      &lt;wsdl:binding name="testWSSOAP" type="tns:testWS"&gt;
          &lt;soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /&gt;
          &lt;wsdl:operation name="NewOperation"&gt;
              &lt;soap:operation soapAction="http://www.example.org/test/NewOperation" /&gt;
              &lt;wsdl:input&gt;
                  &lt;soap:body use="literal" /&gt;
              &lt;/wsdl:input&gt;
              &lt;wsdl:output&gt;
                  &lt;soap:body use="literal" /&gt;
              &lt;/wsdl:output&gt;
          &lt;/wsdl:operation&gt;
      &lt;/wsdl:binding&gt;
      &lt;wsdl:service name="testWS"&gt;
          &lt;wsdl:port binding="tns:testWSSOAP" name="testWSSOAP"&gt;
              &lt;soap:address location="http://www.example.org/" /&gt;
          &lt;/wsdl:port&gt;
      &lt;/wsdl:service&gt;
  &lt;/wsdl:definitions&gt;
  </code></pre>
  
  <p><em>src/main/java/</em></p>
  
  <p>org.example.test</p>
  
  <pre><code>package org.example.test;
  
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  import org.springframework.boot.web.support.SpringBootServletInitializer;
  
  @SpringBootApplication
  public class Application extends SpringBootServletInitializer {
  
      public static void main(String[] args) {
          SpringApplication.run(Application.class, args);
      }
  }
  
  package org.example.test;
  
  import javax.jws.WebMethod;
  import javax.jws.WebParam;
  import javax.jws.WebResult;
  import javax.jws.WebService;
  import javax.jws.soap.SOAPBinding;
  import javax.validation.Valid;
  import javax.xml.bind.annotation.XmlSeeAlso;
  import javax.xml.ws.RequestWrapper;
  import javax.xml.ws.ResponseWrapper;
  
  import org.example.test.ObjectFactory;
  
  @WebService(targetNamespace = "http://www.example.org/test/", name = "testWS")
  @XmlSeeAlso({ObjectFactory.class})
  @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
  public interface TestWSValid {
  
      @WebMethod(operationName = "NewOperation", action = "http://www.example.org/test/NewOperation")
      @Valid @WebResult(name = "NewOperationResponse", targetNamespace = "http://www.example.org/test/", partName = "parameters")
      public NewOperationResponse newOperation(
              @Valid @WebParam(partName = "parameters", name = "NewOperation", targetNamespace = "http://www.example.org/test/")
          NewOperation parameters
      );
  }
  </code></pre>
  
  <p>org.example.test.configuration</p>
  
  <pre><code>package org.example.test.configuration;
  
  import javax.xml.ws.Endpoint;
  
  import org.apache.cxf.Bus;
  import org.apache.cxf.feature.Feature;
  import org.apache.cxf.jaxws.EndpointImpl;
  import org.apache.cxf.transport.servlet.CXFServlet;
  import org.apache.cxf.validation.BeanValidationFeature;
  import org.example.test.services.TestWSImpl;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.boot.web.servlet.ServletRegistrationBean;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.ImportResource;
  
  @Configuration
  @ImportResource({ "classpath:META-INF/cxf/cxf.xml", "classpath:META-INF/cxf/cxf-servlet.xml" })
  @ComponentScan({ "org.example.test" })
  public class ApplicationConfiguration {
  
      @Autowired
      private Bus cxfBus;
  
      @Bean
      public Endpoint testWSEndpoint() {
          EndpointImpl endpoint = new EndpointImpl(cxfBus, new TestWSImpl());
          endpoint.setAddress("/testws");
          endpoint.publish();
          return endpoint;
      }
  
      @Bean
      public ServletRegistrationBean cxfServlet() {
          ServletRegistrationBean servlet = new ServletRegistrationBean(new CXFServlet(), "/services/*");
          servlet.setLoadOnStartup(1);
          return servlet;
      }
  
      @Bean
      public Feature validationFeature() {
          Feature validationFeature = new BeanValidationFeature();
          validationFeature.initialize(cxfBus);
          cxfBus.getFeatures().add(validationFeature);
          ConstraintViolationInterceptor interceptor = new ConstraintViolationInterceptor();
          cxfBus.getInFaultInterceptors().add(interceptor);
          cxfBus.getOutFaultInterceptors().add(interceptor);
          cxfBus.getProperties().put("exceptionMessageCauseEnabled", true);
          return validationFeature;
      }
  }
  
  package org.example.test.configuration;
  
  import java.text.MessageFormat;
  import java.util.stream.Collectors;
  
  import javax.validation.ConstraintViolationException;
  
  import org.apache.cxf.binding.soap.SoapMessage;
  import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
  import org.apache.cxf.binding.soap.interceptor.Soap11FaultOutInterceptor;
  import org.apache.cxf.interceptor.Fault;
  import org.apache.cxf.phase.Phase;
  
  public class ConstraintViolationInterceptor extends AbstractSoapInterceptor {
  
      public ConstraintViolationInterceptor() {
          super(Phase.MARSHAL);
          getBefore().add(Soap11FaultOutInterceptor.class.getName());
      }
  
      private static final String TEMPLATE = "[{0}] {1} : {2}";
  
      @Override
      public void handleMessage(SoapMessage message) throws Fault {
          Fault fault = (Fault) message.getContent(Exception.class);
          Throwable exception = fault.getCause();
          if (exception instanceof ConstraintViolationException) {
              fault.setMessage(processConstraints((ConstraintViolationException) exception));
          }
      }
  
      private String processConstraints(ConstraintViolationException exception) {
          return exception.getConstraintViolations().stream().map((error) -&gt; {
              return MessageFormat.format(TEMPLATE, error.getPropertyPath(), error.getMessage(), error.getInvalidValue());
          }).collect(Collectors.joining(System.lineSeparator()));
      }
  
  }
  </code></pre>
  
  <p>org.example.test.services</p>
  
  <pre><code>package org.example.test.services;
  
  import javax.jws.WebService;
  
  import org.example.test.NewOperation;
  import org.example.test.NewOperationResponse;
  import org.example.test.ObjectFactory;
  import org.example.test.TestWS;
  
  @WebService(endpointInterface = "org.example.test.TestWS", portName = "TestWSPort", serviceName = "TestWS", targetNamespace = "http://www.example.org/test/")
  public class TestWSImpl implements TestWS {
  
      @Override
      public NewOperationResponse newOperation(NewOperation parameters) {
          int in = parameters.getIn();
          NewOperationResponse response = new ObjectFactory().createNewOperationResponse();
          if (in &lt; 10 || in &gt; 20) {
              response.setOut("no no no");
          } else {
              response.setOut("OK");
          }
          return response;
      }
  
  }
  </code></pre>
  
  <p>With reference to the project above, you can test that as long as <code>TestWSImpl implements TestWS</code> (the generated class) there is no validation occurring, but if <code>TestWSImpl implements TestWSValid</code> (the class that contains the generated code with the <code>@Valid</code> addition) then the validation works as expected</p>