How to configure PayloadValidatingInterceptor using annotation
Asked Answered
D

4

6

I am trying to develop a Spring webservice and followed this tutorial https://spring.io/guides/gs/producing-web-service/

The project structure(and the configuration class names) are same as mentioned in the tutorial. I am trying to do all possible configuration using annotation and want to avoid all xml based configuration. So far I even avoided applicationContext.xml and web.xml by using java configuration. However, now I want to introduce XSD validation as shown in this tutorial: http://stack-over-flow.blogspot.com/2012/03/spring-ws-schema-validation-using.html i.e. by extending the PayloadValidatingInterceptor class.As shown in the tutorial, this custom validator interceptor then needs to be registered using the following xml configuration:

<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
 <property name="interceptors">
  <list>
    <ref bean="validatingInterceptor"/>   
  </list>
 </property>
</bean>

<bean id="validatingInterceptor" class="com.test.ValidationInterceptor ">
     <property name="schema" value="/jaxb/test.xsd"/>
</bean>

However, I am not sue how to do the above configuration using annotation. i.e. setting the XSD file to the interceptor. I have tried overriding the "addInterceptor" of the WsConfigurerAdaptor class to register the interceptor. Please let me know if I need to do that or what is the correct way of doing the entire thing using annotations.

Deloris answered 28/10, 2015 at 15:6 Comment(0)
D
1

I could solve it using following:

@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
    interceptors.add(validationInterceptor());
}
@Bean
ValidationInterceptor validationInterceptor() {
        final ValidationInterceptor payloadValidatingInterceptor = new ValidationInterceptor();
        payloadValidatingInterceptor.setSchema(new ClassPathResource(
                "XSD/Pay.xsd"));
        return payloadValidatingInterceptor;
    }

and then I had to read the schema file from the validator class using the following

SchemaFactory schemaFactory = SchemaFactory.newInstance(getSchemaLanguage());
        Schema schema = schemaFactory.newSchema(getSchemas()[0].getURL());
        Validator validator = schema.newValidator();
Deloris answered 29/10, 2015 at 17:25 Comment(1)
Voted down because code fragment has no context. Not indicated which class to put into. See Julio Villlane's answer below for more complete code.Jumbled
P
5

I'm working with spring-boot and i was looking for a way to do the same, and i found this:

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {

  @Override
  public void addInterceptors(List<EndpointInterceptor> interceptors) {
    PayloadValidatingInterceptor validatingInterceptor = new PayloadValidatingInterceptor();
    validatingInterceptor.setValidateRequest(true);
    validatingInterceptor.setValidateResponse(true);
    validatingInterceptor.setXsdSchema(resourceSchema());
    interceptors.add(validatingInterceptor);
  }

  @Bean
  public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
    MessageDispatcherServlet servlet = new MessageDispatcherServlet();
    servlet.setApplicationContext(applicationContext);
    servlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean(servlet, "/api/*");
  }

  @Bean(name = "registros")
  public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("ResourcePort");
    wsdl11Definition.setLocationUri("/api");
    wsdl11Definition.setTargetNamespace("http://resource.com/schema");
    wsdl11Definition.setSchema(resourceSchema());
    return wsdl11Definition;
  }

  @Bean
  public XsdSchema resourceSchema() {
    return new SimpleXsdSchema(new ClassPathResource("registro.xsd"));
  }
}

In this example the addInterceptors method is the important, the others 3 are basic to expose a WSDL API.

Maybe it'll be useful for someone else.

Pseudohermaphroditism answered 9/5, 2017 at 14:35 Comment(4)
I have more than 1 url and they have different xsd for validation, how to do that?Duclos
Use an approach of 2 different war to separate both configurations is not an option?Pseudohermaphroditism
Thanks for the reply. Actually, I am working on spring boot application and this is part of same. I have already post a detail question #51209067Duclos
upvote on your answer since this is rarerly availble soloution over internetDuclos
D
1

I could solve it using following:

@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
    interceptors.add(validationInterceptor());
}
@Bean
ValidationInterceptor validationInterceptor() {
        final ValidationInterceptor payloadValidatingInterceptor = new ValidationInterceptor();
        payloadValidatingInterceptor.setSchema(new ClassPathResource(
                "XSD/Pay.xsd"));
        return payloadValidatingInterceptor;
    }

and then I had to read the schema file from the validator class using the following

SchemaFactory schemaFactory = SchemaFactory.newInstance(getSchemaLanguage());
        Schema schema = schemaFactory.newSchema(getSchemas()[0].getURL());
        Validator validator = schema.newValidator();
Deloris answered 29/10, 2015 at 17:25 Comment(1)
Voted down because code fragment has no context. Not indicated which class to put into. See Julio Villlane's answer below for more complete code.Jumbled
D
1

I was able to solve it by following way.

@Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
        HotelDirectUpdateRQValidator validatingInterceptor = new HotelDirectUpdateRQValidator();
        validatingInterceptor.setValidateRequest(true);
        validatingInterceptor.setValidateResponse(false);
        validatingInterceptor.setXsdSchemaCollection(new XsdSchemaCollection() {
            @Override
            public XsdSchema[] getXsdSchemas() {
                return null;
            }

            @Override
            public XmlValidator createValidator() {
                try {
                    return XmlValidatorFactory.createValidator(getSchemas(), "http://www.w3.org/2001/XMLSchema");
                } catch (Exception e) {
                    LOGGER.error("Failed to create validator e={}", e);
                }
                return null;
            }

            public Resource[] getSchemas() {
                return new Resource[]{
                        new ClassPathResource("/schemas/OTA/OTA_HotelRateAmountNotifAndHotelAvailNotifRQValidate.xsd"),
                        new ClassPathResource("/schemas/HotelDirectUpdateRQ.xsd")
                };
            }
        });

        interceptors.add(validatingInterceptor);
    }
Duclos answered 10/7, 2018 at 4:26 Comment(0)
G
0

Configure your validator interceptor class in spring.xml like below:

<sws:interceptors>

    <bean id="validatingInterceptor"
            class="com.kalra.xsd.validator.WSDLValidator">
            <property name="xsdSchema" ref="types" />
            <property name="validateRequest" value="true" />
            <property name="validateResponse" value="true" />
    </bean>


</sws:interceptors>

Need to add your bean validatingInterceptor in this tag sws:interceptors so that interceptor will automatically register. For sws prefix need to add xmlns is "xmlns:sws="http://www.springframework.org/schema/web-services" in spring.xml

we should write wsdlvalidator child class of PayloadValidatingInterceptor for our own QNAME to show in response after fault exception otherwise it will pick default qname of sprint ws.

WSDLValidator code snapshot:

import javax.xml.namespace.QName;
import org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor;

public class WSDLValidator extends PayloadValidatingInterceptor {

    public WSDLValidator(){
    }

    @Override
    public QName getDetailElementName() {
        return new QName(Constants.XMLNamespaces.TNS_URI, "SoapValidationFault");
    }

}

SoapValidationFault is complex type declaration in XSD and TNS_URI is target namespace defined in wsdl and xsd.

Granulation answered 12/4, 2019 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.