+++ /dev/null
-
-
-*************************** Porque estoy usando sws:annotation-driven ***************************
-
-Porque estoy usando sws:annotation-driven y no declarando explícitamente los beans en XML existe un
-orden de búsqueda de por defecto de macheadores de endpoints y excepciones. Ver: org.springframework.ws.config.AnnotationDrivenBeanDefinitionParser
-Cuanto más bajo es el valor de order mayor es la prioridad.
-
-
- 1. Manejadores de excepción, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
- a) SoapFaultAnnotationExceptionResolver será el primer manejador de excepciones que se intente usar por defecto. order = 0
- b) SimpleSoapExceptionResolver será el último manejador de excepciones que se intente usar por defecto. order = Ordered.LOWEST_PRECEDENCE
- Se usará si la excepción generada no pudo ser manejada por SoapFaultAnnotationExceptionResolver (porque la excepción no fue anotada con
- @SoapFault. Este manejador se traga cualquier excepción.
-
- 2. Endpoints a buscar, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
- a) PayloadRootAnnotationMethodEndpointMapping será el primer tipo de endpoints que se buscará y que se intentará usar. order = 0
- Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a b).
- b) SoapActionAnnotationMethodEndpointMapping será el segundo tipo de endpoints que se intentará usar. order = 1
- Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a c).
- c) AnnotationActionEndpointMapping será el último tipo de endpoints que se buscará. order = 2
- Si el XML SOAP que llega no machea tampoco métodos anotado con este EndPoint se
- lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
-
-
- EN LUGAR DE USAR LA ANOTACIÓN PODRÍAMOS HABER DECLARADO EXPLÍCITAMENTE CADA BEAN TAL QUE ASÍ:
-
- <bean id="soapFaultMappingExceptionResolver"
- class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
- <property name="order" value="0" />
- </bean>
-
- <bean id="payloadRootAnnotationMethodEndpointMapping"
- class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
- <property name="order" value="0" />
- </bean>
-
- CON LA ANOTACIÓN ME AHORRO DECLARAR bean POR bean PERO LO MALO ES QUE INSTANCIO MANEJADORES QUE LUEGO NO USO :(
-
-
-
-
-*************************** org.springframework.ws.server.MessageDispatcher ***************************
-
-
-org.springframework.ws.server.MessageDispatcher ES LA CLASE QUE BUSCA EndPoints Y MANEJADORES DE EXCEPCIÓN
-
-ORDEN DE BUSQUEDA DE IMPLEMENTACIONES DE MANEJADORES DE EXCEPCION
-Busca en el ApplicationContext manejadores de excepción siguiendo este orden. Cuanto más bajo es el valor de order
-mayor es la prioridad.
-
-Por haber usado sws:annotation-driven el orden es el siguiente:
-
-
-1. Primero se busca por excepciones anotadas con @SoapFault. Si la excepcion generada
-está anotada son @SoapFault entonces se usa este manejador de excepcion.
-
-Implementation of the org.springframework.ws.server.EndpointExceptionResolver interface
-that uses the SoapFault annotation to map exceptions to SOAP Faults.
-org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver
-
-
-
-2. Segundo usa este manejador de excepción. Este manejador machea cualquier excepción así que si
-este manejador llega primero siempre resolverá la excepción.
-Simple, SOAP-specific EndpointExceptionResolver implementation that stores
-the exception's message as the fault string.
-org.springframework.ws.soap.server.endpoint.SimpleSoapExceptionResolver
-
-
-3. Un manejador de excepciones inyectado por mi en un archivo XML de Spring. Si no se pone prioridad por defecto
-Spring le pone la prioridad más baja que es lo que me pasó a mí al principio y SimpleSoapExceptionResolver
-se meterá siempre por el medio :(
-org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
-
-
-Si ninguno machea MessageDispatcher lanza la Excepción desde org.springframework.ws.server.MessageDispatcher.processEndpointException()
-
-
-
-ORDEN DE BUSQUEDA DE ENDPOINTS EN EL APPLICATION CONTEXT:
-Busca en el ApplicationContext metodos anotados siguiendo este orden. Si el XML SOAP que me llega
-machea con alguna de estas anotaciones, entonces ese método anotado será usado. Y NO SE CONTINUARÁ
-BUSCANDO MÁS MANEJADORES. EN CUANTO UNO MACHEA YA NO SE BUSCA POR MÁS.
-
-
-Por haber usado sws:annotation-driven el orden es el siguiente:
-
-
-1. Primero se busca por métodos de este modo. Si el XML SOAP machea con algún metodo anotado
-de este modo, entonces ese método será usado y no se continúa buscando matches.
-
-Implementation of the org.springframework.ws.server.EndpointMapping interface that uses the
-PayloadRoot annotation to map methods to request payload root elements.
-org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping
-@Endpoint
-public class MyEndpoint {
-
- @PayloadRoot(localPart = "Request", namespace = "http://springframework.org/spring-ws")
- public Source doSomethingWithRequest() {
- ...
- }
-}
-
-2. Segundo se busca por métodos de este modo. Si el XML SOAP machea con algún metodo anotado
-de este modo, entonces ese método será usado y no se continúa buscando matches.
-
-Implementation of the org.springframework.ws.server.EndpointMapping interface that uses the
-SoapAction annotation to map methods to the request SOAPAction header.
-org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping
-@Endpoint
-public class MyEndpoint{
-
- @SoapAction("http://springframework.org/spring-ws/SoapAction")
- public Source doSomethingWithRequest() {
- ...
- }
-}
-
-
-3. Tercero se busca por métodos de este modo. Si el XML SOAP machea con algún metodo anotado
-de este modo, entonces ese método será usado.
-
-Implementation of the org.springframework.ws.server.EndpointMapping interface that uses the
-@Action annotation to map methods to a WS-Addressing Action header.
-org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping
-@Endpoint
-@Address("mailto:joe@fabrikam123.example")
-public class MyEndpoint{
-
- @Action("http://fabrikam123.example/mail/Delete")
- public Source doSomethingWithRequest() {
- ...
- }
-}
-
-
-Si ninguno machea MessageDispatcher lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
SpringWebServicesForFun
=======================
+SOAP
+
Messing around with Spring Web Services
mvn clean install
mvn clean install -Dmaven.test.skip=true
-TODO: using Jetty instead of Tomcat
For debugging: export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y"
--- /dev/null
+
+
+*************************** Porque estoy usando sws:annotation-driven ***************************
+
+Porque estoy usando sws:annotation-driven y no declarando explícitamente los beans en XML existe un
+orden de búsqueda de por defecto de macheadores de endpoints y excepciones. Ver: org.springframework.ws.config.AnnotationDrivenBeanDefinitionParser
+Cuanto más bajo es el valor de order mayor es la prioridad.
+
+
+ 1. Manejadores de excepción, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
+ a) SoapFaultAnnotationExceptionResolver será el primer manejador de excepciones que se intente usar por defecto. order = 0
+ b) SimpleSoapExceptionResolver será el último manejador de excepciones que se intente usar por defecto. order = Ordered.LOWEST_PRECEDENCE
+ Se usará si la excepción generada no pudo ser manejada por SoapFaultAnnotationExceptionResolver (porque la excepción no fue anotada con
+ @SoapFault. Este manejador se traga cualquier excepción.
+
+ 2. Endpoints a buscar, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
+ a) PayloadRootAnnotationMethodEndpointMapping será el primer tipo de endpoints que se buscará y que se intentará usar. order = 0
+ Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a b).
+ b) SoapActionAnnotationMethodEndpointMapping será el segundo tipo de endpoints que se intentará usar. order = 1
+ Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a c).
+ c) AnnotationActionEndpointMapping será el último tipo de endpoints que se buscará. order = 2
+ Si el XML SOAP que llega no machea tampoco métodos anotado con este EndPoint se
+ lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
+
+
+ EN LUGAR DE USAR LA ANOTACIÓN PODRÍAMOS HABER DECLARADO EXPLÍCITAMENTE CADA BEAN TAL QUE ASÍ:
+
+ <bean id="soapFaultMappingExceptionResolver"
+ class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
+ <property name="order" value="0" />
+ </bean>
+
+ <bean id="payloadRootAnnotationMethodEndpointMapping"
+ class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
+ <property name="order" value="0" />
+ </bean>
+
+ CON LA ANOTACIÓN ME AHORRO DECLARAR bean POR bean PERO LO MALO ES QUE INSTANCIO MANEJADORES QUE LUEGO NO USO :(
+
+
+
+
+*************************** org.springframework.ws.server.MessageDispatcher ***************************
+
+
+org.springframework.ws.server.MessageDispatcher ES LA CLASE QUE BUSCA EndPoints Y MANEJADORES DE EXCEPCIÓN
+
+ORDEN DE BUSQUEDA DE IMPLEMENTACIONES DE MANEJADORES DE EXCEPCION
+Busca en el ApplicationContext manejadores de excepción siguiendo este orden. Cuanto más bajo es el valor de order
+mayor es la prioridad.
+
+Por haber usado sws:annotation-driven el orden es el siguiente:
+
+
+1. Primero se busca por excepciones anotadas con @SoapFault. Si la excepcion generada
+está anotada son @SoapFault entonces se usa este manejador de excepcion.
+
+Implementation of the org.springframework.ws.server.EndpointExceptionResolver interface
+that uses the SoapFault annotation to map exceptions to SOAP Faults.
+org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver
+
+
+
+2. Segundo usa este manejador de excepción. Este manejador machea cualquier excepción así que si
+este manejador llega primero siempre resolverá la excepción.
+Simple, SOAP-specific EndpointExceptionResolver implementation that stores
+the exception's message as the fault string.
+org.springframework.ws.soap.server.endpoint.SimpleSoapExceptionResolver
+
+
+3. Un manejador de excepciones inyectado por mi en un archivo XML de Spring. Si no se pone prioridad por defecto
+Spring le pone la prioridad más baja que es lo que me pasó a mí al principio y SimpleSoapExceptionResolver
+se meterá siempre por el medio :(
+org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
+
+
+Si ninguno machea MessageDispatcher lanza la Excepción desde org.springframework.ws.server.MessageDispatcher.processEndpointException()
+
+
+
+ORDEN DE BUSQUEDA DE ENDPOINTS EN EL APPLICATION CONTEXT:
+Busca en el ApplicationContext metodos anotados siguiendo este orden. Si el XML SOAP que me llega
+machea con alguna de estas anotaciones, entonces ese método anotado será usado. Y NO SE CONTINUARÁ
+BUSCANDO MÁS MANEJADORES. EN CUANTO UNO MACHEA YA NO SE BUSCA POR MÁS.
+
+
+Por haber usado sws:annotation-driven el orden es el siguiente:
+
+
+1. Primero se busca por métodos de este modo. Si el XML SOAP machea con algún metodo anotado
+de este modo, entonces ese método será usado y no se continúa buscando matches.
+
+Implementation of the org.springframework.ws.server.EndpointMapping interface that uses the
+PayloadRoot annotation to map methods to request payload root elements.
+org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping
+@Endpoint
+public class MyEndpoint {
+
+ @PayloadRoot(localPart = "Request", namespace = "http://springframework.org/spring-ws")
+ public Source doSomethingWithRequest() {
+ ...
+ }
+}
+
+2. Segundo se busca por métodos de este modo. Si el XML SOAP machea con algún metodo anotado
+de este modo, entonces ese método será usado y no se continúa buscando matches.
+
+Implementation of the org.springframework.ws.server.EndpointMapping interface that uses the
+SoapAction annotation to map methods to the request SOAPAction header.
+org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping
+@Endpoint
+public class MyEndpoint{
+
+ @SoapAction("http://springframework.org/spring-ws/SoapAction")
+ public Source doSomethingWithRequest() {
+ ...
+ }
+}
+
+
+3. Tercero se busca por métodos de este modo. Si el XML SOAP machea con algún metodo anotado
+de este modo, entonces ese método será usado.
+
+Implementation of the org.springframework.ws.server.EndpointMapping interface that uses the
+@Action annotation to map methods to a WS-Addressing Action header.
+org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping
+@Endpoint
+@Address("mailto:joe@fabrikam123.example")
+public class MyEndpoint{
+
+ @Action("http://fabrikam123.example/mail/Delete")
+ public Source doSomethingWithRequest() {
+ ...
+ }
+}
+
+
+Si ninguno machea MessageDispatcher lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>web-services-spring-cxf</artifactId>
+ <groupId>de.spring.webservices</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>web-services-spring-cxf-client</artifactId>
+ <name>web-services-spring-cxf-client</name>
+ <url>http://gumartinm.name</url>
+
+ <properties>
+ <project.wsdl.sources.path>src/main/build-resources/wsdl</project.wsdl.sources.path>
+ <project.wsdl.target.path>${basedir}/target/generated-sources/src/main/java</project.wsdl.target.path>
+ <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
+ <!-- Requires absolute path (because of that I am using ${basedir} -->
+ <project.catalogs.path>${basedir}/src/main/build-resources/catalogs</project.catalogs.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-xml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ </dependency>
+
+
+ <!-- Global types -->
+ <dependency>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-cxf-globalxsds</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <!-- Required by spring-ws-core -->
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ </dependency>
+
+ <!-- Required by jaxb2-basics as specified: http://confluence.highsource.org/display/J2B/Using+JAXB2+Basics+Plugins+with+CXF -->
+ <dependency>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-runtime</artifactId>
+ <version>0.9.4</version>
+ </dependency>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/resources/</directory>
+ <includes>
+ <include>**/*.*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <!-- Generate code from wsdl files: We could use maven-jaxb2-plugin in
+ order to generate Java classes from WSDL files but this plugin seems more
+ useful so, I keep using it. Besides, it is based on Apache CXF which as well,
+ uses jaxb. See: http://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html -->
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-codegen-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>generate-sources-from-wsdl</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>wsdl2java</goal>
+ </goals>
+ <configuration>
+ <fork>true</fork>
+ <sourceRoot>${project.wsdl.target.path}</sourceRoot>
+ <wsdlOptions>
+ <wsdlOption>
+ <wsdl>${project.wsdl.sources.path}/example.wsdl</wsdl>
+ <bindingFiles>
+ <bindingFile>${project.bindings.path}/custombinding.xjb</bindingFile>
+ </bindingFiles>
+ <extraargs>
+ <extraarg>-xjc-Xinheritance</extraarg>
+ <extraarg>-xjc-Xannotate</extraarg>
+ <extraarg>-catalog</extraarg>
+ <extraarg>${project.catalogs.path}/catalog.cat</extraarg>
+ <extraarg>-verbose</extraarg>
+ </extraargs>
+ </wsdlOption>
+ </wsdlOptions>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <!-- We make this plugin work with this jaxb2 version. This particular
+ version let us generate inherited classes using the -Xinheritance argument.
+ DO NOT FORGET: We can use <inheritance:implements> in xsd files or by means
+ of custom bindings (see custombinding.xjb) This is useful when you may not
+ modify xsd files because they are generated by other person or machine. -->
+ <dependency>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics</artifactId>
+ <version>0.9.4</version>
+ </dependency>
+
+ <!-- We make this plugin work with this jaxb2 version. This particular
+ version let us generate annotated classes using the -Xannotate argument.
+ DO NOT FORGET: We can use <annox:annotate> in xsd files or by means of custom
+ bindings like I did with <inheritance:implements> (see custombinding.xjb)
+ This is useful when you may not modify xsd files because they are generated
+ by other person or machine. -->
+ <dependency>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-annotate</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.9.1</version>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${project.wsdl.target.path}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<jaxws:bindings
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="xjc inheritance annox">
+
+ <!--
+ Perhaps it would be better to relay on the package generated automatically from WSDL
+ In a real project, I guess, I should use the package generated from WSDL file...
+ -->
+ <jaxws:bindings
+ node="wsdl:definitions">
+ <jaxws:package name="de.spring.webservices.client.auto"/>
+ </jaxws:bindings>
+
+
+ <!--
+ XSD namespace for included schema in WSDL: http://gumartinm.name/spring-ws/example
+
+ I am skiping the XSD namespace for imported schema in WSDL: http://gumartinm.name/spring-ws/parent because I guess,
+ there must be some way of using the already generated code in web-services-spring-globalxsds instead of generating new one
+ (perhaps using maven-jaxb2-plugin with episodes)
+ -->
+ <jaxws:bindings
+ node="wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://gumartinm.name/spring-ws/example']">
+
+ <!--
+ Perhaps it would be better to relay on the package generated automatically from WSDL
+ In a real project, I guess, I should use the package generated from WSDL file...
+ -->
+ <jaxb:schemaBindings>
+ <jaxb:package name="de.spring.webservices.client.auto"/>
+ </jaxb:schemaBindings>
+
+ <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleRequest']/xsd:complextype">
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ <annox:annotate>@java.lang.suppresswarnings({"unchecked","rawtypes"})</annox:annotate>
+ </jaxb:bindings>
+
+ <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleResponse']/xsd:complextype">
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ <annox:annotate>@java.lang.suppresswarnings({"unchecked","rawtypes"})</annox:annotate>
+ </jaxb:bindings>
+
+ <jaxb:globalBindings>
+ <xjc:javaType adapter="de.spring.webservices.binders.XSDateTimeCustomBinder"
+ name="java.util.Date" xmlType="xsd:dateTime" />
+ </jaxb:globalBindings>
+
+ </jaxws:bindings>
+
+</jaxws:bindings>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system|public" >
+
+ <!--
+ An XML catalog will allow us to specify real locations for our imported XML schemas.
+ The XJC tool supports several different XML Catalog formats: TR9401, XCatalog, OASIS XML Catalog.
+ I am using OASIS XML Catalog Format
+
+ OASIS XML Catalog Format: https://www.oasis-open.org/committees/entity/specs/cs-entity-xml-catalogs-1.0.html
+ TR9401: https://www.oasis-open.org/specs/a401.htm
+
+
+ See: http://labs.bsb.com/2011/01/usage-of-an-xml-catalog-in-the-xmlbeans-cxf-integration/
+ http://cxf.apache.org/cxf-xjc-plugin.html
+ https://jaxb.java.net/2.2.4/docs/catalog.html
+ -->
+
+
+ <!-- I JUST NEED THIS CONFIGURATION, ANYHOW I AM WRITING ALL OF THEM -->
+ <rewriteSystem systemIdStartString="http://gumartinm.name/spring-ws/parent"
+ rewritePrefix="classpath:parent.xsd"/>
+
+
+ <!-- THE FOLLOWING ONES ARE NOT REQUIRED EVEN IF I AM WRITING THEM -->
+ <public
+ publicId="http://gumartinm.name/spring-ws/parent"
+ uri="classpath:parent.xsd"/>
+
+
+ <system
+ systemId="http://gumartinm.name/spring-ws/parent/parent.xsd"
+ uri="classpath:parent.xsd"/>
+
+
+ <rewriteURI uriStartString="http://gumartinm.name/spring-ws/parent"
+ rewritePrefix="classpath:parent.xsd"/>
+
+</catalog>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://gumartinm.name/spring-ws/example" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://gumartinm.name/spring-ws/exampleService" targetNamespace="http://gumartinm.name/spring-ws/exampleService">
+ <wsdl:types>
+ <xsd:schema xmlns="http://gumartinm.name/spring-ws/example" xmlns:annox="http://annox.dev.java.net" xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:parent="http://gumartinm.name/spring-ws/parent" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" jaxb:extensionBindingPrefixes="inheritance annox" jaxb:version="2.1" targetNamespace="http://gumartinm.name/spring-ws/example">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <!--
+ We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
+ when creating Java objects from examples.xsd.
+ -->
+ <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd"/>
+
+
+ <!-- Spring requires the following:
+ 1. XSD elements being used as request must end with Request name.
+ 2. XSD elements being used as response must end with Response name.
+
+ IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
+
+ ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
+ the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
+ The same for CustomBindingExample.
+ -->
+ <!-- Using inheritance and annox plugin -->
+ <xsd:element name="ExampleRequest">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="parent:limitedString"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleResponse">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- Using custombinding.xjb instead of inheritance plugin.
+ Useful when you can not modify your xsd files because they are provided
+ by another person or company
+ -->
+ <xsd:element name="CustomBindingExampleRequest">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleResponse">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Example of creating array list by means of XSD -->
+ <xsd:complexType name="car">
+ <xsd:sequence>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="100" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="truck">
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:all>
+ </xsd:complexType>
+ <xsd:element name="vehicles">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" name="cars" type="car"/>
+ <xsd:element maxOccurs="100" minOccurs="0" name="trucks" type="truck"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
+ </wsdl:types>
+ <wsdl:message name="ExampleFault">
+ <wsdl:part element="sch:ExampleFault" name="ExampleFault">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="CustomBindingExampleFault">
+ <wsdl:part element="sch:CustomBindingExampleFault" name="CustomBindingExampleFault">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="ExampleRequest">
+ <wsdl:part element="sch:ExampleRequest" name="ExampleRequest">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="ExampleResponse">
+ <wsdl:part element="sch:ExampleResponse" name="ExampleResponse">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="CustomBindingExampleResponse">
+ <wsdl:part element="sch:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="CustomBindingExampleRequest">
+ <wsdl:part element="sch:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:portType name="Examples">
+ <wsdl:operation name="Example">
+ <wsdl:input message="tns:ExampleRequest" name="ExampleRequest">
+ </wsdl:input>
+ <wsdl:output message="tns:ExampleResponse" name="ExampleResponse">
+ </wsdl:output>
+ <wsdl:fault message="tns:ExampleFault" name="ExampleFault">
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="CustomBindingExample">
+ <wsdl:input message="tns:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
+ </wsdl:input>
+ <wsdl:output message="tns:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
+ </wsdl:output>
+ <wsdl:fault message="tns:CustomBindingExampleFault" name="CustomBindingExampleFault">
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="ExamplesSoap12" type="tns:Examples">
+ <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <wsdl:operation name="Example">
+ <soap12:operation soapAction=""/>
+ <wsdl:input name="ExampleRequest">
+ <soap12:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="ExampleResponse">
+ <soap12:body use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ExampleFault">
+ <soap12:fault name="ExampleFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="CustomBindingExample">
+ <soap12:operation soapAction=""/>
+ <wsdl:input name="CustomBindingExampleRequest">
+ <soap12:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="CustomBindingExampleResponse">
+ <soap12:body use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="CustomBindingExampleFault">
+ <soap12:fault name="CustomBindingExampleFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="ExamplesService">
+ <wsdl:port binding="tns:ExamplesSoap12" name="ExamplesSoap12">
+ <soap12:address location="http://localhost:8080/web-services-spring-cxf-server/spring-ws/example"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>
\ No newline at end of file
--- /dev/null
+package de.spring.webservices.client;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import javax.xml.transform.Source;
+
+// cxf-codegen-plugin DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
+// So I guess it is better to use the objects generated in this package
+// than the ones from globalxsds even if they should be the same.
+import name.gumartinm.spring_ws.parent.GeneralFault;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.oxm.XmlMappingException;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.client.core.FaultMessageResolver;
+import org.springframework.ws.soap.SoapBody;
+import org.springframework.ws.soap.SoapFault;
+import org.springframework.ws.soap.SoapFaultDetail;
+import org.springframework.ws.soap.SoapFaultDetailElement;
+import org.springframework.ws.soap.SoapMessage;
+import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
+
+/**
+ * Enables us to log custom Fault remote messages.
+ *
+ */
+public class CustomFaultMessageResolver implements FaultMessageResolver {
+
+private static final Logger LOGGER = LoggerFactory.getLogger(CustomFaultMessageResolver.class);
+
+ private final FaultMessageResolver defaultMessageResolver = new SoapFaultMessageResolver();
+
+ private Unmarshaller unmarshaller;
+
+ @Override
+ public void resolveFault(WebServiceMessage message) throws IOException {
+
+ // Same behavior as default message resolver (SoapFaultMessageResolver) but this implementation also
+ // logs error information.
+ if (LOGGER.isErrorEnabled()) {
+ try {
+ logErrorInformation(message);
+ } catch (Exception ex) {
+ LOGGER.error("CustomFaultMessageResolver exception:", ex);
+ }
+ }
+
+ defaultMessageResolver.resolveFault(message);
+ }
+
+ private void logErrorInformation(WebServiceMessage message) throws XmlMappingException, IOException {
+ SoapMessage soapMessage = (SoapMessage) message;
+ SoapBody body = soapMessage.getSoapBody();
+ SoapFault soapFault = body != null ? body.getFault() : null;
+ SoapFaultDetail detail = soapFault != null ? soapFault.getFaultDetail() : null;
+
+ if (detail != null) {
+ Iterator<SoapFaultDetailElement> iterator = detail.getDetailEntries();
+ while (iterator.hasNext()) {
+ SoapFaultDetailElement bodyElement = iterator.next();
+ Source detailSource = bodyElement.getSource();
+ // TODO: How to check if I am receiving GeneralFault before trying to unmarshal?
+ // Right now there will be exception if unmarshal doesn't return a GeneralFault object.
+ GeneralFault error = (GeneralFault)this.unmarshaller.unmarshal(detailSource);
+ LOGGER.error("TECHNICALERROR:");
+ LOGGER.error(error.getTechnicalError());
+ LOGGER.error("ELEMENTS:");
+ error.getElements().forEach(element -> {
+ LOGGER.error("MESSAGE: " + element.getMessage());
+ LOGGER.error("MESSAGEARGS:");
+ element.getMessageArgs().forEach(messageArg -> LOGGER.error(messageArg));
+ });
+ }
+ }
+ }
+
+ public void setUnmarshaller(Unmarshaller unmarshaller) {
+ this.unmarshaller = unmarshaller;
+ }
+}
--- /dev/null
+package de.spring.webservices.client;
+
+import name.gumartinm.spring_ws.parent.ParentEnumType;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.ws.client.core.WebServiceTemplate;
+
+import de.spring.webservices.client.auto.CustomBindingExampleFault_Exception;
+import de.spring.webservices.client.auto.CustomBindingExampleRequest;
+import de.spring.webservices.client.auto.CustomBindingExampleResponse;
+import de.spring.webservices.client.auto.ExampleFault_Exception;
+import de.spring.webservices.client.auto.ExampleRequest;
+import de.spring.webservices.client.auto.ExampleResponse;
+import de.spring.webservices.client.auto.Examples;
+import de.spring.webservices.client.auto.ExamplesService;
+
+/**
+ * Someone could write code like this one in order to send and receive
+ * information from our Web Services.
+ *
+ */
+@Service("exampleClientService")
+public class ExampleClientService {
+ private final WebServiceTemplate webServiceTemplate;
+
+ @Autowired
+ public ExampleClientService(WebServiceTemplate webServiceTemplate) {
+ this.webServiceTemplate = webServiceTemplate;
+ }
+
+ public ExampleResponse sendAndReceiveJava() throws ExampleFault_Exception {
+ final ExampleRequest exampleRequest = new ExampleRequest();
+ exampleRequest.setData("SCARLETT JAVA. IT IS CANON.");
+
+ final Examples exampleService = new ExamplesService().getExamplesSoap12();
+ final ExampleResponse exampleResponse = exampleService.example(exampleRequest);
+
+ return exampleResponse;
+ }
+
+ public ExampleResponse sendAndReceiveSpring() {
+ final ExampleRequest exampleRequest = new ExampleRequest();
+ exampleRequest.setData("SCARLETT SPRING. IT IS CANON.");
+
+ final ExampleResponse exampleResponse = (ExampleResponse)
+ this.webServiceTemplate.marshalSendAndReceive(exampleRequest);
+
+ return exampleResponse;
+ }
+
+ public CustomBindingExampleResponse sendAndReceiveJavaCustom() throws CustomBindingExampleFault_Exception {
+ final CustomBindingExampleRequest customBindingxampleRequest =
+ new CustomBindingExampleRequest();
+ customBindingxampleRequest.setData("CUSTOM BINDING JAVA. SCARLETT. IT IS CANON.");
+ customBindingxampleRequest.setParentEnum(ParentEnumType.FIRST);
+
+ final Examples exampleService = new ExamplesService().getExamplesSoap12();
+ final CustomBindingExampleResponse customBindingExampleResponse =
+ exampleService.customBindingExample(customBindingxampleRequest);
+
+ return customBindingExampleResponse;
+ }
+
+ public CustomBindingExampleResponse sendAndReceiveSpringCustom() {
+ final CustomBindingExampleRequest customBindingxampleRequest =
+ new CustomBindingExampleRequest();
+ customBindingxampleRequest.setData("CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.");
+
+ final CustomBindingExampleResponse customBindingExampleResponse =
+ (CustomBindingExampleResponse) this.webServiceTemplate
+ .marshalSendAndReceive(customBindingxampleRequest);
+
+ return customBindingExampleResponse;
+ }
+}
--- /dev/null
+package de.spring.webservices.client;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import de.spring.webservices.client.auto.CustomBindingExampleFault;
+import de.spring.webservices.client.auto.CustomBindingExampleResponse;
+import de.spring.webservices.client.auto.ExampleFault;
+import de.spring.webservices.client.auto.ExampleResponse;
+
+/**
+ * This class is used just like a nice example about how to write and run client
+ * code which will send data to and from the Web Services.
+ *
+ */
+public class MainTest {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MainTest.class);
+
+ public ApplicationContext context;
+
+ /**
+ * @param args
+ * @throws ExampleFault_Exception
+ * @throws CustomBindingExampleFault_Exception
+ */
+ public static void main(final String[] args) {
+ final MainTest test = new MainTest();
+
+ test.context = new ClassPathXmlApplicationContext(
+ "classpath:spring-configuration/ws/client-spring-configuration.xml");
+
+ final ExampleClientService example =
+ (ExampleClientService) test.context.getBean("exampleClientService");
+
+ LOGGER.info("ExampleResponse Java:");
+ ExampleResponse response;
+ try {
+ response = example.sendAndReceiveJava();
+ LOGGER.info(response.getData());
+ } catch (Exception e) {
+ LOGGER.info("ExampleResponse Java error:", e);
+ }
+
+
+
+ LOGGER.info("CustomBindingExampleResponse Java:");
+ CustomBindingExampleResponse customBindingResponse;
+ try {
+ customBindingResponse = example.sendAndReceiveJavaCustom();
+ LOGGER.info(customBindingResponse.getData());
+ } catch (Exception e) {
+ LOGGER.info("CustomBindingExampleResponse Java error:", e);
+ }
+
+
+
+ LOGGER.info("ExampleResponse Spring:");
+ response = example.sendAndReceiveSpring();
+ LOGGER.info(response.getData());
+
+
+ LOGGER.info("CustomBindingExampleResponse Spring:");
+ customBindingResponse = example.sendAndReceiveSpringCustom();
+ LOGGER.info(customBindingResponse.getData());
+ }
+}
--- /dev/null
+package de.spring.webservices.client.transport.http;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.ws.transport.WebServiceConnection;
+import org.springframework.ws.transport.http.AbstractHttpWebServiceMessageSender;
+import org.springframework.ws.transport.http.ClientHttpRequestConnection;
+import org.springframework.ws.transport.http.HttpTransportConstants;
+
+
+/**
+ * Based on ClientHttpRequestMessageSender from the Spring WS framework.
+ *
+ * <p>
+ * Spring WS framework also provides implementations based on the HTTP clients by Jakarta and Apache HttpClient:
+ * {@link https://hc.apache.org/httpcomponents-client-ga/} and {@link http://hc.apache.org/httpclient-3.x/}
+ * </p>
+ *
+ * <p>
+ * Four implementations for four HTTP clients:
+ * <ul>
+ * <li> org.springframework.ws.transport.http.ClientHttpRequestMessageSender (ClientHttpRequestFactory from the Spring framework) </li>
+ * <li> org.springframework.ws.transport.http.CommonsHttpMessageSender (Jakarta implementation) </li>
+ * <li> org.springframework.ws.transport.http.HttpComponentsMessageSender (Apache HttpClient) </li>
+ * <li> org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
+ * (org.springframework.ws.transport.http.HttpUrlConnection internal Spring framework implementation) </li>
+ * </ul>
+ * </p>
+ */
+public class CustomHttpRequestMessageSender extends AbstractHttpWebServiceMessageSender {
+ private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
+
+ private final ClientHttpRequestFactory requestFactory;
+
+ public CustomHttpRequestMessageSender() {
+ requestFactory = new SimpleClientHttpRequestFactory();
+ }
+
+ @Override
+ public WebServiceConnection createConnection(URI uri) throws IOException {
+ ClientHttpRequest request = requestFactory.createRequest(uri, HttpMethod.POST);
+ if (isAcceptGzipEncoding()) {
+ request.getHeaders().add(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
+ HttpTransportConstants.CONTENT_ENCODING_GZIP);
+ }
+
+ request.getHeaders().add(MY_CUSTOM_HEADER, "gumartinm.name");
+
+ return new ClientHttpRequestConnection(request);
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:parent="http://gumartinm.name/spring-ws/parent"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="inheritance annox"
+ targetNamespace="http://gumartinm.name/spring-ws/example"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <!--
+ We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
+ when creating Java objects from examples.xsd.
+ -->
+ <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
+
+
+ <!-- Spring requires the following:
+ 1. XSD elements being used as request must end with Request name.
+ 2. XSD elements being used as response must end with Response name.
+
+ IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
+
+ ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
+ the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
+ The same for CustomBindingExample.
+ -->
+ <!-- Using inheritance and annox plugin -->
+ <xsd:element name="ExampleRequest">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="parent:limitedString" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleResponse">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- Using custombinding.xjb instead of inheritance plugin.
+ Useful when you can not modify your xsd files because they are provided
+ by another person or company
+ -->
+ <xsd:element name="CustomBindingExampleRequest">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleResponse">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Example of creating array list by means of XSD -->
+ <xsd:complexType name="car">
+ <xsd:sequence>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="truck">
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ <xsd:element name="vehicles">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="cars" type="car" maxOccurs="unbounded" />
+ <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ status: The level of internal Log4j events that should be logged to the console.
+ Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
+
+ monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
+
+
+ see https://logging.apache.org/log4j/2.x/manual/configuration.html
+ -->
+<Configuration status="error" strict="true" monitorInterval="30"
+ name="XMLConfigTest" packages="org.apache.logging.log4j.test">
+
+ <!--
+ ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
+
+ ERROR by default.
+ -->
+
+ <Appenders>
+ <Appender type="Console" name="STDOUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
+ </Appender>
+ </Appenders>
+ <Loggers>
+
+
+ <!--
+ Specific log when request message from this client or response message created by remote server contains validation errors.
+
+ see client-spring-configuration.xml Spring configuration file.
+
+ This configuration enables us to log validation errors of data sent from this client or data sent by remote server.
+ -->
+ <Logger name="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+ <!--
+ Con esta configuración podemos loguear mensajes de error (SOAP Fault) procedentes del sevidor customizados. En mi caso
+ usando GeneralFault. No se loguean los de validación (ni de envio de cliente ni de respuesta desde el servidor)
+ porque esto lo hace PayloadValidatingInterceptor.
+ -->
+ <Logger name="de.spring.webservices.client.CustomFaultMessageResolver" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+ <!-- Specific log level for SOAP XML messages.
+
+ see client-spring-configuration.xml Spring configuration file.
+
+ This configuration enables us to log the SOAP XML Request (sent from this client), Response (sent by remote server) and Fault (sent by remote server).
+ -->
+ <Logger name="org.springframework.ws.client.MessageTracing" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+ <Logger name="org.springframework.ws.server.MessageTracing" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+ <!--
+ Specific log level for Spring WS.
+ -->
+ <Logger name="org.springframework.ws" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ General logging Spring.
+ -->
+ <Logger name="org.springframework" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ Anything else will be using TRACE logging level.
+ -->
+ <Root level="INFO">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:sws="http://www.springframework.org/schema/web-services"
+ xmlns:oxm="http://www.springframework.org/schema/oxm"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:util="http://www.springframework.org/schema/util"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/web-services
+ http://www.springframework.org/schema/web-services/web-services.xsd
+ http://www.springframework.org/schema/oxm
+ http://www.springframework.org/schema/oxm/spring-oxm.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+ <!--
+ This file is an example about how someone should write code in order to send and
+ receive data from the Web Services.
+ -->
+
+ <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Component, etc, etc) -->
+ <context:component-scan base-package="de.spring.webservices"/>
+
+ <!--
+ Three ways of using a marshallers/unmarshallers.
+
+ 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
+ Esto equivale a esta configuracion en XML
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
+ El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
+
+ 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
+ se hace de este modo:
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.auto"/>
+ Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
+ de especificar un context-path en concreto.
+
+ 3. Especificando la implementación concreta del marshaller.
+ Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
+ cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
+ De todos modos, probablemente habría que usar un package distinto para lo que hay
+ en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
+
+
+ <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
+ <property name="packagesToScan" value="de.spring.webservices.auto"/>
+ </bean>
+
+ NO PUEDO USAR ESTA CONFIGURACION PORQUE SE PRODUCE ESTE ERROR:
+
+ Caused by: org.springframework.oxm.UncategorizedMappingException: Unknown JAXB exception;
+ nested exception is com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
+ de.spring.webservices.auto.Examples es una interfaz y JAXB no puede manejar interfaces.
+ this problem is related to the following location: at de.spring.webservices.auto.Examples
+
+ at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:888)
+
+ ESTE ERROR SE PRODUCE PORQUE cxf-codegen-plugin GENERA Examples QUE ES UN inteface @WebService
+ maven-jaxb2-plugin NO GENERA ESTOS OBJETOS pero maven-jaxb2-plugin NO ES BUENO PARA GENERAR CLASES
+ DESDE WSDLs POR LAS RAZONES EXPLICADAS EN EL pom.xml DEL PROYECTO web-services-spring-jaxb2-client.
+ -->
+ <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
+ <!--
+ contextPath because of Examples autogenerated class, which is an @Weberservice interface.
+
+ cxf-codegen-plugin DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
+ So we MAY NOT scan everything because there is more than one class representing
+ the same XML element. :(
+
+ We scan the objects generated in this package.
+ -->
+ <property name="contextPath" value="de.spring.webservices.client.auto:name.gumartinm.spring_ws.parent"/>
+ </bean>
+
+
+
+ <!-- Required in order to use SOAP 1.2
+ id="messageFactory" is not a random choice, if you use another name it will not work
+ (Spring will end up loading SOAP 1.1)
+ -->
+ <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
+ <property name="soapVersion">
+ <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
+ </property>
+ </bean>
+
+
+ <!--
+ ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
+ del JAXB2 que estoy usando para generar las clases desde el xsd)
+ Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
+ debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
+ funciona, así que supongo el validador tambien :/
+ Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
+ -->
+ <bean id="payloadValidatingInterceptor"
+ class="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor">
+ <property name="schemas">
+ <list>
+ <!--
+ ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
+ OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
+ EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
+
+ IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
+ EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
+ REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
+ CONFIGURATION.
+ -->
+ <value>classpath:parent.xsd</value>
+
+ <value>classpath:examples.xsd</value>
+ </list>
+ </property>
+ <property name="validateRequest" value="true"/>
+ <property name="validateResponse" value="true"/>
+ </bean>
+
+ <!--
+ Los errores de validacion se devuelven así:
+
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+ <env:Header/>
+ <env:Body>
+ <env:Fault>
+ <env:Code>
+ <env:Value>env:Sender</env:Value>
+ </env:Code>
+ <env:Reason>
+ <env:Text xml:lang="en">Validation error</env:Text>
+ </env:Reason>
+ <env:Detail>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
+ </env:Detail>
+ </env:Fault>
+ </env:Body>
+ </env:Envelope>
+
+ El manejador de errores de validación es implementado por AbstractValidatingInterceptor (PayloadValidatingInterceptor)
+ luego si quisiéramos loguear los mensaje de error de validación de algún modo especial tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
+ -->
+
+ <!-- Enables us to log custom Fault remote messages. No loguea mensajes de error de validación :( -->
+ <bean id="customFaultMessageResolver" class="de.spring.webservices.client.CustomFaultMessageResolver">
+ <property name="unmarshaller" ref="marshaller"/>
+ </bean>
+
+ <!--
+ WebServiceTemplate using these strategies by default (see WebServiceTemplate.properties file)
+
+ org.springframework.ws.client.core.FaultMessageResolver=org.springframework.ws.soap.client.core.SoapFaultMessageResolver
+ org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
+ org.springframework.ws.transport.WebServiceMessageSender=org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
+
+ -->
+
+ <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
+ <constructor-arg ref="messageFactory"/>
+ <property name="marshaller" ref="marshaller" />
+ <property name="unmarshaller" ref="marshaller" />
+
+ <!-- For local deployments change to http://localhost:8080/web-services-spring-cxf-server/spring-ws/example -->
+ <property name="defaultUri" value="http://gumartinm.name/spring-ws/example"/>
+
+ <property name="interceptors">
+ <list>
+ <ref bean="payloadValidatingInterceptor" />
+ </list>
+ </property>
+
+ <property name="faultMessageResolver" ref="customFaultMessageResolver" />
+
+ <property name="messageSenders">
+ <list>
+ <bean class="de.spring.webservices.client.transport.http.CustomHttpRequestMessageSender" />
+ </list>
+ </property>
+ </bean>
+
+ <!--
+ Using @Service and @Autowired
+ We could use just XML configuration, or XML confirguration and @Autowired or as I am doing now @Service and @Autowired.
+ <bean id="exampleClientService" class="de.spring.webservices.client.ExampleClientService">
+
+ @Autowired works even using XML configuration as long as you use context:component-scan
+ <property name="webServiceTemplate" ref="webServiceTemplate"/>
+ </bean>
+ -->
+
+</beans>
--- /dev/null
+package de.spring.webservices.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.ws.test.client.RequestMatchers.payload;
+import static org.springframework.ws.test.client.ResponseCreators.withPayload;
+
+import javax.xml.transform.Source;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.ws.client.core.WebServiceTemplate;
+import org.springframework.ws.test.client.MockWebServiceServer;
+import org.springframework.xml.transform.StringSource;
+
+import de.spring.webservices.client.auto.CustomBindingExampleResponse;
+import de.spring.webservices.client.auto.ExampleResponse;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath*:spring-configuration/ws/client-spring-configuration.xml")
+public class ExampleClientServiceIntegrationTest {
+
+ @Autowired
+ ExampleClientService exampleClientService;
+
+ @Autowired
+ private WebServiceTemplate webServiceTemplate;
+
+ private MockWebServiceServer mockServer;
+
+ @Before
+ public void createServer() throws Exception {
+ mockServer = MockWebServiceServer.createServer(webServiceTemplate);
+ }
+
+ @Test
+ public void customerClient() throws Exception {
+ final Source requestPayload = new StringSource(
+ "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>"
+ + "<data>SCARLETT SPRING. IT IS CANON.</data>"
+ + "</ExampleRequest>");
+ final Source responsePayload = new StringSource(
+ "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>"
+ + "<ns2:data>SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>"
+ + "</ns2:ExampleResponse>");
+ mockServer.expect(payload(requestPayload)).andRespond(
+ withPayload(responsePayload));
+
+ final ExampleResponse response = exampleClientService.sendAndReceiveSpring();
+
+ assertEquals(response.getData(), "SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
+ mockServer.verify();
+ }
+
+ @Test
+ public void customerCustomClient() throws Exception {
+ final Source customRequestPayload = new StringSource(
+ "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
+ "<data>CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.</data>" +
+ "</CustomBindingExampleRequest>");
+ final Source customResponsePayload = new StringSource(
+ "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
+ "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>" +
+ "</ns2:CustomBindingExampleResponse>");
+ mockServer.expect(payload(customRequestPayload)).andRespond(
+ withPayload(customResponsePayload));
+
+ final CustomBindingExampleResponse response = exampleClientService.sendAndReceiveSpringCustom();
+
+ assertEquals(response.getData(), "CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
+ mockServer.verify();
+ }
+}
+
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>web-services-spring-cxf</artifactId>
+ <groupId>de.spring.webservices</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>web-services-spring-cxf-globalxsds</artifactId>
+ <name>web-services-spring-cxf-globalxsds</name>
+ <url>http://gumartinm.name</url>
+
+ <properties>
+ <project.xsd.schemas.source.path>src/main/resources</project.xsd.schemas.source.path>
+ <project.xsd.schemas.target.path>${basedir}/target/generated-sources/src/main/java</project.xsd.schemas.target.path>
+ <project.xsd.schemas.package.name>de.spring.webservices.parent.auto</project.xsd.schemas.package.name>
+ <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
+ </properties>
+
+ <dependencies>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*.*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <!-- Generate code from xsd files: We could use maven-jaxb2-plugin in
+ order to generate Java classes from XSD files but this plugin seems more
+ useful so, I keep using it. Besides, it is based on Apache CXF which as well,
+ uses jaxb. See: http://cxf.apache.org/cxf-xjc-plugin.html -->
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-xjc-plugin</artifactId>
+ <version>3.0.3</version>
+ <configuration>
+ <fork>true</fork>
+ <extensions>
+ <extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:3.0.3</extension>
+ </extensions>
+ </configuration>
+ <executions>
+ <execution>
+ <id>generate-sources-from-xsd</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>xsdtojava</goal>
+ </goals>
+ <configuration>
+ <sourceRoot>${project.xsd.schemas.target.path}</sourceRoot>
+ <xsdOptions>
+ <xsdOption>
+ <extension>true</extension>
+ <xsd>${project.xsd.schemas.source.path}/parent.xsd</xsd>
+ <bindingFile>${project.bindings.path}/custombinding.xjb</bindingFile>
+ <packagename>${project.xsd.schemas.package.name}</packagename>
+ </xsdOption>
+ </xsdOptions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.9.1</version>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${project.xsd.schemas.target.path}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="">
+
+</jaxb:bindings>
--- /dev/null
+package de.spring.webservices.binders;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+
+/**
+ * ATTENTION: if you are using this custombinder you will have to create custom payload
+ * validators for Spring (AS FAR AS I KNOW)
+ *
+ */
+public class XSDateTimeCustomBinder extends XmlAdapter<String, Date> {
+
+ @Override
+ public Date unmarshal(final String dateTime) throws Exception {
+ // X pattern just works from Java >= 1.7
+ final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
+
+ return formatter.parse(dateTime);
+ }
+
+ @Override
+ public String marshal(final Date dateTime) throws Exception {
+ // X pattern just works from Java >= 1.7
+ final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
+
+ return formatter.format(dateTime);
+ }
+}
--- /dev/null
+package de.spring.webservices.operations;
+
+/**
+ * <p>
+ * Operations: WSDL v1.1 and v2.0
+ * </p>
+ * See: <a href="http://www.w3.org/TR/wsdl#_porttypes">http://www.w3.org/TR/wsdl#_porttypes</a><br>
+ * See: <a href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ */
+public interface Operations {
+
+ /**
+ * <p>
+ * Request-response operation WSDL v1.1
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/wsdl#_request-response">http://www.w3.org
+ * /TR/wsdl#_request-response</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public static interface RequestResponse<T extends Response, E extends Request> {
+ T requestResponse(E request);
+ }
+
+ /**
+ * <p>
+ * One-way operation WSDL v1.1
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/wsdl#_one-way">http://www.w3.org/TR/wsdl
+ * #_one-way</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface OneWay<E extends Request> {
+ void oneWay(E request);
+ }
+
+ /**
+ * <p>
+ * Notification operation WSDL v1.1
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/wsdl#_notification">http://www.w3.org/TR
+ * /wsdl#_notification</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface Notification<T extends Response> {
+ T notification();
+ }
+
+ /**
+ * <p>
+ * In-Only message exchange pattern WSDL 2.0
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface InOnly<E extends Request> {
+ void inOnly(E request);
+ }
+
+ /**
+ * <p>
+ * Robust In-Only message exchange pattern WSDL 2.0
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface RobustInOnly<E extends Request> {
+ void robustInOnly(E request);
+ }
+
+ /**
+ * <p>
+ * In-Out message exchange pattern WSDL 2.0
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface InOut<T extends Response, E extends Request> {
+ T inOut(E request);
+ }
+}
\ No newline at end of file
--- /dev/null
+package de.spring.webservices.operations;
+
+public interface Request {
+
+}
--- /dev/null
+package de.spring.webservices.operations;
+
+public interface Response {
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsd:schema xmlns="http://gumartinm.name/spring-ws/parent"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ targetNamespace="http://gumartinm.name/spring-ws/parent">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <xsd:simpleType name="parentEnumType">
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="FIRST"/>
+ <xsd:enumeration value="SECOND"/>
+ <xsd:enumeration value="THIRD"/>
+ <xsd:enumeration value="FOURTH"/>
+ <xsd:enumeration value="FIVETH"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="limitedString">
+ <xsd:restriction base="xsd:string">
+ <xsd:maxLength value="30" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="element">
+ <xsd:sequence>
+ <xsd:element name="message" type="xsd:string"/>
+ <xsd:element name="messageArgs" type="xsd:string" minOccurs="0" maxOccurs="100"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="GeneralFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="technicalError" type="xsd:string" />
+ <xsd:element name="elements" type="element" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>web-services-spring-cxf</artifactId>
+ <groupId>de.spring.webservices</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>web-services-spring-cxf-server</artifactId>
+ <packaging>war</packaging>
+ <name>web-services-spring-cxf-server</name>
+ <url>http://gumartinm.name</url>
+
+ <properties>
+ <jetty.version>9.3.0.RC0</jetty.version>
+ <project.xsd.schemas.source.path>src/main/resources</project.xsd.schemas.source.path>
+ <project.xsd.schemas.target.path>${basedir}/target/generated-sources/src/main/java</project.xsd.schemas.target.path>
+ <project.xsd.schemas.package.name>de.spring.webservices.server.auto</project.xsd.schemas.package.name>
+ <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
+ <!-- Requires absolute path (because of that I am using ${basedir} -->
+ <project.catalogs.path>${basedir}/src/main/build-resources/catalogs</project.catalogs.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-xml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ </dependency>
+
+
+ <!-- Global types -->
+ <dependency>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-cxf-globalxsds</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <!-- Required by spring-ws-core -->
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ </dependency>
+
+ <!-- Required by jaxb2-basics as specified: http://confluence.highsource.org/display/J2B/Using+JAXB2+Basics+Plugins+with+CXF -->
+ <dependency>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-runtime</artifactId>
+ <version>0.9.4</version>
+ </dependency>
+
+ <!-- Required by my CustomHeaderInterceptor -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>4.0.0-b01</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/webapp</directory>
+ <excludes>
+ <exclude>**/*.*</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>${basedir}/src/main/resources/</directory>
+ <includes>
+ <include>**/*.*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <!-- Generate code from xsd files: We could use maven-jaxb2-plugin in
+ order to generate Java classes from XSD files but this plugin seems more
+ useful so, I keep using it. Besides, it is based on Apache CXF which as well,
+ uses jaxb. See: http://cxf.apache.org/cxf-xjc-plugin.html -->
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-xjc-plugin</artifactId>
+ <configuration>
+ <fork>true</fork>
+ <extensions>
+ <extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:3.0.3</extension>
+ </extensions>
+ </configuration>
+ <executions>
+ <execution>
+ <id>generate-sources-from-xsd</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>xsdtojava</goal>
+ </goals>
+ <configuration>
+ <sourceRoot>${project.xsd.schemas.target.path}</sourceRoot>
+ <xsdOptions>
+ <xsdOption>
+ <extension>true</extension>
+ <xsd>${project.xsd.schemas.source.path}/examples.xsd</xsd>
+ <bindingFile>${project.bindings.path}/custombinding.xjb</bindingFile>
+ <catalog>${project.catalogs.path}/catalog.cat</catalog>
+ <packagename>${project.xsd.schemas.package.name}</packagename>
+ <extensionArgs>
+ <extraarg>-Xinheritance</extraarg>
+ <extraarg>-Xannotate</extraarg>
+ </extensionArgs>
+ </xsdOption>
+ </xsdOptions>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <!-- We make this plugin work with this jaxb2 version. This particular
+ version let us generate inherited classes using the -Xinheritance argument.
+ DO NOT FORGET: We can use <inheritance:implements> in xsd files or by means
+ of custom bindings (see custombinding.xjb) This useful when you may not modify
+ xsd files because they are generated by other person or machine. -->
+ <dependency>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics</artifactId>
+ <version>0.9.4</version>
+ </dependency>
+
+ <!-- We make this plugin work with this jaxb2 version. This particular
+ version let us generate annotated classes using the -Xannotate argument.
+ DO NOT FORGET: We can use <annox:annotate> in xsd files or by means of custom
+ bindings like I did with <inheritance:implements> (see custombinding.xjb)
+ This useful when you may not modify xsd files because they are generated
+ by other person or machine. -->
+ <dependency>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-annotate</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.9.1</version>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${project.xsd.schemas.target.path}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <webResources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/webapp</directory>
+ <includes>
+ <include>WEB-INF/web.xml</include>
+ </includes>
+ </resource>
+ </webResources>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <version>${jetty.version}</version>
+ <configuration>
+ <jettyXml>${basedir}/src/main/jetty/jetty-http.xml</jettyXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="xjc inheritance annox">
+
+ <!--
+ Se procesa con Xpath si quieres meter expresiones regulares y cosas así en teoría dependes de Xpath
+ por ejemplo esto: @name=match[.] se supone que debería funcionar pero me dice que no puede
+ cambiar mas de un nodo a la vez. Puede que sea un bug de xjc que se carga las opciones de Xpath :/
+ <jaxb:bindings schemaLocation="examples.xsd">
+ <jaxb:bindings node="//xsd:element[@name='ExampleRequest']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </jaxb:bindings>
+ <jaxb:bindings node="//xsd:element[@name='ExampleResponse']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </jaxb:bindings>
+ </jaxb:bindings>
+ -->
+
+ <jaxb:bindings schemaLocation="../../resources/examples.xsd">
+ <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleRequest']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ </jaxb:bindings>
+ </jaxb:bindings>
+
+
+ <jaxb:bindings schemaLocation="../../resources/examples.xsd">
+ <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleResponse']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ </jaxb:bindings>
+ </jaxb:bindings>
+
+ <!-- The same applies to annotate. If you do not want or you may not modify your xsd files you can
+ modify instead this file with your custom binding :) -->
+
+ <!-- Custom xsd:dateTime adapter
+ See: https://jaxb.java.net/2.2.4/docs/vendorCustomizations.html#javaType
+ -->
+ <jaxb:globalBindings>
+ <xjc:javaType adapter="de.spring.webservices.binders.XSDateTimeCustomBinder"
+ name="java.util.Date" xmlType="xsd:dateTime" />
+ </jaxb:globalBindings>
+
+</jaxb:bindings>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system|public" >
+
+ <!--
+ An XML catalog will allow us to specify real locations for our imported XML schemas.
+ The XJC tool supports several different XML Catalog formats: TR9401, XCatalog, OASIS XML Catalog.
+ I am using OASIS XML Catalog Format
+
+ OASIS XML Catalog Format: https://www.oasis-open.org/committees/entity/specs/cs-entity-xml-catalogs-1.0.html
+ TR9401: https://www.oasis-open.org/specs/a401.htm
+
+
+ See: http://labs.bsb.com/2011/01/usage-of-an-xml-catalog-in-the-xmlbeans-cxf-integration/
+ http://cxf.apache.org/cxf-xjc-plugin.html
+ https://jaxb.java.net/2.2.4/docs/catalog.html
+ -->
+
+
+ <!-- I JUST NEED THIS CONFIGURATION, ANYHOW I AM WRITING ALL OF THEM -->
+ <rewriteSystem systemIdStartString="http://gumartinm.name/spring-ws/parent"
+ rewritePrefix="classpath:parent.xsd"/>
+
+
+ <!-- THE FOLLOWING ONES ARE NOT REQUIRED EVEN IF I AM WRITING THEM -->
+ <public
+ publicId="http://gumartinm.name/spring-ws/parent"
+ uri="classpath:parent.xsd"/>
+
+
+ <system
+ systemId="http://gumartinm.name/spring-ws/parent/parent.xsd"
+ uri="classpath:parent.xsd"/>
+
+
+ <rewriteURI uriStartString="http://gumartinm.name/spring-ws/parent"
+ rewritePrefix="classpath:parent.xsd"/>
+
+</catalog>
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.server.EndpointInterceptor;
+import org.springframework.ws.transport.context.TransportContext;
+import org.springframework.ws.transport.context.TransportContextHolder;
+import org.springframework.ws.transport.http.HttpServletConnection;
+
+public class CustomHeaderInterceptor implements EndpointInterceptor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CustomHeaderInterceptor.class);
+ private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
+
+ @Override
+ public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
+ TransportContext transport = TransportContextHolder.getTransportContext();
+
+ if (transport != null) {
+ HttpServletConnection connection = (HttpServletConnection) transport.getConnection();
+ HttpServletRequest headers = connection.getHttpServletRequest();
+ String headerValue = headers.getHeader(MY_CUSTOM_HEADER);
+
+ if (!StringUtils.isEmpty(headerValue)) {
+ LOGGER.info("Custom header value: " + headerValue);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
+ return true;
+ }
+
+ @Override
+ public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
+
+ }
+
+}
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import org.jdom2.Element;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.server.endpoint.annotation.Endpoint;
+import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
+import org.springframework.ws.server.endpoint.annotation.RequestPayload;
+import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.operations.Operations.RequestResponse;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+import de.spring.webservices.services.ExampleService;
+
+
+@Endpoint
+public class ExampleEndPoint {
+ private static final String NAMESPACE_URI = "http://gumartinm.name/spring-ws/example";
+
+ private final Operations.RequestResponse
+ <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
+
+ private final ExampleService exampleService;
+
+ @Autowired
+ public ExampleEndPoint(
+ RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService,
+ ExampleService exampleService) {
+ this.customBindingExampleService = customBindingExampleService;
+ this.exampleService = exampleService;
+ }
+
+ @PayloadRoot(localPart = "ExampleRequest", namespace = NAMESPACE_URI)
+ @ResponsePayload
+ public ExampleResponse exampleResponse(
+ @RequestPayload final ExampleRequest request,
+ @RequestPayload final Element element,
+ final MessageContext messageContext) {
+
+ return this.exampleService.doResponse(request);
+ }
+
+ @PayloadRoot(localPart = "CustomBindingExampleRequest", namespace = NAMESPACE_URI)
+ @ResponsePayload
+ public CustomBindingExampleResponse cuntomBindingExampleResponse(
+ @RequestPayload final CustomBindingExampleRequest requestObject,
+ @RequestPayload final Element element,
+ final MessageContext messageContext) {
+
+ return this.customBindingExampleService.requestResponse(requestObject);
+ }
+}
+
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.transform.Result;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.oxm.Marshaller;
+import org.springframework.util.CollectionUtils;
+import org.springframework.ws.soap.SoapFault;
+import org.springframework.ws.soap.SoapFaultDetail;
+import org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver;
+import org.springframework.ws.soap.server.endpoint.SoapFaultDefinition;
+import org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor;
+
+import de.spring.webservices.exceptions.CustomBusinessException;
+import de.spring.webservices.server.auto.Element;
+import de.spring.webservices.server.auto.GeneralFault;
+
+public class MyCustomMappingExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomMappingExceptionResolver.class);
+
+ private Marshaller marshaller;
+
+ private Map<String, String> exceptionMappings = new LinkedHashMap<>();
+
+ /**
+ * Set the mappings between exception class names and SOAP Faults. The exception class name can be a substring, with
+ * no wildcard support at present.
+ *
+ * <p>The values of the given properties object should use the format described in
+ * {@code SoapFaultDefinitionEditor}.
+ *
+ * <p>Follows the same matching algorithm as {@code SimpleMappingExceptionResolver}.
+ *
+ * @param mappings exception patterns (can also be fully qualified class names) as keys, fault definition texts as
+ * values
+ * @see SoapFaultDefinitionEditor
+ */
+ public void setExceptionMappings(Properties mappings) {
+ for (Map.Entry<Object, Object> entry : mappings.entrySet()) {
+ if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
+ exceptionMappings.put((String)entry.getKey(), (String)entry.getValue());
+ }
+ }
+ }
+
+ @Override
+ protected SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) {
+ if (!CollectionUtils.isEmpty(exceptionMappings)) {
+ String definitionText = null;
+ int deepest = Integer.MAX_VALUE;
+ for (String exceptionMapping : exceptionMappings.keySet()) {
+ int depth = getDepth(exceptionMapping, ex);
+ if (depth >= 0 && depth < deepest) {
+ deepest = depth;
+ definitionText = exceptionMappings.get(exceptionMapping);
+ }
+ }
+ if (definitionText != null) {
+ SoapFaultDefinitionEditor editor = new SoapFaultDefinitionEditor();
+ editor.setAsText(definitionText);
+ return (SoapFaultDefinition) editor.getValue();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the depth to the superclass matching. {@code 0} means ex matches exactly. Returns {@code -1} if
+ * there's no match. Otherwise, returns depth. Lowest depth wins.
+ *
+ * <p>Follows the same algorithm as RollbackRuleAttribute, and SimpleMappingExceptionResolver
+ */
+ protected int getDepth(String exceptionMapping, Exception ex) {
+ return getDepth(exceptionMapping, ex.getClass(), 0);
+ }
+
+ @SuppressWarnings("unchecked")
+ private int getDepth(String exceptionMapping, Class<? extends Exception> exceptionClass, int depth) {
+ if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
+ return depth;
+ }
+ if (exceptionClass.equals(Throwable.class)) {
+ return -1;
+ }
+ return getDepth(exceptionMapping, (Class<? extends Exception>) exceptionClass.getSuperclass(), depth + 1);
+ }
+
+ protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
+ GeneralFault customFault = new GeneralFault();
+ customFault.setTechnicalError(getStackTrace(ex));
+
+ Element element = buildElement(ex);
+ List<Element> elements = customFault.getElements();
+ elements.add(element);
+
+ SoapFaultDetail detail = fault.addFaultDetail();
+ Result result = detail.getResult();
+ try {
+ marshaller.marshal(customFault, result);
+ } catch (Exception marshallEx) {
+ LOGGER.error("MyCustomMappingExceptionResolver: marshaller error", marshallEx);
+ }
+ }
+
+ public void setMarshaller(Marshaller marshaller) {
+ this.marshaller = marshaller;
+ }
+
+ private Element buildElement(Exception ex) {
+ Element element = new Element();
+ element.setMessage(ex.getMessage());
+
+ if (ex instanceof CustomBusinessException) {
+ CustomBusinessException customEx = (CustomBusinessException) ex;
+ List<String> messageArgs = element.getMessageArgs();
+ List<String> argumentsEx = customEx.getArguments();
+
+ for (String argumentEx: argumentsEx) {
+ messageArgs.add(argumentEx);
+ }
+ }
+
+ return element;
+ }
+
+ private String getStackTrace(Throwable throwable) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw, true);
+ throwable.printStackTrace(pw);
+ return sw.getBuffer().toString();
+ }
+}
--- /dev/null
+package de.spring.webservices.exceptions;
+
+/**
+ * This exception will be caught by org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
+ *
+ */
+public class BusinessException extends RuntimeException {
+
+ private static final long serialVersionUID = -4042139454770293299L;
+
+ public BusinessException() {
+ super();
+ }
+
+ public BusinessException(String message) {
+ super(message);
+ }
+
+ public BusinessException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
--- /dev/null
+package de.spring.webservices.exceptions;
+
+import java.util.List;
+
+/**
+ * This exception will be caught by de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
+ *
+ */
+public class CustomBusinessException extends RuntimeException {
+ private final List<String> arguments;
+
+ public CustomBusinessException(List<String> arguments) {
+ super();
+ this.arguments = arguments;
+ }
+
+ public CustomBusinessException(String message, List<String> arguments) {
+ super(message);
+
+ this.arguments = arguments;
+ }
+
+ public CustomBusinessException(String message, Throwable cause, List<String> arguments) {
+ super(message, cause);
+
+ this.arguments = arguments;
+ }
+
+ public List<String> getArguments() {
+ return arguments;
+ }
+}
--- /dev/null
+package de.spring.webservices.services;
+
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+
+
+public interface ExampleService {
+
+ public ExampleResponse doResponse(ExampleRequest request);
+
+}
--- /dev/null
+package de.spring.webservices.services.impl;
+
+//import java.util.ArrayList;
+//import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.server.auto.ParentEnumType;
+//import de.spring.webservices.exceptions.BusinessException;
+//import de.spring.webservices.exceptions.CustomBusinessException;
+
+
+@Service("customBindingExampleService")
+public class CustomBindingExampleServiceImpl implements
+ Operations.RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> {
+
+
+ @Override
+ public CustomBindingExampleResponse requestResponse(final CustomBindingExampleRequest request) {
+
+
+ // Example about how works org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
+ // see soap-ws.xml Spring configuration file.
+// throw new BusinessException("This feature has not been implemented yet.");
+
+ // Example about how works de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
+ // see soap-ws.xml Spring configuration file.
+// List<String> arguments = new ArrayList<>();
+// arguments.add("ARGUMENT 1");
+// arguments.add("ARGUMENT 2");
+// throw new CustomBusinessException("This feature has not been implemented yet.", arguments);
+
+ CustomBindingExampleResponse response = new CustomBindingExampleResponse();
+
+ response.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
+ response.setParentEnum(ParentEnumType.FIRST);
+
+ return response;
+ }
+
+}
--- /dev/null
+package de.spring.webservices.services.impl;
+
+import org.springframework.stereotype.Service;
+
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+import de.spring.webservices.services.ExampleService;
+
+
+@Service("exampleService")
+public class ExampleServiceImpl implements ExampleService {
+
+ @Override
+ public ExampleResponse doResponse(final ExampleRequest request) {
+
+ ExampleResponse response = new ExampleResponse();
+
+ response.setData("SNAKE EYES AND " + request.getData());
+
+ return response;
+ }
+
+}
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<!-- ============================================================= -->
+<!-- Configure the Jetty Server instance with an ID "Server" -->
+<!-- by adding a HTTP connector. -->
+<!-- This configuration must be used in conjunction with jetty.xml -->
+<!-- ============================================================= -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
+ <Set name="secureScheme">https</Set>
+ <Set name="securePort">
+ <Property name="jetty.secure.port" default="8443" />
+ </Set>
+ <Set name="outputBufferSize">32768</Set>
+ <Set name="requestHeaderSize">8192</Set>
+ <Set name="responseHeaderSize">8192</Set>
+ <Set name="sendServerVersion">true</Set>
+ <Set name="sendDateHeader">false</Set>
+ <Set name="headerCacheSize">512</Set>
+
+ <!-- Uncomment to enable handling of X-Forwarded- style headers
+ <Call name="addCustomizer">
+ <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
+ </Call>
+ -->
+ </New>
+
+
+ <!-- =========================================================== -->
+ <!-- Add a HTTP Connector. -->
+ <!-- Configure an o.e.j.server.ServerConnector with a single -->
+ <!-- HttpConnectionFactory instance using the common httpConfig -->
+ <!-- instance defined in jetty.xml -->
+ <!-- -->
+ <!-- Consult the javadoc of o.e.j.server.ServerConnector and -->
+ <!-- o.e.j.server.HttpConnectionFactory for all configuration -->
+ <!-- that may be set here. -->
+ <!-- =========================================================== -->
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="Server" />
+ </Arg>
+ <Arg name="factories">
+ <Array type="org.eclipse.jetty.server.ConnectionFactory">
+ <Item>
+ <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+ <Arg name="config">
+ <Ref refid="httpConfig" />
+ </Arg>
+ </New>
+ </Item>
+ </Array>
+ </Arg>
+ <Set name="host">
+ <Property name="jetty.host" default="127.0.0.1"/>
+ </Set>
+ <Set name="port">
+ <Property name="jetty.port" default="8080" />
+ </Set>
+ <Set name="idleTimeout">
+ <Property name="http.timeout" default="30000"/>
+ </Set>
+ </New>
+ </Arg>
+ </Call>
+
+</Configure>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:parent="http://gumartinm.name/spring-ws/parent"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="inheritance annox"
+ targetNamespace="http://gumartinm.name/spring-ws/example"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <!--
+ We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
+ when creating Java objects from examples.xsd.
+ -->
+ <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
+
+
+ <!-- Spring requires the following:
+ 1. XSD elements being used as request must end with Request name.
+ 2. XSD elements being used as response must end with Response name.
+
+ IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
+
+ ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
+ the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
+ The same for CustomBindingExample.
+ -->
+ <!-- Using inheritance and annox plugin -->
+ <xsd:element name="ExampleRequest">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="parent:limitedString" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleResponse">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- Using custombinding.xjb instead of inheritance plugin.
+ Useful when you can not modify your xsd files because they are provided
+ by another person or company
+ -->
+ <xsd:element name="CustomBindingExampleRequest">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleResponse">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Example of creating array list by means of XSD -->
+ <xsd:complexType name="car">
+ <xsd:sequence>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="truck">
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ <xsd:element name="vehicles">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="cars" type="car" maxOccurs="unbounded" />
+ <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ status: The level of internal Log4j events that should be logged to the console.
+ Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
+
+ monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
+
+
+ see https://logging.apache.org/log4j/2.x/manual/configuration.html
+ -->
+<Configuration status="error" strict="true" monitorInterval="30"
+ name="XMLConfigTest" packages="org.apache.logging.log4j.test">
+
+ <!--
+ ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
+
+ ERROR by default.
+ -->
+
+ <Appenders>
+ <Appender type="Console" name="STDOUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
+ </Appender>
+ </Appenders>
+ <Loggers>
+
+
+ <!--
+ Specific log when request message from remote client or response message created by this server contains validation errors.
+
+ see soap-ws.xml Spring configuration file.
+
+ This configuration enables us to log validation errors of data sent from remote client or data created by this server.
+
+ Los errores de validación se loguean aquí (tanto de validación de datos de respuesta de servidor como de datos recibidos desde cliente)
+ -->
+ <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!-- Specific log level for SOAP SoapEnvelopeLoggingInterceptor.
+
+ see soap-ws.xml Spring configuration file.
+
+ This configuration enables us to log the SOAP XML Request (received from remote client), Response (sent by this server) and Fault (sent by this server).
+
+ Aquí no se loguean errores de validación.
+ -->
+ <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+
+ <!--
+ Specific log level for Spring WS.
+ -->
+ <Logger name="org.springframework.ws" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ General logging Spring.
+ -->
+ <Logger name="org.springframework" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ Anything else will be using TRACE logging level.
+ -->
+ <Root level="INFO">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+</beans>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:sws="http://www.springframework.org/schema/web-services"
+ xmlns:util="http://www.springframework.org/schema/util"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/web-services
+ http://www.springframework.org/schema/web-services/web-services.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+ <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Endpoint, etc, etc) -->
+ <context:component-scan base-package="de.spring.webservices"/>
+
+ <!--
+ Three ways of using a marshallers/unmarshallers.
+
+ 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
+ Esto equivale a esta configuracion en XML
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
+ El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
+
+ 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
+ se hace de este modo:
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.server.auto"/>
+ Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
+ de especificar un context-path en concreto.
+
+ 3. Especificando la implementación concreta del marshaller.
+ Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
+ cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
+ De todos modos, probablemente habría que usar un package distinto para lo que hay
+ en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
+ -->
+ <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
+ <!--
+ cxf-xjc-plugin generates again the objects in web-services-spring-cxf-globalxsds :(
+ So we MAY NOT scan everything because there is more than one class representing
+ the same XML element. :(
+ -->
+ <property name="packagesToScan" value="de.spring.webservices.server.auto"/>
+ </bean>
+ <!-- Searches for @PayloadRoot -->
+ <sws:annotation-driven marshaller="marshaller" unmarshaller="marshaller" />
+
+
+ <!--
+ CONSECUENCIAS DE USAR sws:annotation-driven VER: org.springframework.ws.config.AnnotationDrivenBeanDefinitionParser
+ Cuanto más bajo es el valor de order mayor es la prioridad.
+
+ 1. Manejadores de excepción, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
+ a) SoapFaultAnnotationExceptionResolver será el primer manejador de excepciones que se intente usar por defecto. order = 0
+ b) SimpleSoapExceptionResolver será el último manejador de excepciones que se intente usar por defecto. order = Ordered.LOWEST_PRECEDENCE
+ Se usará si la excepción generada no pudo ser manejada por SoapFaultAnnotationExceptionResolver (porque la excepción no fue anotada con
+ @SoapFault. Este manejador se traga cualquier excepción.
+
+ 2. Endpoints a buscar, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
+ a) PayloadRootAnnotationMethodEndpointMapping será el primer tipo de endpoints que se buscará y que se intentará usar. order = 0
+ Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a b).
+ b) SoapActionAnnotationMethodEndpointMapping será el segundo tipo de endpoints que se intentará usar. order = 1
+ Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a c).
+ c) AnnotationActionEndpointMapping será el último tipo de endpoints que se buscará. order = 2
+ Si el XML SOAP que llega no machea tampoco métodos anotado con este EndPoint se
+ lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
+
+
+ EN LUGAR DE USAR LA ANOTACIÓN PODRÍAMOS HABER DECLARADO EXPLÍCITAMENTE CADA BEAN TAL QUE ASÍ:
+
+ <bean id="soapFaultMappingExceptionResolver"
+ class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
+ <property name="order" value="0" />
+ </bean>
+
+ <bean id="payloadRootAnnotationMethodEndpointMapping"
+ class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
+ <property name="order" value="0" />
+ </bean>
+
+ CON LA ANOTACIÓN ME AHORRO DECLARAR bean POR bean PERO LO MALO ES QUE INSTANCIO MANEJADORES QUE LUEGO NO USO :(
+
+
+ ATENCION:
+ Solo se usa una instancia de org.springframework.oxm.jaxb.Jaxb2Marshaller que será usada por todas las llamadas (todos los hilos).
+ Es hilo seguro, por debajo usa javax.xml.bind.JAXBContext que es hilo seguro.
+ JAXBContext debe ser siempre un singleton porque la primera vez tarda mucho en inicializarse. Cada vez que se haga marshalling y unmarshalling
+ se deben crear objetos ligeros y no seguros mediante los métodos JAXBContext.createMarshaller() y JAXBContext.createUnmarshaller()
+ (esto es lo que hace Jaxb2Marshaller por nosotros) Los objetos ligeros creados son javax.xml.bind.Marshaller y javax.xml.bind.Unmarshaller
+ que no son hilo seguro y por tanto serán creados por cada petición (todo esto lo está haciendo Spring ya, así que genial)
+ -->
+
+ <!--
+ Spring makes the WSDL file for us from the XSD file.
+ Launch the Jetty server and download WSDL file from this URL:
+ http://localhost:8080/web-services-spring-cxf-server/spring-ws/example/example.wsdl
+ -->
+ <sws:dynamic-wsdl id="example" portTypeName="Examples"
+ createSoap12Binding="true" createSoap11Binding="false"
+ locationUri="/spring-ws/example"
+ targetNamespace="http://gumartinm.name/spring-ws/exampleService">
+ <sws:xsd location="classpath:examples.xsd"/>
+ </sws:dynamic-wsdl>
+
+
+ <!-- Required in order to use SOAP 1.2
+ id="messageFactory" is not a random choice, if you use another name it will not work
+ (Spring will end up loading SOAP 1.1)
+ -->
+ <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
+ <property name="soapVersion">
+ <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
+ </property>
+ </bean>
+
+ <!-- The interceptors in this set are automatically configured on each registered EndpointMapping
+ What means, every class annotated with @Endpoint will be using these interceptors.
+
+ This configuration enables us to log the SOAP XML Request (received from client), Response (sent by this server) and Fault (sent by this server).
+ -->
+ <sws:interceptors>
+ <bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor">
+ <property name="logRequest" value="true"/>
+ <property name="logResponse" value="true"/>
+ <property name="logFault" value="true"/>
+ </bean>
+
+ <!--
+ ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
+ del JAXB2 que estoy usando para generar las clases desde el xsd)
+ Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
+ debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
+ funciona, así que supongo el validador tambien :/
+ Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
+ -->
+ <bean id="validatingInterceptor"
+ class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
+ <property name="schemas">
+ <list>
+ <!--
+ ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
+ OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
+ EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
+
+ IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
+ EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
+ REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
+ CONFIGURATION.
+ -->
+ <value>classpath:parent.xsd</value>
+
+ <value>classpath:examples.xsd</value>
+ </list>
+ </property>
+ <property name="validateRequest" value="true"/>
+ <property name="validateResponse" value="true"/>
+ </bean>
+
+ <!-- My custom header interceptor -->
+ <bean class="de.spring.webservices.endpoints.CustomHeaderInterceptor" />
+ </sws:interceptors>
+
+
+ <!--
+ PARA METER MAS COSAS A LA RESPUESTA CON ERROR, por ejemplo si quisiéramos enviar en Reason Text la pila de excepción tengo que
+ implementar mi propio manejador de excepción que extienda de AbstractSoapFaultDefinitionExceptionResolver y añada todo aquello
+ que yo necesite.
+
+ A mí me parecen muy pobres las implementaciones que trae Spring así que implementaré el mío propio que devuelva la pila
+ de excepción si la hay.
+ -->
+ <bean id="soapFaultMappingExceptionResolver"
+ class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
+ <!--
+ No quiero usar un valor por defecto porque si no, si mi manejador no machea ninguna excepción
+ devolvera este valor por defecto. Y no se probará con otros manejadores de excepción que tengan un order con menor precedencia.
+
+ Cuando se escribe value="SERVER" Spring está seteando SoapFaultDefinition.SERVER en defaultValue
+ de org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver Esto parece
+ magia pero Spring lo logra usando org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor.setAsText("SERVER")
+
+ <property name="defaultFault" value="SERVER"/>
+ -->
+ <property name="exceptionMappings">
+ <props>
+ <!--
+ <prop key="de.spring.webservices.exceptions.BusinessException">SERVER,something went wrong in server side,en_US</prop>
+
+ Si hago esto en lugar de devolver al cliente el mensaje que va dentro de la excepcion devuelvo siempre:
+
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+ <env:Header/>
+ <env:Body>
+ <env:Fault>
+ <env:Code>
+ <env:Value>env:Receiver</env:Value> Receiver y Server significa lo mismo. Cuando pongo "SERVER" en primer token aquí aparece Receiver.
+ </env:Code>
+ <env:Reason>
+ <env:Text xml:lang="en-US">something went wrong in server side</env:Text> en-US porque puse como Locale en_US en el tercer token.
+ </env:Reason>
+ </env:Fault>
+ </env:Body>
+ </env:Envelope>
+
+ El primer token es el Value. Si es SERVER o RECEIVER se muestra Receiver. Si es CLIENT o SENDER se muestra Sender.
+
+ El segundo token es el mensaje que SIEMPRE se mostrará.
+
+ El tercer token mapea a un Locale en SoapFaultDefinition (por defecto Locale.ENGLISH). El mapeo se hace con
+ org.springframework.util.StringUtils.parseLocaleString("en_US")
+
+
+
+
+
+ Yo prefiero que se devuelva el mensaje que va dentro de la excepción. Para eso SOLO puede haber un token y
+ el Locale siempre será entonces Locale.ENGLISH.
+
+ Uso SERVER porque de.spring.webservices.exceptions.BusinessException es una excepción generada en el lado servidor.
+ -->
+ <prop key="de.spring.webservices.exceptions.BusinessException">SERVER</prop>
+ </props>
+ </property>
+ <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
+ SoapFaultAnnotationExceptionResolver
+ -->
+ <property name="order" value="1" />
+ </bean>
+
+
+
+ <bean id="myCustomMappingExceptionResolver" class="de.spring.webservices.endpoints.MyCustomMappingExceptionResolver">
+ <!--
+ Voy a usar un valor por defecto porque este va a ser el último manejador que haya antes de
+ SimpleSoapExceptionResolver. SimpleSoapExceptionResolver será siempre por el order que he puesto
+ el último manejador de excepciones.
+ Así todas las excepciones que no hayan sido macheadas por los otros manejadores serán siempre
+ cogidas por este y se les asignará un SoapFaultDefinition.SERVER. En este caso SimpleSoapExceptionResolver
+ nunca será usado.
+ -->
+ <property name="defaultFault" value="SERVER"/>
+ <property name="exceptionMappings">
+ <props>
+ <!--
+ Los errores de validacion se devuelven así:
+
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+ <env:Header/>
+ <env:Body>
+ <env:Fault>
+ <env:Code>
+ <env:Value>env:Sender</env:Value>
+ </env:Code>
+ <env:Reason>
+ <env:Text xml:lang="en">Validation error</env:Text>
+ </env:Reason>
+ <env:Detail>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
+ </env:Detail>
+ </env:Fault>
+ </env:Body>
+ </env:Envelope>
+
+ El manejador de errores de validación es implementado por AbstractFaultCreatingValidatingInterceptor (PayloadValidatingInterceptor)
+ luego si quisiéramos devolver un mensaje de error distinto al implementado por AbstractFaultCreatingValidatingInterceptor
+ tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
+ -->
+ <prop key="de.spring.webservices.exceptions.CustomBusinessException">SERVER</prop>
+ </props>
+ </property>
+ <property name="marshaller" ref="marshaller"/>
+ <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
+ SoapFaultAnnotationExceptionResolver y SoapFaultMappingExceptionResolver
+ -->
+ <property name="order" value="2" />
+ </bean>
+
+</beans>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+ <display-name>Spring Web Services: example</display-name>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <context-param>
+ <param-name>spring.profiles.active</param-name>
+ <param-value>${environment.profile}</param-value>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>
+ classpath*:spring-configuration/*.xml
+ </param-value>
+ </context-param>
+
+ <!-- Spring SOAP servlet -->
+ <servlet>
+ <servlet-name>spring-ws</servlet-name>
+ <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ <async-supported>true</async-supported>
+ <init-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath*:spring-configuration/ws/*.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>transformWsdlLocations</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>spring-ws</servlet-name>
+ <url-pattern>/spring-ws/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import static org.springframework.ws.test.server.RequestCreators.withPayload;
+import static org.springframework.ws.test.server.ResponseMatchers.payload;
+
+import javax.xml.transform.Source;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.ws.test.server.MockWebServiceClient;
+import org.springframework.xml.transform.StringSource;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath*:spring-configuration/ws/soap-ws.xml" } )
+public class ExampleEndPointIntegrationTest {
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ private MockWebServiceClient mockClient;
+
+ @Before
+ public void createClient() {
+ mockClient = MockWebServiceClient.createClient(applicationContext);
+ }
+
+ @Test
+ public void exampleEndpoint() throws Exception {
+ final Source requestPayload = new StringSource(
+ "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
+ "<data>SCARLETT</data>" +
+ "</ExampleRequest>");
+ final Source responsePayload = new StringSource(
+ "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
+ "<ns2:data>SNAKE EYES AND SCARLETT</ns2:data>" +
+ "</ns2:ExampleResponse>");
+ mockClient.sendRequest(withPayload(requestPayload)).andExpect(
+ payload(responsePayload));
+
+
+ final Source customRequestPayload = new StringSource(
+ "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
+ "<data>SCARLETT</data>" +
+ "<exampleDate>2015-06-03T10:20:30Z</exampleDate>" +
+ "<parentEnum>FIRST</parentEnum>" +
+ "</CustomBindingExampleRequest>");
+ final Source customResponsePayload = new StringSource(
+ "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
+ "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT</ns2:data>" +
+ "<ns2:parentEnum>FIRST</ns2:parentEnum>" +
+ "</ns2:CustomBindingExampleResponse>");
+ mockClient.sendRequest(withPayload(customRequestPayload)).andExpect(
+ payload(customResponsePayload));
+ }
+}
+
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.services.ExampleService;
+
+
+public class ExampleEndPointTest {
+
+ private ExampleService exampleService;
+
+ private Operations.RequestResponse
+ <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
+
+ private ExampleEndPoint exampleEndPoint;
+
+ @Before
+ public void init() {
+ exampleService = mock(ExampleService.class);
+ customBindingExampleService = mock(Operations.RequestResponse.class);
+ exampleEndPoint = new ExampleEndPoint(customBindingExampleService, exampleService);
+ }
+
+ @Test
+ public void givenExampleRequestThenInvokeExampleService() {
+ ExampleRequest request = new ExampleRequest();
+ request.setData("SCARLETT");
+
+ exampleEndPoint.exampleResponse(request, null, null);
+
+ verify(exampleService).doResponse(request);
+ }
+
+ @Test
+ public void givenCustomBindingExampleRequestThenInvokeCustomBindingExampleService() {
+ CustomBindingExampleRequest request = new CustomBindingExampleRequest();
+ request.setData("SCARLETT");
+
+ exampleEndPoint.cuntomBindingExampleResponse(request, null, null);
+
+ verify(customBindingExampleService).requestResponse(request);
+ }
+
+}
--- /dev/null
+package de.spring.webservices.services;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.services.impl.CustomBindingExampleServiceImpl;
+
+
+public class CustomBindingExampleServiceTest {
+
+ private Operations.RequestResponse
+ <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
+
+ @Before
+ public void init() {
+ customBindingExampleService = new CustomBindingExampleServiceImpl();
+ }
+
+ @Test
+ public void givenCustomBindingExampleRequestThenReturnCustomBindingExampleResponse() {
+ CustomBindingExampleRequest request = new CustomBindingExampleRequest();
+ request.setData("SCARLETT");
+ CustomBindingExampleResponse expected = new CustomBindingExampleResponse();
+ expected.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
+
+ CustomBindingExampleResponse actual = customBindingExampleService.requestResponse(request);
+
+ Assert.assertEquals(expected.getData(), actual.getData());
+ }
+}
--- /dev/null
+package de.spring.webservices.services;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+import de.spring.webservices.services.impl.ExampleServiceImpl;
+
+public class ExampleServiceTest {
+
+ private ExampleService exampleService;
+
+ @Before
+ public void init() {
+ exampleService = new ExampleServiceImpl();
+ }
+
+ @Test
+ public void givenExampleRequestThenReturnExampleResponse() {
+ ExampleRequest request = new ExampleRequest();
+ request.setData("SCARLETT");
+ ExampleResponse expected = new ExampleResponse();
+ expected.setData("SNAKE EYES AND " + request.getData());
+
+ ExampleResponse actual = exampleService.doResponse(request);
+
+ Assert.assertEquals(expected.getData(), actual.getData());
+ }
+
+}
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-cxf</artifactId>
+ <packaging>pom</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <name>web-services-spring-cxf</name>
+ <url>http://gumartinm.name</url>
+ <description>Web Services Spring Framework</description>
+ <organization>
+ <name>Gustavo Martin Morcuende</name>
+ <url>http://www.gumartinm.name</url>
+ </organization>
+ <scm>
+ <developerConnection>scm:git:http://git.gumartinm.name/SpringWebServicesForFun</developerConnection>
+ <url>http://git.gumartinm.name/SpringWebServicesForFun</url>
+ </scm>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <!-- Be aware: spring-ws latest version does not follow spring-context
+ latest version -->
+ <spring.version>4.0.9.RELEASE</spring.version>
+ <spring.ws.version>2.2.1.RELEASE</spring.ws.version>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <properties>
+ <environment.profile>release</environment.profile>
+ </properties>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <!--
+ 1/3 Required dependency for log4j 2 with slf4j: binding between log4j 2 and slf4j
+ -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <!--
+ 2/3 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin (it is the log4j 2 implementation)
+ -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <!--
+ 3/3 Required dependency for getting rid of commons logging.
+ This is the BRIDGE (no binding) between Jakarta Commons Logging (used by Spring) and whatever
+ I am using for logging (in this case I am using log4j 2)
+ See: http://www.slf4j.org/legacy.html
+
+ We need exclusions in every dependency using Jakarta Commons Logging (see Spring dependencies below)
+ -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-core</artifactId>
+ <version>${spring.ws.version}</version>
+ <!--
+ Required dependency for getting rid of commons logging and use my own logging library
+ (in my case I decided to use log4j 2 under slf4j)
+ -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-xml</artifactId>
+ <version>${spring.ws.version}</version>
+ <!--
+ Required dependency for getting rid of commons logging and use my own logging library
+ (in my case I decided to use log4j 2 under slf4j)
+ -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ <version>2.0.2</version>
+ </dependency>
+
+ <!-- Required by spring-ws-core -->
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ <version>1.6.3</version>
+ </dependency>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-test</artifactId>
+ <version>${spring.ws.version}</version>
+ <scope>test</scope>
+ <!--
+ Required dependency for getting rid of commons logging and use my own logging library
+ (in my case I decided to use log4j 2 under slf4j)
+ -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.0.11-beta</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <build>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.18.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.18.1</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.3</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.7</version>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Specification-Title>${project.description}</Specification-Title>
+ <Specification-Version>${project.version}</Specification-Version>
+ <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+ <Implementation-Title>${project.description}</Implementation-Title>
+ <Implementation-Version>${project.version}</Implementation-Version>
+ <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/*IntegrationTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <includes>
+ <include>**/*IntegrationTest.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>web-services-spring-jaxb2</artifactId>
+ <groupId>de.spring.webservices</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>web-services-spring-jaxb2-client</artifactId>
+ <name>web-services-spring-jaxb2-client</name>
+ <url>http://gumartinm.name</url>
+
+ <properties>
+ <project.xsd.schemas.source.path>src/main/build-resources/wsdl</project.xsd.schemas.source.path>
+ <project.xsd.schemas.target.path>${project.build.directory}/generated-sources/src/main/java</project.xsd.schemas.target.path>
+ <project.xsd.schemas.package.name>de.spring.webservices.client.auto</project.xsd.schemas.package.name>
+ <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-xml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ </dependency>
+
+
+ <!-- Global types -->
+ <dependency>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <!-- Required by spring-ws-core -->
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ </dependency>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/resources/</directory>
+ <includes>
+ <include>**/*.*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <version>0.13.1</version>
+ <executions>
+ <execution>
+ <id>generate-sources-from-xsd</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ <configuration>
+ <!-- REQUIRED FOR USING THIS PLUGIN WITH WSDL FILES!!!!! -->
+ <schemaLanguage>WSDL</schemaLanguage>
+ <schemaDirectory>${project.xsd.schemas.source.path}</schemaDirectory>
+ <schemaIncludes>
+ <include>*.wsdl</include>
+ </schemaIncludes>
+
+
+ <!--
+ GRANDES DIFERENCIAS:
+
+ :( CON ESTE PLUGIN A DIFERENCIA DE cxf-codegen-plugin NO SE PUEDEN USAR BINDINGS PARA WSDL
+ LLAMADOS jaxws:bindings :( ESTO PUEDE SER UN PROBLEMA SI SE QUIERE MODIFICAR EL WSDL PROPORCIONADO
+ POR ALGUIEN SIN TENER QUE EDITARLO :( POR EJEMPLO, AQUÍ YA NO PUEDO METER MI XSDateTimeCustomBinder
+ SIN EDITAR EL WSDL :(
+
+ :( CON ESTE PLUGIN AL IGUAL QUE CON cxf-codegen-plugin SE VUELVEN A GENERAR LOS OBJETOS DE parent.xsd
+ QUE SE ENCONTRABAN EN web-services-spring-jaxb2-globalxsds
+
+ :( CON ESTE PLUGIN NO CONSIGO GENERAR LAS CLASES @WebService, @WebServiceClient y @WebEndpoint
+ CON cxf-codegen-plugin SÍ PUEDO :( VER ExamplesService EN web-services-spring-cxf-client
+
+ CONCLUSION: ESTE PLUGIN PARA WSDLs ES PEOR QUE cxf-codegen-plugin
+
+ ¡¡¡¡¡PARA WSDLs MEJOR USAR cxf-codegen-plugin!!!!!
+ -->
+
+ <!-- DOESN'T WORK FOR WSDL FILES!!!!
+ Specifies the binding directory, default to the schemaDirectory
+ <bindingDirectory>${project.bindings.path}</bindingDirectory>
+ -->
+ <!-- Do not scan for *.xjb files in dependencies -->
+ <scanDependenciesForBindings>false</scanDependenciesForBindings>
+
+ <!-- Target directory for the generated code, target/generated-sources/xjc
+ by default. -->
+ <generateDirectory>${project.xsd.schemas.target.path}</generateDirectory>
+
+ <!-- The generated classes will all be placed under this Java package
+ (XJC's -p option), unless otherwise specified in the schemas. If left unspecified,
+ the package will be derived from the schemas only. -->
+ <generatePackage>${project.xsd.schemas.package.name}</generatePackage>
+
+ <!-- I don't think I need the next two options because mvn clean should
+ make the trick, anyhow, I am using them. If true, the generateDirectory will
+ be deleted before the XJC binding compiler recompiles the source files. Default
+ is false. -->
+ <removeOldOutput>true</removeOldOutput>
+ <!-- If true (default), package directories will be cleaned before the
+ XJC binding compiler generates the source files. -->
+ <cleanPackageDirectories>true</cleanPackageDirectories>
+
+ <!-- Encoding for the generated sources, defaults to ${project.build.sourceEncoding}. -->
+ <encoding>${project.build.sourceEncoding}</encoding>
+
+ <!-- Locale used during generation, for instance en, de, fr etc. This
+ will, for instance, influence the language of the generated JavaDoc comments. -->
+ <locale>en</locale>
+
+ <!-- This nice configuration avoids to use build-helper-maven-plugin -->
+ <addCompileSourceRoot>true</addCompileSourceRoot>
+ <addTestCompileSourceRoot>false</addTestCompileSourceRoot>
+
+ <!-- If true (default), XJC will perform strict validation of the input
+ schema. If strict is set to false XJC will be run with -nv, this disables
+ strict validation of schemas.
+
+ The plugin is configured to use catalogs and strict mode at the
+ same time. Using catalogs to resolve schema URIs in strict mode is known
+ to be problematic and may fail. Please refer to the following link for more
+ information: https://github.com/highsource/maven-jaxb2-plugin/wiki/Catalogs-in-Strict-Mode
+ Consider setting <strict>false</strict> in your plugin configuration. -->
+ <strict>false</strict>
+
+ <verbose>true</verbose>
+
+ <extension>true</extension>
+ <args>
+ <arg>-Xinheritance</arg>
+ <arg>-Xannotate</arg>
+ </args>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics</artifactId>
+ <version>0.9.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-annotate</artifactId>
+ <version>1.0.2</version>
+ </plugin>
+ </plugins>
+
+ <!-- Avoids the annoying SCD "x-schema::tns" didn't match any schema component errors. -->
+ <addIfExistsToEpisodeSchemaBindings>true</addIfExistsToEpisodeSchemaBindings>
+
+ <!--
+ :( CON ESTE PLUGIN COMO CON cxf-xjc-plugin SE VUELVEN A GENERAR LOS OBJETOS DE parent.xsd
+ QUE SE ENCONTRABAN EN web-services-spring-jaxb2-globalxsds
+
+ ESTE PLUGIN PARA WSDLs SE COMPORTA COMO cxf-xjc-plugin EN CUANTO A QUE GENERA
+ OTRA VEZ LOS OBJETOS QUE YA ESTÁN EN web-services-spring-jaxb2-globalxsds :(
+ -->
+
+ <!-- You can use the useDependenciesAsEpisodes instead of configuring
+ individual episodes. In this case all the dependencies will be treated as
+ episodes which is very convenient (less configuration). I am going to use
+ the long way (individual episodes) -->
+ <useDependenciesAsEpisodes>false</useDependenciesAsEpisodes>
+ <catalog>src/main/build-resources/catalogs/catalog.cat</catalog>
+ <episodes>
+ <episode>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
+ </episode>
+ </episodes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+
+
+REWRITE_SYSTEM "http://gumartinm.name/spring-ws/parent/parent.xsd" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
+
+--
+ This configuration is better (it relies on namespace instead of schemaLocation) but it doesn't work
+ because of this bug: https://java.net/jira/browse/JAXB-942
+
+ PUBLIC "xmlns:parent" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
+
+--
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://gumartinm.name/spring-ws/example" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://gumartinm.name/spring-ws/exampleService" targetNamespace="http://gumartinm.name/spring-ws/exampleService">
+ <wsdl:types>
+ <xsd:schema xmlns="http://gumartinm.name/spring-ws/example" xmlns:annox="http://annox.dev.java.net" xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:parent="http://gumartinm.name/spring-ws/parent" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" jaxb:extensionBindingPrefixes="inheritance annox" jaxb:version="2.1" targetNamespace="http://gumartinm.name/spring-ws/example">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <!--
+ We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
+ when creating Java objects from examples.xsd.
+ -->
+ <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd"/>
+
+
+ <!-- Spring requires the following:
+ 1. XSD elements being used as request must end with Request name.
+ 2. XSD elements being used as response must end with Response name.
+
+ IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
+
+ ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
+ the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
+ The same for CustomBindingExample.
+ -->
+ <!-- Using inheritance and annox plugin -->
+ <xsd:element name="ExampleRequest">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="parent:limitedString"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleResponse">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- Using custombinding.xjb instead of inheritance plugin.
+ Useful when you can not modify your xsd files because they are provided
+ by another person or company
+ -->
+ <xsd:element name="CustomBindingExampleRequest">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleResponse">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Example of creating array list by means of XSD -->
+ <xsd:complexType name="car">
+ <xsd:sequence>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="100" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="truck">
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string"/>
+ <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
+ </xsd:all>
+ </xsd:complexType>
+ <xsd:element name="vehicles">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" name="cars" type="car"/>
+ <xsd:element maxOccurs="100" minOccurs="0" name="trucks" type="truck"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
+ </wsdl:types>
+ <wsdl:message name="ExampleFault">
+ <wsdl:part element="sch:ExampleFault" name="ExampleFault">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="CustomBindingExampleFault">
+ <wsdl:part element="sch:CustomBindingExampleFault" name="CustomBindingExampleFault">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="ExampleRequest">
+ <wsdl:part element="sch:ExampleRequest" name="ExampleRequest">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="ExampleResponse">
+ <wsdl:part element="sch:ExampleResponse" name="ExampleResponse">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="CustomBindingExampleResponse">
+ <wsdl:part element="sch:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:message name="CustomBindingExampleRequest">
+ <wsdl:part element="sch:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
+ </wsdl:part>
+ </wsdl:message>
+ <wsdl:portType name="Examples">
+ <wsdl:operation name="Example">
+ <wsdl:input message="tns:ExampleRequest" name="ExampleRequest">
+ </wsdl:input>
+ <wsdl:output message="tns:ExampleResponse" name="ExampleResponse">
+ </wsdl:output>
+ <wsdl:fault message="tns:ExampleFault" name="ExampleFault">
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="CustomBindingExample">
+ <wsdl:input message="tns:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
+ </wsdl:input>
+ <wsdl:output message="tns:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
+ </wsdl:output>
+ <wsdl:fault message="tns:CustomBindingExampleFault" name="CustomBindingExampleFault">
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="ExamplesSoap12" type="tns:Examples">
+ <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <wsdl:operation name="Example">
+ <soap12:operation soapAction=""/>
+ <wsdl:input name="ExampleRequest">
+ <soap12:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="ExampleResponse">
+ <soap12:body use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="ExampleFault">
+ <soap12:fault name="ExampleFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ <wsdl:operation name="CustomBindingExample">
+ <soap12:operation soapAction=""/>
+ <wsdl:input name="CustomBindingExampleRequest">
+ <soap12:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output name="CustomBindingExampleResponse">
+ <soap12:body use="literal"/>
+ </wsdl:output>
+ <wsdl:fault name="CustomBindingExampleFault">
+ <soap12:fault name="CustomBindingExampleFault" use="literal"/>
+ </wsdl:fault>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="ExamplesService">
+ <wsdl:port binding="tns:ExamplesSoap12" name="ExamplesSoap12">
+ <soap12:address location="http://localhost:8080/web-services-spring-jaxb2-server/spring-ws/example"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>
\ No newline at end of file
--- /dev/null
+package de.spring.webservices.client;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import javax.xml.transform.Source;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.oxm.XmlMappingException;
+import org.springframework.ws.WebServiceMessage;
+import org.springframework.ws.client.core.FaultMessageResolver;
+import org.springframework.ws.soap.SoapBody;
+import org.springframework.ws.soap.SoapFault;
+import org.springframework.ws.soap.SoapFaultDetail;
+import org.springframework.ws.soap.SoapFaultDetailElement;
+import org.springframework.ws.soap.SoapMessage;
+import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
+
+// maven-jaxb2-plugin for WSDL DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
+// So I guess it is better to use the objects generated in this package
+// than the ones from globalxsds even if they should be the same.
+import de.spring.webservices.client.auto.GeneralFault;
+
+/**
+ * Enables us to log custom Fault remote messages.
+ *
+ */
+public class CustomFaultMessageResolver implements FaultMessageResolver {
+
+private static final Logger LOGGER = LoggerFactory.getLogger(CustomFaultMessageResolver.class);
+
+ private final FaultMessageResolver defaultMessageResolver = new SoapFaultMessageResolver();
+
+ private Unmarshaller unmarshaller;
+
+ @Override
+ public void resolveFault(WebServiceMessage message) throws IOException {
+
+ // Same behavior as default message resolver (SoapFaultMessageResolver) but this implementation also
+ // logs error information.
+ if (LOGGER.isErrorEnabled()) {
+ try {
+ logErrorInformation(message);
+ } catch (Exception ex) {
+ LOGGER.error("CustomFaultMessageResolver exception:", ex);
+ }
+ }
+
+ defaultMessageResolver.resolveFault(message);
+ }
+
+ private void logErrorInformation(WebServiceMessage message) throws XmlMappingException, IOException {
+ SoapMessage soapMessage = (SoapMessage) message;
+ SoapBody body = soapMessage.getSoapBody();
+ SoapFault soapFault = body != null ? body.getFault() : null;
+ SoapFaultDetail detail = soapFault != null ? soapFault.getFaultDetail() : null;
+
+ if (detail != null) {
+ Iterator<SoapFaultDetailElement> iterator = detail.getDetailEntries();
+ while (iterator.hasNext()) {
+ SoapFaultDetailElement bodyElement = iterator.next();
+ Source detailSource = bodyElement.getSource();
+ // TODO: How to check if I am receiving GeneralFault before trying to unmarshal?
+ // Right now there will be exception if unmarshal doesn't return a GeneralFault object.
+ GeneralFault error = (GeneralFault)this.unmarshaller.unmarshal(detailSource);
+ LOGGER.error("TECHNICALERROR:");
+ LOGGER.error(error.getTechnicalError());
+ LOGGER.error("ELEMENTS:");
+ error.getElements().forEach(element -> {
+ LOGGER.error("MESSAGE: " + element.getMessage());
+ LOGGER.error("MESSAGEARGS:");
+ element.getMessageArgs().forEach(messageArg -> LOGGER.error(messageArg));
+ });
+ }
+ }
+ }
+
+ public void setUnmarshaller(Unmarshaller unmarshaller) {
+ this.unmarshaller = unmarshaller;
+ }
+}
--- /dev/null
+package de.spring.webservices.client;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.ws.client.core.WebServiceTemplate;
+
+import de.spring.webservices.client.auto.CustomBindingExampleRequest;
+import de.spring.webservices.client.auto.CustomBindingExampleResponse;
+import de.spring.webservices.client.auto.ExampleRequest;
+import de.spring.webservices.client.auto.ExampleResponse;
+//import de.spring.webservices.client.auto.Examples;
+//import de.spring.webservices.client.auto.ExamplesService;
+//import de.spring.webservices.client.auto.ParentEnumType;
+
+/**
+ * Someone could write code like this one in order to send and receive
+ * information from our Web Services.
+ *
+ */
+@Service("exampleClientService")
+public class ExampleClientService {
+ private final WebServiceTemplate webServiceTemplate;
+
+ @Autowired
+ public ExampleClientService(WebServiceTemplate webServiceTemplate) {
+ this.webServiceTemplate = webServiceTemplate;
+ }
+
+// maven-jaxb2-plugin DOESN'T CREATE @WebService, @WebServiceClient y @WebEndpoint
+// public ExampleResponse sendAndReceiveJava() {
+// final ExampleRequest exampleRequest = new ExampleRequest();
+// exampleRequest.setData("SCARLETT JAVA. IT IS CANON.");
+//
+// final Examples exampleService = new ExamplesService().getExamplesSoap12();
+// final ExampleResponse exampleResponse = exampleService.example(exampleRequest);
+//
+// return exampleResponse;
+// }
+
+ public ExampleResponse sendAndReceiveSpring() {
+ final ExampleRequest exampleRequest = new ExampleRequest();
+ exampleRequest.setData("SCARLETT SPRING. IT IS CANON.");
+
+ final ExampleResponse exampleResponse = (ExampleResponse)
+ this.webServiceTemplate.marshalSendAndReceive(exampleRequest);
+
+ return exampleResponse;
+ }
+
+// maven-jaxb2-plugin DOESN'T CREATE @WebService, @WebServiceClient y @WebEndpoint
+// public CustomBindingExampleResponse sendAndReceiveJavaCustom() {
+// final CustomBindingExampleRequest customBindingxampleRequest =
+// new CustomBindingExampleRequest();
+// customBindingxampleRequest.setData("CUSTOM BINDING JAVA. SCARLETT. IT IS CANON.");
+// customBindingxampleRequest.setParentEnum(ParentEnumType.FIRST);
+//
+// final Examples exampleService = new ExamplesService().getExamplesSoap12();
+// final CustomBindingExampleResponse customBindingExampleResponse =
+// exampleService.customBindingExample(customBindingxampleRequest);
+//
+// return customBindingExampleResponse;
+// }
+
+ public CustomBindingExampleResponse sendAndReceiveSpringCustom() {
+ final CustomBindingExampleRequest customBindingxampleRequest =
+ new CustomBindingExampleRequest();
+ customBindingxampleRequest.setData("CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.");
+
+ final CustomBindingExampleResponse customBindingExampleResponse =
+ (CustomBindingExampleResponse) this.webServiceTemplate
+ .marshalSendAndReceive(customBindingxampleRequest);
+
+ return customBindingExampleResponse;
+ }
+}
--- /dev/null
+package de.spring.webservices.client;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import de.spring.webservices.client.auto.CustomBindingExampleResponse;
+import de.spring.webservices.client.auto.ExampleResponse;
+
+/**
+ * This class is used just like a nice example about how to write and run client
+ * code which will send data to and from the Web Services.
+ *
+ */
+public class MainTest {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MainTest.class);
+
+ public ApplicationContext context;
+
+ /**
+ * @param args
+ */
+ public static void main(final String[] args) {
+ final MainTest test = new MainTest();
+
+ test.context = new ClassPathXmlApplicationContext(
+ "classpath:spring-configuration/ws/client-spring-configuration.xml");
+
+ final ExampleClientService example =
+ (ExampleClientService) test.context.getBean("exampleClientService");
+
+// maven-jaxb2-plugin DOESN'T CREATE @WebService, @WebServiceClient y @WebEndpoint
+// logger.info("ExampleResponse Java:");
+// ExampleResponse response = example.sendAndReceiveJava();
+// logger.info(response.getData());
+
+
+// logger.info("CustomBindingExampleResponse Java:");
+// CustomBindingExampleResponse customBindingResponse = example.sendAndReceiveJavaCustom();
+// logger.info(customBindingResponse.getData());
+
+
+ LOGGER.info("ExampleResponse Spring:");
+ ExampleResponse response = example.sendAndReceiveSpring();
+ LOGGER.info(response.getData());
+
+
+ LOGGER.info("CustomBindingExampleResponse Spring:");
+ CustomBindingExampleResponse customBindingResponse = example.sendAndReceiveSpringCustom();
+ LOGGER.info(customBindingResponse.getData());
+ }
+}
--- /dev/null
+package de.spring.webservices.client.transport.http;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.ws.transport.WebServiceConnection;
+import org.springframework.ws.transport.http.AbstractHttpWebServiceMessageSender;
+import org.springframework.ws.transport.http.ClientHttpRequestConnection;
+import org.springframework.ws.transport.http.HttpTransportConstants;
+
+
+/**
+ * Based on ClientHttpRequestMessageSender from the Spring WS framework.
+ *
+ * <p>
+ * Spring WS framework also provides implementations based on the HTTP clients by Jakarta and Apache HttpClient:
+ * {@link https://hc.apache.org/httpcomponents-client-ga/} and {@link http://hc.apache.org/httpclient-3.x/}
+ * </p>
+ *
+ * <p>
+ * Four implementations for four HTTP clients:
+ * <ul>
+ * <li> org.springframework.ws.transport.http.ClientHttpRequestMessageSender (ClientHttpRequestFactory from the Spring framework) </li>
+ * <li> org.springframework.ws.transport.http.CommonsHttpMessageSender (Jakarta implementation) </li>
+ * <li> org.springframework.ws.transport.http.HttpComponentsMessageSender (Apache HttpClient) </li>
+ * <li> org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
+ * (org.springframework.ws.transport.http.HttpUrlConnection internal Spring framework implementation) </li>
+ * </ul>
+ * </p>
+ */
+public class CustomHttpRequestMessageSender extends AbstractHttpWebServiceMessageSender {
+ private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
+
+ private final ClientHttpRequestFactory requestFactory;
+
+ public CustomHttpRequestMessageSender() {
+ requestFactory = new SimpleClientHttpRequestFactory();
+ }
+
+ @Override
+ public WebServiceConnection createConnection(URI uri) throws IOException {
+ ClientHttpRequest request = requestFactory.createRequest(uri, HttpMethod.POST);
+ if (isAcceptGzipEncoding()) {
+ request.getHeaders().add(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
+ HttpTransportConstants.CONTENT_ENCODING_GZIP);
+ }
+
+ request.getHeaders().add(MY_CUSTOM_HEADER, "gumartinm.name");
+
+ return new ClientHttpRequestConnection(request);
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ status: The level of internal Log4j events that should be logged to the console.
+ Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
+
+ monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
+
+
+ see https://logging.apache.org/log4j/2.x/manual/configuration.html
+ -->
+<Configuration status="error" strict="true" monitorInterval="30"
+ name="XMLConfigTest" packages="org.apache.logging.log4j.test">
+
+ <!--
+ ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
+
+ ERROR by default.
+ -->
+
+ <Appenders>
+ <Appender type="Console" name="STDOUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
+ </Appender>
+ </Appenders>
+ <Loggers>
+
+
+ <!--
+ Specific log when request message from this client or response message created by remote server contains validation errors.
+
+ see client-spring-configuration.xml Spring configuration file.
+
+ This configuration enables us to log validation errors of data sent from this client or data sent by remote server.
+ -->
+ <Logger name="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+ <!--
+ Con esta configuración podemos loguear mensajes de error (SOAP Fault) procedentes del sevidor customizados. En mi caso
+ usando GeneralFault. No se loguean los de validación (ni de envio de cliente ni de respuesta desde el servidor)
+ porque esto lo hace PayloadValidatingInterceptor.
+ -->
+ <Logger name="de.spring.webservices.client.CustomFaultMessageResolver" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+ <!-- Specific log level for SOAP XML messages.
+
+ see client-spring-configuration.xml Spring configuration file.
+
+ This configuration enables us to log the SOAP XML Request (sent from this client), Response (sent by remote server) and Fault (sent by remote server).
+ -->
+ <Logger name="org.springframework.ws.client.MessageTracing" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+ <Logger name="org.springframework.ws.server.MessageTracing" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+ <!--
+ Specific log level for Spring WS.
+ -->
+ <Logger name="org.springframework.ws" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ General logging Spring.
+ -->
+ <Logger name="org.springframework" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ Anything else will be using TRACE logging level.
+ -->
+ <Root level="INFO">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:parent="http://gumartinm.name/spring-ws/parent"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="inheritance annox"
+ targetNamespace="http://gumartinm.name/spring-ws/example"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <!--
+ We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
+ when creating Java objects from examples.xsd.
+ -->
+ <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
+
+
+ <!-- Spring requires the following:
+ 1. XSD elements being used as request must end with Request name.
+ 2. XSD elements being used as response must end with Response name.
+
+ IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
+
+ ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
+ the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
+ The same for CustomBindingExample.
+ -->
+ <!-- Using inheritance and annox plugin -->
+ <xsd:element name="ExampleRequest">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="parent:limitedString" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleResponse">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- Using custombinding.xjb instead of inheritance plugin.
+ Useful when you can not modify your xsd files because they are provided
+ by another person or company
+ -->
+ <xsd:element name="CustomBindingExampleRequest">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleResponse">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Example of creating array list by means of XSD -->
+ <xsd:complexType name="car">
+ <xsd:sequence>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="truck">
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ <xsd:element name="vehicles">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="cars" type="car" maxOccurs="unbounded" />
+ <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:sws="http://www.springframework.org/schema/web-services"
+ xmlns:oxm="http://www.springframework.org/schema/oxm"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:util="http://www.springframework.org/schema/util"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/web-services
+ http://www.springframework.org/schema/web-services/web-services.xsd
+ http://www.springframework.org/schema/oxm
+ http://www.springframework.org/schema/oxm/spring-oxm.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+ <!--
+ This file is an example about how someone should write code in order to send and
+ receive data from the Web Services.
+ -->
+
+ <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Component, etc, etc) -->
+ <context:component-scan base-package="de.spring.webservices"/>
+
+ <!--
+ Three ways of using a marshallers/unmarshallers.
+
+ 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
+ Esto equivale a esta configuracion en XML
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
+ El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
+
+ 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
+ se hace de este modo:
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.auto"/>
+ Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
+ de especificar un context-path en concreto.
+
+ 3. Especificando la implementación concreta del marshaller.
+ Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
+ cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
+ De todos modos, probablemente habría que usar un package distinto para lo que hay
+ en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
+ -->
+ <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
+ <!--
+ maven-jaxb2-plugin for WSDL DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
+ So we MAY NOT scan everything because there is more than one class representing
+ the same XML element. :(
+
+ We scan the objects generated in this package.
+ -->
+ <property name="packagesToScan" value="de.spring.webservices.client.auto"/>
+ </bean>
+
+
+ <!-- Required in order to use SOAP 1.2
+ id="messageFactory" is not a random choice, if you use another name it will not work
+ (Spring will end up loading SOAP 1.1)
+ -->
+ <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
+ <property name="soapVersion">
+ <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
+ </property>
+ </bean>
+
+
+ <!--
+ ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
+ del JAXB2 que estoy usando para generar las clases desde el xsd)
+ Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
+ debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
+ funciona, así que supongo el validador tambien :/
+ Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
+ -->
+ <bean id="payloadValidatingInterceptor"
+ class="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor">
+ <property name="schemas">
+ <list>
+ <!--
+ ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
+ OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
+ EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
+
+ IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
+ EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
+ REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
+ CONFIGURATION.
+ -->
+ <value>classpath:schemas/parent.xsd</value>
+
+ <value>classpath:schemas/examples.xsd</value>
+ </list>
+ </property>
+ <property name="validateRequest" value="true"/>
+ <property name="validateResponse" value="true"/>
+ </bean>
+
+ <!--
+ Los errores de validacion se devuelven así:
+
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+ <env:Header/>
+ <env:Body>
+ <env:Fault>
+ <env:Code>
+ <env:Value>env:Sender</env:Value>
+ </env:Code>
+ <env:Reason>
+ <env:Text xml:lang="en">Validation error</env:Text>
+ </env:Reason>
+ <env:Detail>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
+ </env:Detail>
+ </env:Fault>
+ </env:Body>
+ </env:Envelope>
+
+ El manejador de errores de validación es implementado por AbstractValidatingInterceptor (PayloadValidatingInterceptor)
+ luego si quisiéramos loguear los mensaje de error de validación de algún modo especial tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
+ -->
+
+ <!-- Enables us to log custom Fault remote messages. No loguea mensajes de error de validación :( -->
+ <bean id="customFaultMessageResolver" class="de.spring.webservices.client.CustomFaultMessageResolver">
+ <property name="unmarshaller" ref="marshaller"/>
+ </bean>
+
+ <!--
+ WebServiceTemplate using these strategies by default (see WebServiceTemplate.properties file)
+
+ org.springframework.ws.client.core.FaultMessageResolver=org.springframework.ws.soap.client.core.SoapFaultMessageResolver
+ org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
+ org.springframework.ws.transport.WebServiceMessageSender=org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
+
+ -->
+
+ <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
+ <constructor-arg ref="messageFactory"/>
+ <property name="marshaller" ref="marshaller" />
+ <property name="unmarshaller" ref="marshaller" />
+
+ <!-- For local deployments change to http://localhost:8080/web-services-spring-jaxb2-server/spring-ws/example -->
+ <property name="defaultUri" value="http://gumartinm.name/spring-ws/example"/>
+
+ <property name="interceptors">
+ <list>
+ <ref bean="payloadValidatingInterceptor" />
+ </list>
+ </property>
+
+ <property name="faultMessageResolver" ref="customFaultMessageResolver" />
+
+ <property name="messageSenders">
+ <list>
+ <bean class="de.spring.webservices.client.transport.http.CustomHttpRequestMessageSender" />
+ </list>
+ </property>
+ </bean>
+
+ <!--
+ Using @Service and @Autowired
+ We could use just XML configuration, or XML confirguration and @Autowired or as I am doing now @Service and @Autowired.
+ <bean id="exampleClientService" class="de.spring.webservices.client.ExampleClientService">
+
+ @Autowired works even using XML configuration as long as you use context:component-scan
+ <property name="webServiceTemplate" ref="webServiceTemplate"/>
+ </bean>
+ -->
+
+</beans>
--- /dev/null
+package de.spring.webservices.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.ws.test.client.RequestMatchers.payload;
+import static org.springframework.ws.test.client.ResponseCreators.withPayload;
+
+import javax.xml.transform.Source;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.ws.client.core.WebServiceTemplate;
+import org.springframework.ws.test.client.MockWebServiceServer;
+import org.springframework.xml.transform.StringSource;
+
+import de.spring.webservices.client.auto.CustomBindingExampleResponse;
+import de.spring.webservices.client.auto.ExampleResponse;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("classpath*:spring-configuration/ws/client-spring-configuration.xml")
+public class ExampleClientServiceIntegrationTest {
+
+ @Autowired
+ ExampleClientService exampleClientService;
+
+ @Autowired
+ private WebServiceTemplate webServiceTemplate;
+
+ private MockWebServiceServer mockServer;
+
+ @Before
+ public void createServer() throws Exception {
+ mockServer = MockWebServiceServer.createServer(webServiceTemplate);
+ }
+
+ @Test
+ public void customerClient() throws Exception {
+ final Source requestPayload = new StringSource(
+ "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>"
+ + "<data>SCARLETT SPRING. IT IS CANON.</data>"
+ + "</ExampleRequest>");
+ final Source responsePayload = new StringSource(
+ "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>"
+ + "<ns2:data>SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>"
+ + "</ns2:ExampleResponse>");
+ mockServer.expect(payload(requestPayload)).andRespond(
+ withPayload(responsePayload));
+
+ final ExampleResponse response = exampleClientService.sendAndReceiveSpring();
+
+ assertEquals(response.getData(), "SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
+ mockServer.verify();
+ }
+
+ @Test
+ public void customerCustomClient() throws Exception {
+ final Source customRequestPayload = new StringSource(
+ "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
+ "<data>CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.</data>" +
+ "</CustomBindingExampleRequest>");
+ final Source customResponsePayload = new StringSource(
+ "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
+ "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>" +
+ "</ns2:CustomBindingExampleResponse>");
+ mockServer.expect(payload(customRequestPayload)).andRespond(
+ withPayload(customResponsePayload));
+
+ final CustomBindingExampleResponse response = exampleClientService.sendAndReceiveSpringCustom();
+
+ assertEquals(response.getData(), "CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
+ mockServer.verify();
+ }
+}
+
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>web-services-spring-jaxb2</artifactId>
+ <groupId>de.spring.webservices</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
+ <name>web-services-spring-jaxb2-globalxsds</name>
+ <url>http://gumartinm.name</url>
+
+ <properties>
+ <project.xsd.schemas.source.path>src/main/resources/schemas</project.xsd.schemas.source.path>
+ <project.xsd.schemas.target.path>${project.build.directory}/generated-sources/src/main/java</project.xsd.schemas.target.path>
+ <project.xsd.schemas.package.name>de.spring.webservices.parent.auto</project.xsd.schemas.package.name>
+ <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
+ </properties>
+
+ <dependencies>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*.*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <version>0.13.1</version>
+ <executions>
+ <execution>
+ <id>generate-sources-from-xsd</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ <configuration>
+ <!-- Specifies the schema directory, src/main/resources by default. -->
+ <schemaDirectory>${project.xsd.schemas.source.path}</schemaDirectory>
+
+ <!-- Specifies the binding directory, default to the schemaDirectory -->
+ <bindingDirectory>${project.bindings.path}</bindingDirectory>
+ <!-- Do not scan for *.xjb files in dependencies -->
+ <scanDependenciesForBindings>false</scanDependenciesForBindings>
+
+ <!-- Target directory for the generated code, target/generated-sources/xjc
+ by default. -->
+ <generateDirectory>${project.xsd.schemas.target.path}</generateDirectory>
+
+ <!-- The generated classes will all be placed under this Java package
+ (XJC's -p option), unless otherwise specified in the schemas. If left unspecified,
+ the package will be derived from the schemas only. -->
+ <generatePackage>${project.xsd.schemas.package.name}</generatePackage>
+
+ <!-- I don't think I need the next two options because mvn clean should
+ make the trick, anyhow, I am using them. If true, the generateDirectory will
+ be deleted before the XJC binding compiler recompiles the source files. Default
+ is false. -->
+ <removeOldOutput>true</removeOldOutput>
+ <!-- If true (default), package directories will be cleaned before the
+ XJC binding compiler generates the source files. -->
+ <cleanPackageDirectories>true</cleanPackageDirectories>
+
+ <!-- Encoding for the generated sources, defaults to ${project.build.sourceEncoding}. -->
+ <encoding>${project.build.sourceEncoding}</encoding>
+
+ <!-- Locale used during generation, for instance en, de, fr etc. This
+ will, for instance, influence the language of the generated JavaDoc comments. -->
+ <locale>en</locale>
+
+ <!-- This nice configuration avoids to use build-helper-maven-plugin -->
+ <addCompileSourceRoot>true</addCompileSourceRoot>
+ <addTestCompileSourceRoot>false</addTestCompileSourceRoot>
+
+ <!-- If true (default), XJC will perform strict validation of the input
+ schema. If strict is set to false XJC will be run with -nv, this disables
+ strict validation of schemas. -->
+ <strict>true</strict>
+
+ <verbose>true</verbose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="">
+
+</jaxb:bindings>
--- /dev/null
+package de.spring.webservices.binders;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+
+/**
+ * ATTENTION: if you are using this custombinder you will have to create custom payload
+ * validators for Spring (AS FAR AS I KNOW)
+ *
+ */
+public class XSDateTimeCustomBinder extends XmlAdapter<String, Date> {
+
+ @Override
+ public Date unmarshal(final String dateTime) throws Exception {
+ // X pattern just works from Java >= 1.7
+ final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
+
+ return formatter.parse(dateTime);
+ }
+
+ @Override
+ public String marshal(final Date dateTime) throws Exception {
+ // X pattern just works from Java >= 1.7
+ final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
+
+ return formatter.format(dateTime);
+ }
+}
--- /dev/null
+package de.spring.webservices.operations;
+
+/**
+ * <p>
+ * Operations: WSDL v1.1 and v2.0
+ * </p>
+ * See: <a href="http://www.w3.org/TR/wsdl#_porttypes">http://www.w3.org/TR/wsdl#_porttypes</a><br>
+ * See: <a href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ */
+public interface Operations {
+
+ /**
+ * <p>
+ * Request-response operation WSDL v1.1
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/wsdl#_request-response">http://www.w3.org
+ * /TR/wsdl#_request-response</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public static interface RequestResponse<T extends Response, E extends Request> {
+ T requestResponse(E request);
+ }
+
+ /**
+ * <p>
+ * One-way operation WSDL v1.1
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/wsdl#_one-way">http://www.w3.org/TR/wsdl
+ * #_one-way</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface OneWay<E extends Request> {
+ void oneWay(E request);
+ }
+
+ /**
+ * <p>
+ * Notification operation WSDL v1.1
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/wsdl#_notification">http://www.w3.org/TR
+ * /wsdl#_notification</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface Notification<T extends Response> {
+ T notification();
+ }
+
+ /**
+ * <p>
+ * In-Only message exchange pattern WSDL 2.0
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface InOnly<E extends Request> {
+ void inOnly(E request);
+ }
+
+ /**
+ * <p>
+ * Robust In-Only message exchange pattern WSDL 2.0
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface RobustInOnly<E extends Request> {
+ void robustInOnly(E request);
+ }
+
+ /**
+ * <p>
+ * In-Out message exchange pattern WSDL 2.0
+ * </p>
+ * See: <a
+ * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
+ * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
+ *
+ * @param <T>
+ * Describes {@link Response}
+ * @param <E>
+ * Describes {@link Request}
+ */
+ public interface InOut<T extends Response, E extends Request> {
+ T inOut(E request);
+ }
+}
\ No newline at end of file
--- /dev/null
+package de.spring.webservices.operations;
+
+public interface Request {
+
+}
--- /dev/null
+package de.spring.webservices.operations;
+
+public interface Response {
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsd:schema xmlns="http://gumartinm.name/spring-ws/parent"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ targetNamespace="http://gumartinm.name/spring-ws/parent">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <xsd:simpleType name="parentEnumType">
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="FIRST"/>
+ <xsd:enumeration value="SECOND"/>
+ <xsd:enumeration value="THIRD"/>
+ <xsd:enumeration value="FOURTH"/>
+ <xsd:enumeration value="FIVETH"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="limitedString">
+ <xsd:restriction base="xsd:string">
+ <xsd:maxLength value="30" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="element">
+ <xsd:sequence>
+ <xsd:element name="message" type="xsd:string"/>
+ <xsd:element name="messageArgs" type="xsd:string" minOccurs="0" maxOccurs="100"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name="GeneralFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="technicalError" type="xsd:string" />
+ <xsd:element name="elements" type="element" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>web-services-spring-jaxb2</artifactId>
+ <groupId>de.spring.webservices</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>web-services-spring-jaxb2-server</artifactId>
+ <packaging>war</packaging>
+ <name>web-services-spring-jaxb2-server</name>
+ <url>http://gumartinm.name</url>
+
+ <properties>
+ <jetty.version>9.3.0.RC0</jetty.version>
+ <project.xsd.schemas.source.path>src/main/resources/schemas</project.xsd.schemas.source.path>
+ <project.xsd.schemas.target.path>${project.build.directory}/generated-sources/src/main/java</project.xsd.schemas.target.path>
+ <project.xsd.schemas.package.name>de.spring.webservices.server.auto</project.xsd.schemas.package.name>
+ <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-xml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ </dependency>
+
+
+ <!-- Global types -->
+ <dependency>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <!-- Required by spring-ws-core -->
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ </dependency>
+
+ <!-- Required by my CustomHeaderInterceptor -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>4.0.0-b01</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <resources>
+ <resource>
+ <directory>${basedir}/src/main/webapp</directory>
+ <excludes>
+ <exclude>**/*.*</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>${basedir}/src/main/resources/</directory>
+ <includes>
+ <include>**/*.*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <version>0.13.1</version>
+ <executions>
+ <execution>
+ <id>generate-sources-from-xsd</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ <configuration>
+ <schemaLanguage>XMLSCHEMA</schemaLanguage>
+
+ <!-- Specifies the schema directory, src/main/resources by default. -->
+ <schemaDirectory>${project.xsd.schemas.source.path}</schemaDirectory>
+
+ <!-- Specifies the binding directory, default to the schemaDirectory -->
+ <bindingDirectory>${project.bindings.path}</bindingDirectory>
+ <!-- Do not scan for *.xjb files in dependencies -->
+ <scanDependenciesForBindings>false</scanDependenciesForBindings>
+
+ <!-- Target directory for the generated code, target/generated-sources/xjc
+ by default. -->
+ <generateDirectory>${project.xsd.schemas.target.path}</generateDirectory>
+
+ <!-- The generated classes will all be placed under this Java package
+ (XJC's -p option), unless otherwise specified in the schemas. If left unspecified,
+ the package will be derived from the schemas only. -->
+ <generatePackage>${project.xsd.schemas.package.name}</generatePackage>
+
+ <!-- I don't think I need the next two options because mvn clean should
+ make the trick, anyhow, I am using them. If true, the generateDirectory will
+ be deleted before the XJC binding compiler recompiles the source files. Default
+ is false. -->
+ <removeOldOutput>true</removeOldOutput>
+ <!-- If true (default), package directories will be cleaned before the
+ XJC binding compiler generates the source files. -->
+ <cleanPackageDirectories>true</cleanPackageDirectories>
+
+ <!-- Encoding for the generated sources, defaults to ${project.build.sourceEncoding}. -->
+ <encoding>${project.build.sourceEncoding}</encoding>
+
+ <!-- Locale used during generation, for instance en, de, fr etc. This
+ will, for instance, influence the language of the generated JavaDoc comments. -->
+ <locale>en</locale>
+
+ <!-- This nice configuration avoids to use build-helper-maven-plugin -->
+ <addCompileSourceRoot>true</addCompileSourceRoot>
+ <addTestCompileSourceRoot>false</addTestCompileSourceRoot>
+
+ <!-- If true (default), XJC will perform strict validation of the input
+ schema. If strict is set to false XJC will be run with -nv, this disables
+ strict validation of schemas.
+
+ The plugin is configured to use catalogs and strict mode at the
+ same time. Using catalogs to resolve schema URIs in strict mode is known
+ to be problematic and may fail. Please refer to the following link for more
+ information: https://github.com/highsource/maven-jaxb2-plugin/wiki/Catalogs-in-Strict-Mode
+ Consider setting <strict>false</strict> in your plugin configuration. -->
+ <strict>false</strict>
+
+ <verbose>true</verbose>
+
+ <extension>true</extension>
+ <args>
+ <arg>-Xinheritance</arg>
+ <arg>-Xannotate</arg>
+ </args>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics</artifactId>
+ <version>0.9.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-annotate</artifactId>
+ <version>1.0.2</version>
+ </plugin>
+ </plugins>
+
+ <!-- Avoids the annoying SCD "x-schema::tns" didn't match any schema component errors. -->
+ <addIfExistsToEpisodeSchemaBindings>true</addIfExistsToEpisodeSchemaBindings>
+
+ <!--
+ GRAN DIFERENCIA:
+
+ :) CON ESTE PLUGIN A DIFERENCIA DE cxf-xjc-plugin NO SE VUELVEN A GENERAR LOS OBJETOS DE parent.xsd
+ QUE SE ENCONTRABAN EN web-services-spring-jaxb2-globalxsds
+
+ CON cxf-xjc-plugin SÍ SE VUELVEN A GENERAR INCLUSO AUNQUE USEMOS EPISODIOS :(
+
+ CON ESTE PLUGIN CONSEGUIMOS NO EMPAQUETAR AQUÍ TAMBIÉN LAS MISMAS CLASES QUE
+ TENÍAMOS EN web-services-spring-jaxb2-globalxsds
+
+ ESTE PLUGIN ES MUCHO MEJOR QUE cxf-xjc-plugin :)
+ -->
+
+ <!-- You can use the useDependenciesAsEpisodes instead of configuring
+ individual episodes. In this case all the dependencies will be treated as
+ episodes which is very convenient (less configuration). I am going to use
+ the long way (individual episodes) -->
+ <useDependenciesAsEpisodes>false</useDependenciesAsEpisodes>
+ <catalog>src/main/build-resources/catalogs/catalog.cat</catalog>
+ <episodes>
+ <episode>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
+ </episode>
+ </episodes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <webResources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/webapp</directory>
+ <includes>
+ <include>WEB-INF/web.xml</include>
+ </includes>
+ </resource>
+ </webResources>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <version>${jetty.version}</version>
+ <configuration>
+ <jettyXml>${basedir}/src/main/jetty/jetty-http.xml</jettyXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="xjc inheritance annox">
+
+ <!--
+ Se procesa con Xpath si quieres meter expresiones regulares y cosas así en teoría dependes de Xpath
+ por ejemplo esto: @name=match[.] se supone que debería funcionar pero me dice que no puede
+ cambiar mas de un nodo a la vez. Puede que sea un bug de xjc que se carga las opciones de Xpath :/
+ <jaxb:bindings schemaLocation="examples.xsd">
+ <jaxb:bindings node="//xsd:element[@name='ExampleRequest']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </jaxb:bindings>
+ <jaxb:bindings node="//xsd:element[@name='ExampleResponse']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </jaxb:bindings>
+ </jaxb:bindings>
+ -->
+
+ <jaxb:bindings schemaLocation="../../resources/schemas/examples.xsd">
+ <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleRequest']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ </jaxb:bindings>
+ </jaxb:bindings>
+
+
+ <jaxb:bindings schemaLocation="../../resources/schemas/examples.xsd">
+ <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleResponse']/xsd:complexType">
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ </jaxb:bindings>
+ </jaxb:bindings>
+
+ <!-- The same applies to annotate. If you do not want or you may not modify your xsd files you can
+ modify instead this file with your custom binding :) -->
+
+ <!-- Custom xsd:dateTime adapter
+ See: https://jaxb.java.net/2.2.4/docs/vendorCustomizations.html#javaType
+ -->
+ <jaxb:globalBindings>
+ <xjc:javaType adapter="de.spring.webservices.binders.XSDateTimeCustomBinder"
+ name="java.util.Date" xmlType="xsd:dateTime" />
+ </jaxb:globalBindings>
+
+</jaxb:bindings>
--- /dev/null
+
+
+REWRITE_SYSTEM "http://gumartinm.name/spring-ws/parent/parent.xsd" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
+
+--
+ This configuration is better (it relies on namespace instead of schemaLocation) but it doesn't work
+ because of this bug: https://java.net/jira/browse/JAXB-942
+
+ PUBLIC "xmlns:parent" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
+
+--
+
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.server.EndpointInterceptor;
+import org.springframework.ws.transport.context.TransportContext;
+import org.springframework.ws.transport.context.TransportContextHolder;
+import org.springframework.ws.transport.http.HttpServletConnection;
+
+public class CustomHeaderInterceptor implements EndpointInterceptor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CustomHeaderInterceptor.class);
+ private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
+
+ @Override
+ public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
+ TransportContext transport = TransportContextHolder.getTransportContext();
+
+ if (transport != null) {
+ HttpServletConnection connection = (HttpServletConnection) transport.getConnection();
+ HttpServletRequest headers = connection.getHttpServletRequest();
+ String headerValue = headers.getHeader(MY_CUSTOM_HEADER);
+
+ if (!StringUtils.isEmpty(headerValue)) {
+ LOGGER.info("Custom header value: " + headerValue);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
+ return true;
+ }
+
+ @Override
+ public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
+
+ }
+
+}
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import org.jdom2.Element;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ws.context.MessageContext;
+import org.springframework.ws.server.endpoint.annotation.Endpoint;
+import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
+import org.springframework.ws.server.endpoint.annotation.RequestPayload;
+import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.operations.Operations.RequestResponse;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+import de.spring.webservices.services.ExampleService;
+
+
+@Endpoint
+public class ExampleEndPoint {
+ private static final String NAMESPACE_URI = "http://gumartinm.name/spring-ws/example";
+
+ private final Operations.RequestResponse
+ <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
+
+ private final ExampleService exampleService;
+
+ @Autowired
+ public ExampleEndPoint(
+ RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService,
+ ExampleService exampleService) {
+ this.customBindingExampleService = customBindingExampleService;
+ this.exampleService = exampleService;
+ }
+
+ @PayloadRoot(localPart = "ExampleRequest", namespace = NAMESPACE_URI)
+ @ResponsePayload
+ public ExampleResponse exampleResponse(
+ @RequestPayload final ExampleRequest request,
+ @RequestPayload final Element element,
+ final MessageContext messageContext) {
+
+ return this.exampleService.doResponse(request);
+ }
+
+ @PayloadRoot(localPart = "CustomBindingExampleRequest", namespace = NAMESPACE_URI)
+ @ResponsePayload
+ public CustomBindingExampleResponse cuntomBindingExampleResponse(
+ @RequestPayload final CustomBindingExampleRequest requestObject,
+ @RequestPayload final Element element,
+ final MessageContext messageContext) {
+
+ return this.customBindingExampleService.requestResponse(requestObject);
+ }
+}
+
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.transform.Result;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.oxm.Marshaller;
+import org.springframework.util.CollectionUtils;
+import org.springframework.ws.soap.SoapFault;
+import org.springframework.ws.soap.SoapFaultDetail;
+import org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver;
+import org.springframework.ws.soap.server.endpoint.SoapFaultDefinition;
+import org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor;
+
+import de.spring.webservices.exceptions.CustomBusinessException;
+import de.spring.webservices.parent.auto.Element;
+import de.spring.webservices.parent.auto.GeneralFault;
+
+public class MyCustomMappingExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomMappingExceptionResolver.class);
+
+ private Marshaller marshaller;
+
+ private Map<String, String> exceptionMappings = new LinkedHashMap<>();
+
+ /**
+ * Set the mappings between exception class names and SOAP Faults. The exception class name can be a substring, with
+ * no wildcard support at present.
+ *
+ * <p>The values of the given properties object should use the format described in
+ * {@code SoapFaultDefinitionEditor}.
+ *
+ * <p>Follows the same matching algorithm as {@code SimpleMappingExceptionResolver}.
+ *
+ * @param mappings exception patterns (can also be fully qualified class names) as keys, fault definition texts as
+ * values
+ * @see SoapFaultDefinitionEditor
+ */
+ public void setExceptionMappings(Properties mappings) {
+ for (Map.Entry<Object, Object> entry : mappings.entrySet()) {
+ if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
+ exceptionMappings.put((String)entry.getKey(), (String)entry.getValue());
+ }
+ }
+ }
+
+ @Override
+ protected SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) {
+ if (!CollectionUtils.isEmpty(exceptionMappings)) {
+ String definitionText = null;
+ int deepest = Integer.MAX_VALUE;
+ for (String exceptionMapping : exceptionMappings.keySet()) {
+ int depth = getDepth(exceptionMapping, ex);
+ if (depth >= 0 && depth < deepest) {
+ deepest = depth;
+ definitionText = exceptionMappings.get(exceptionMapping);
+ }
+ }
+ if (definitionText != null) {
+ SoapFaultDefinitionEditor editor = new SoapFaultDefinitionEditor();
+ editor.setAsText(definitionText);
+ return (SoapFaultDefinition) editor.getValue();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the depth to the superclass matching. {@code 0} means ex matches exactly. Returns {@code -1} if
+ * there's no match. Otherwise, returns depth. Lowest depth wins.
+ *
+ * <p>Follows the same algorithm as RollbackRuleAttribute, and SimpleMappingExceptionResolver
+ */
+ protected int getDepth(String exceptionMapping, Exception ex) {
+ return getDepth(exceptionMapping, ex.getClass(), 0);
+ }
+
+ @SuppressWarnings("unchecked")
+ private int getDepth(String exceptionMapping, Class<? extends Exception> exceptionClass, int depth) {
+ if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
+ return depth;
+ }
+ if (exceptionClass.equals(Throwable.class)) {
+ return -1;
+ }
+ return getDepth(exceptionMapping, (Class<? extends Exception>) exceptionClass.getSuperclass(), depth + 1);
+ }
+
+ protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
+ GeneralFault customFault = new GeneralFault();
+ customFault.setTechnicalError(getStackTrace(ex));
+
+ Element element = buildElement(ex);
+ List<Element> elements = customFault.getElements();
+ elements.add(element);
+
+ SoapFaultDetail detail = fault.addFaultDetail();
+ Result result = detail.getResult();
+ try {
+ marshaller.marshal(customFault, result);
+ } catch (Exception marshallEx) {
+ LOGGER.error("MyCustomMappingExceptionResolver: marshaller error", marshallEx);
+ }
+ }
+
+ public void setMarshaller(Marshaller marshaller) {
+ this.marshaller = marshaller;
+ }
+
+ private Element buildElement(Exception ex) {
+ Element element = new Element();
+ element.setMessage(ex.getMessage());
+
+ if (ex instanceof CustomBusinessException) {
+ CustomBusinessException customEx = (CustomBusinessException) ex;
+ List<String> messageArgs = element.getMessageArgs();
+ List<String> argumentsEx = customEx.getArguments();
+
+ for (String argumentEx: argumentsEx) {
+ messageArgs.add(argumentEx);
+ }
+ }
+
+ return element;
+ }
+
+ private String getStackTrace(Throwable throwable) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw, true);
+ throwable.printStackTrace(pw);
+ return sw.getBuffer().toString();
+ }
+}
--- /dev/null
+package de.spring.webservices.exceptions;
+
+/**
+ * This exception will be caught by org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
+ *
+ */
+public class BusinessException extends RuntimeException {
+
+ private static final long serialVersionUID = -4042139454770293299L;
+
+ public BusinessException() {
+ super();
+ }
+
+ public BusinessException(String message) {
+ super(message);
+ }
+
+ public BusinessException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
--- /dev/null
+package de.spring.webservices.exceptions;
+
+import java.util.List;
+
+/**
+ * This exception will be caught by de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
+ *
+ */
+public class CustomBusinessException extends RuntimeException {
+ private final List<String> arguments;
+
+ public CustomBusinessException(List<String> arguments) {
+ super();
+ this.arguments = arguments;
+ }
+
+ public CustomBusinessException(String message, List<String> arguments) {
+ super(message);
+
+ this.arguments = arguments;
+ }
+
+ public CustomBusinessException(String message, Throwable cause, List<String> arguments) {
+ super(message, cause);
+
+ this.arguments = arguments;
+ }
+
+ public List<String> getArguments() {
+ return arguments;
+ }
+}
--- /dev/null
+package de.spring.webservices.services;
+
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+
+
+public interface ExampleService {
+
+ public ExampleResponse doResponse(ExampleRequest request);
+
+}
--- /dev/null
+package de.spring.webservices.services.impl;
+
+//import java.util.ArrayList;
+//import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.parent.auto.ParentEnumType;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+//import de.spring.webservices.exceptions.BusinessException;
+//import de.spring.webservices.exceptions.CustomBusinessException;
+
+
+@Service("customBindingExampleService")
+public class CustomBindingExampleServiceImpl implements
+ Operations.RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> {
+
+
+ @Override
+ public CustomBindingExampleResponse requestResponse(final CustomBindingExampleRequest request) {
+
+
+ // Example about how works org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
+ // see soap-ws.xml Spring configuration file.
+// throw new BusinessException("This feature has not been implemented yet.");
+
+ // Example about how works de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
+ // see soap-ws.xml Spring configuration file.
+// List<String> arguments = new ArrayList<>();
+// arguments.add("ARGUMENT 1");
+// arguments.add("ARGUMENT 2");
+// throw new CustomBusinessException("This feature has not been implemented yet.", arguments);
+
+ CustomBindingExampleResponse response = new CustomBindingExampleResponse();
+
+ response.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
+ response.setParentEnum(ParentEnumType.FIRST);
+
+ return response;
+ }
+
+}
--- /dev/null
+package de.spring.webservices.services.impl;
+
+import org.springframework.stereotype.Service;
+
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+import de.spring.webservices.services.ExampleService;
+
+
+@Service("exampleService")
+public class ExampleServiceImpl implements ExampleService {
+
+ @Override
+ public ExampleResponse doResponse(final ExampleRequest request) {
+
+ ExampleResponse response = new ExampleResponse();
+
+ response.setData("SNAKE EYES AND " + request.getData());
+
+ return response;
+ }
+
+}
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+
+<!-- ============================================================= -->
+<!-- Configure the Jetty Server instance with an ID "Server" -->
+<!-- by adding a HTTP connector. -->
+<!-- This configuration must be used in conjunction with jetty.xml -->
+<!-- ============================================================= -->
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
+ <Set name="secureScheme">https</Set>
+ <Set name="securePort">
+ <Property name="jetty.secure.port" default="8443" />
+ </Set>
+ <Set name="outputBufferSize">32768</Set>
+ <Set name="requestHeaderSize">8192</Set>
+ <Set name="responseHeaderSize">8192</Set>
+ <Set name="sendServerVersion">true</Set>
+ <Set name="sendDateHeader">false</Set>
+ <Set name="headerCacheSize">512</Set>
+
+ <!-- Uncomment to enable handling of X-Forwarded- style headers
+ <Call name="addCustomizer">
+ <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
+ </Call>
+ -->
+ </New>
+
+
+ <!-- =========================================================== -->
+ <!-- Add a HTTP Connector. -->
+ <!-- Configure an o.e.j.server.ServerConnector with a single -->
+ <!-- HttpConnectionFactory instance using the common httpConfig -->
+ <!-- instance defined in jetty.xml -->
+ <!-- -->
+ <!-- Consult the javadoc of o.e.j.server.ServerConnector and -->
+ <!-- o.e.j.server.HttpConnectionFactory for all configuration -->
+ <!-- that may be set here. -->
+ <!-- =========================================================== -->
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.ServerConnector">
+ <Arg name="server">
+ <Ref refid="Server" />
+ </Arg>
+ <Arg name="factories">
+ <Array type="org.eclipse.jetty.server.ConnectionFactory">
+ <Item>
+ <New class="org.eclipse.jetty.server.HttpConnectionFactory">
+ <Arg name="config">
+ <Ref refid="httpConfig" />
+ </Arg>
+ </New>
+ </Item>
+ </Array>
+ </Arg>
+ <Set name="host">
+ <Property name="jetty.host" default="127.0.0.1"/>
+ </Set>
+ <Set name="port">
+ <Property name="jetty.port" default="8080" />
+ </Set>
+ <Set name="idleTimeout">
+ <Property name="http.timeout" default="30000"/>
+ </Set>
+ </New>
+ </Arg>
+ </Call>
+
+</Configure>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ status: The level of internal Log4j events that should be logged to the console.
+ Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
+
+ monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
+
+
+ see https://logging.apache.org/log4j/2.x/manual/configuration.html
+ -->
+<Configuration status="error" strict="true" monitorInterval="30"
+ name="XMLConfigTest" packages="org.apache.logging.log4j.test">
+
+ <!--
+ ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
+
+ ERROR by default.
+ -->
+
+ <Appenders>
+ <Appender type="Console" name="STDOUT">
+ <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
+ </Appender>
+ </Appenders>
+ <Loggers>
+
+
+ <!--
+ Specific log when request message from remote client or response message created by this server contains validation errors.
+
+ see soap-ws.xml Spring configuration file.
+
+ This configuration enables us to log validation errors of data sent from remote client or data created by this server.
+
+ Los errores de validación se loguean aquí (tanto de validación de datos de respuesta de servidor como de datos recibidos desde cliente)
+ -->
+ <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!-- Specific log level for SOAP SoapEnvelopeLoggingInterceptor.
+
+ see soap-ws.xml Spring configuration file.
+
+ This configuration enables us to log the SOAP XML Request (received from remote client), Response (sent by this server) and Fault (sent by this server).
+
+ Aquí no se loguean errores de validación.
+ -->
+ <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+
+ <!--
+ Specific log level for Spring WS.
+ -->
+ <Logger name="org.springframework.ws" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ General logging Spring.
+ -->
+ <Logger name="org.springframework" level="INFO" additivity="false">
+ <AppenderRef ref="STDOUT" />
+ </Logger>
+
+
+ <!--
+ Anything else will be using TRACE logging level.
+ -->
+ <Root level="INFO">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:parent="http://gumartinm.name/spring-ws/parent"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:version="2.1"
+ jaxb:extensionBindingPrefixes="inheritance annox"
+ targetNamespace="http://gumartinm.name/spring-ws/example"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+
+ <!--
+ When should an item be declared as an element versus when should it be defined as a type?
+ When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
+
+ <xsd:all> specifies that the child elements can appear in any order.
+
+ <xsd:sequence> specifies child elements can only appear in the order mentioned.
+ -->
+
+ <!--
+ We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
+ when creating Java objects from examples.xsd.
+ -->
+ <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
+
+
+ <!-- Spring requires the following:
+ 1. XSD elements being used as request must end with Request name.
+ 2. XSD elements being used as response must end with Response name.
+
+ IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
+
+ ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
+ the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
+ The same for CustomBindingExample.
+ -->
+ <!-- Using inheritance and annox plugin -->
+ <xsd:element name="ExampleRequest">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
+ <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="parent:limitedString" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleResponse">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:appinfo>
+ <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <!-- Using custombinding.xjb instead of inheritance plugin.
+ Useful when you can not modify your xsd files because they are provided
+ by another person or company
+ -->
+ <xsd:element name="CustomBindingExampleRequest">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleResponse">
+ <xsd:complexType>
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="CustomBindingExampleFault">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parent:GeneralFault" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Example of creating array list by means of XSD -->
+ <xsd:complexType name="car">
+ <xsd:sequence>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="truck">
+ <xsd:all>
+ <xsd:element name="data" type="xsd:string" />
+ <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
+ </xsd:all>
+ </xsd:complexType>
+ <xsd:element name="vehicles">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="cars" type="car" maxOccurs="unbounded" />
+ <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+</beans>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:sws="http://www.springframework.org/schema/web-services"
+ xmlns:util="http://www.springframework.org/schema/util"
+
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/web-services
+ http://www.springframework.org/schema/web-services/web-services.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd">
+
+ <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Endpoint, etc, etc) -->
+ <context:component-scan base-package="de.spring.webservices"/>
+
+ <!--
+ Three ways of using a marshallers/unmarshallers.
+
+ 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
+ Esto equivale a esta configuracion en XML
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
+ El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
+
+ 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
+ se hace de este modo:
+
+ <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.server.auto"/>
+ Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
+ de especificar un context-path en concreto.
+
+ 3. Especificando la implementación concreta del marshaller.
+ Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
+ cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
+ De todos modos, probablemente habría que usar un package distinto para lo que hay
+ en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
+ -->
+ <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
+ <!--
+ maven-jaxb2-plugin does NOT generate again the objects in web-services-spring-jaxb2-globalxsds
+ So we MAY scan everything and there is no trouble because there is not more than one class representing
+ the same XML element.
+ -->
+ <property name="packagesToScan" value="de.spring.webservices"/>
+ </bean>
+ <!-- Searches for @PayloadRoot -->
+ <sws:annotation-driven marshaller="marshaller" unmarshaller="marshaller" />
+
+
+ <!--
+ CONSECUENCIAS DE USAR sws:annotation-driven VER: org.springframework.ws.config.AnnotationDrivenBeanDefinitionParser
+ Cuanto más bajo es el valor de order mayor es la prioridad.
+
+ 1. Manejadores de excepción, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
+ a) SoapFaultAnnotationExceptionResolver será el primer manejador de excepciones que se intente usar por defecto. order = 0
+ b) SimpleSoapExceptionResolver será el último manejador de excepciones que se intente usar por defecto. order = Ordered.LOWEST_PRECEDENCE
+ Se usará si la excepción generada no pudo ser manejada por SoapFaultAnnotationExceptionResolver (porque la excepción no fue anotada con
+ @SoapFault. Este manejador se traga cualquier excepción.
+
+ 2. Endpoints a buscar, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
+ a) PayloadRootAnnotationMethodEndpointMapping será el primer tipo de endpoints que se buscará y que se intentará usar. order = 0
+ Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a b).
+ b) SoapActionAnnotationMethodEndpointMapping será el segundo tipo de endpoints que se intentará usar. order = 1
+ Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a c).
+ c) AnnotationActionEndpointMapping será el último tipo de endpoints que se buscará. order = 2
+ Si el XML SOAP que llega no machea tampoco métodos anotado con este EndPoint se
+ lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
+
+
+ EN LUGAR DE USAR LA ANOTACIÓN PODRÍAMOS HABER DECLARADO EXPLÍCITAMENTE CADA BEAN TAL QUE ASÍ:
+
+ <bean id="soapFaultMappingExceptionResolver"
+ class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
+ <property name="order" value="0" />
+ </bean>
+
+ <bean id="payloadRootAnnotationMethodEndpointMapping"
+ class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
+ <property name="order" value="0" />
+ </bean>
+
+ CON LA ANOTACIÓN ME AHORRO DECLARAR bean POR bean PERO LO MALO ES QUE INSTANCIO MANEJADORES QUE LUEGO NO USO :(
+
+
+ ATENCION:
+ Solo se usa una instancia de org.springframework.oxm.jaxb.Jaxb2Marshaller que será usada por todas las llamadas (todos los hilos).
+ Es hilo seguro, por debajo usa javax.xml.bind.JAXBContext que es hilo seguro.
+ JAXBContext debe ser siempre un singleton porque la primera vez tarda mucho en inicializarse. Cada vez que se haga marshalling y unmarshalling
+ se deben crear objetos ligeros y no seguros mediante los métodos JAXBContext.createMarshaller() y JAXBContext.createUnmarshaller()
+ (esto es lo que hace Jaxb2Marshaller por nosotros) Los objetos ligeros creados son javax.xml.bind.Marshaller y javax.xml.bind.Unmarshaller
+ que no son hilo seguro y por tanto serán creados por cada petición (todo esto lo está haciendo Spring ya, así que genial)
+ -->
+
+ <!--
+ Spring makes the WSDL file for us from the XSD file.
+ Launch the Jetty server and download WSDL file from this URL:
+ http://localhost:8080/web-services-spring-jaxb2-server/spring-ws/example/example.wsdl
+ -->
+ <sws:dynamic-wsdl id="example" portTypeName="Examples"
+ createSoap12Binding="true" createSoap11Binding="false"
+ locationUri="/spring-ws/example"
+ targetNamespace="http://gumartinm.name/spring-ws/exampleService">
+ <sws:xsd location="classpath:schemas/examples.xsd"/>
+ </sws:dynamic-wsdl>
+
+
+ <!-- Required in order to use SOAP 1.2
+ id="messageFactory" is not a random choice, if you use another name it will not work
+ (Spring will end up loading SOAP 1.1)
+ -->
+ <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
+ <property name="soapVersion">
+ <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
+ </property>
+ </bean>
+
+ <!-- The interceptors in this set are automatically configured on each registered EndpointMapping
+ What means, every class annotated with @Endpoint will be using these interceptors.
+
+ This configuration enables us to log the SOAP XML Request (received from client), Response (sent by this server) and Fault (sent by this server).
+ -->
+ <sws:interceptors>
+ <bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor">
+ <property name="logRequest" value="true"/>
+ <property name="logResponse" value="true"/>
+ <property name="logFault" value="true"/>
+ </bean>
+
+ <!--
+ ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
+ del JAXB2 que estoy usando para generar las clases desde el xsd)
+ Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
+ debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
+ funciona, así que supongo el validador tambien :/
+ Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
+ -->
+ <bean id="validatingInterceptor"
+ class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
+ <property name="schemas">
+ <list>
+ <!--
+ ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
+ OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
+ EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
+
+ IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
+ EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
+ REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
+ CONFIGURATION.
+ -->
+ <value>classpath:schemas/parent.xsd</value>
+
+ <value>classpath:schemas/examples.xsd</value>
+ </list>
+ </property>
+ <property name="validateRequest" value="true"/>
+ <property name="validateResponse" value="true"/>
+ </bean>
+
+ <!-- My custom header interceptor -->
+ <bean class="de.spring.webservices.endpoints.CustomHeaderInterceptor" />
+ </sws:interceptors>
+
+
+ <!--
+ PARA METER MAS COSAS A LA RESPUESTA CON ERROR, por ejemplo si quisiéramos enviar en Reason Text la pila de excepción tengo que
+ implementar mi propio manejador de excepción que extienda de AbstractSoapFaultDefinitionExceptionResolver y añada todo aquello
+ que yo necesite.
+
+ A mí me parecen muy pobres las implementaciones que trae Spring así que implementaré el mío propio que devuelva la pila
+ de excepción si la hay.
+ -->
+ <bean id="soapFaultMappingExceptionResolver"
+ class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
+ <!--
+ No quiero usar un valor por defecto porque si no, si mi manejador no machea ninguna excepción
+ devolvera este valor por defecto. Y no se probará con otros manejadores de excepción que tengan un order con menor precedencia.
+
+ Cuando se escribe value="SERVER" Spring está seteando SoapFaultDefinition.SERVER en defaultValue
+ de org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver Esto parece
+ magia pero Spring lo logra usando org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor.setAsText("SERVER")
+
+ <property name="defaultFault" value="SERVER"/>
+ -->
+ <property name="exceptionMappings">
+ <props>
+ <!--
+ <prop key="de.spring.webservices.exceptions.BusinessException">SERVER,something went wrong in server side,en_US</prop>
+
+ Si hago esto en lugar de devolver al cliente el mensaje que va dentro de la excepcion devuelvo siempre:
+
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+ <env:Header/>
+ <env:Body>
+ <env:Fault>
+ <env:Code>
+ <env:Value>env:Receiver</env:Value> Receiver y Server significa lo mismo. Cuando pongo "SERVER" en primer token aquí aparece Receiver.
+ </env:Code>
+ <env:Reason>
+ <env:Text xml:lang="en-US">something went wrong in server side</env:Text> en-US porque puse como Locale en_US en el tercer token.
+ </env:Reason>
+ </env:Fault>
+ </env:Body>
+ </env:Envelope>
+
+ El primer token es el Value. Si es SERVER o RECEIVER se muestra Receiver. Si es CLIENT o SENDER se muestra Sender.
+
+ El segundo token es el mensaje que SIEMPRE se mostrará.
+
+ El tercer token mapea a un Locale en SoapFaultDefinition (por defecto Locale.ENGLISH). El mapeo se hace con
+ org.springframework.util.StringUtils.parseLocaleString("en_US")
+
+
+
+
+
+ Yo prefiero que se devuelva el mensaje que va dentro de la excepción. Para eso SOLO puede haber un token y
+ el Locale siempre será entonces Locale.ENGLISH.
+
+ Uso SERVER porque de.spring.webservices.exceptions.BusinessException es una excepción generada en el lado servidor.
+ -->
+ <prop key="de.spring.webservices.exceptions.BusinessException">SERVER</prop>
+ </props>
+ </property>
+ <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
+ SoapFaultAnnotationExceptionResolver
+ -->
+ <property name="order" value="1" />
+ </bean>
+
+
+
+ <bean id="myCustomMappingExceptionResolver" class="de.spring.webservices.endpoints.MyCustomMappingExceptionResolver">
+ <!--
+ Voy a usar un valor por defecto porque este va a ser el último manejador que haya antes de
+ SimpleSoapExceptionResolver. SimpleSoapExceptionResolver será siempre por el order que he puesto
+ el último manejador de excepciones.
+ Así todas las excepciones que no hayan sido macheadas por los otros manejadores serán siempre
+ cogidas por este y se les asignará un SoapFaultDefinition.SERVER. En este caso SimpleSoapExceptionResolver
+ nunca será usado.
+ -->
+ <property name="defaultFault" value="SERVER"/>
+ <property name="exceptionMappings">
+ <props>
+ <!--
+ Los errores de validacion se devuelven así:
+
+ <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
+ <env:Header/>
+ <env:Body>
+ <env:Fault>
+ <env:Code>
+ <env:Value>env:Sender</env:Value>
+ </env:Code>
+ <env:Reason>
+ <env:Text xml:lang="en">Validation error</env:Text>
+ </env:Reason>
+ <env:Detail>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
+ <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
+ </env:Detail>
+ </env:Fault>
+ </env:Body>
+ </env:Envelope>
+
+ El manejador de errores de validación es implementado por AbstractFaultCreatingValidatingInterceptor (PayloadValidatingInterceptor)
+ luego si quisiéramos devolver un mensaje de error distinto al implementado por AbstractFaultCreatingValidatingInterceptor
+ tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
+ -->
+ <prop key="de.spring.webservices.exceptions.CustomBusinessException">SERVER</prop>
+ </props>
+ </property>
+ <property name="marshaller" ref="marshaller"/>
+ <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
+ SoapFaultAnnotationExceptionResolver y SoapFaultMappingExceptionResolver
+ -->
+ <property name="order" value="2" />
+ </bean>
+
+</beans>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+ <display-name>Spring Web Services: example</display-name>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <context-param>
+ <param-name>spring.profiles.active</param-name>
+ <param-value>${environment.profile}</param-value>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>
+ classpath*:spring-configuration/*.xml
+ </param-value>
+ </context-param>
+
+ <!-- Spring SOAP servlet -->
+ <servlet>
+ <servlet-name>spring-ws</servlet-name>
+ <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ <async-supported>true</async-supported>
+ <init-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>classpath*:spring-configuration/ws/*.xml</param-value>
+ </init-param>
+ <init-param>
+ <param-name>transformWsdlLocations</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>spring-ws</servlet-name>
+ <url-pattern>/spring-ws/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import static org.springframework.ws.test.server.RequestCreators.withPayload;
+import static org.springframework.ws.test.server.ResponseMatchers.payload;
+
+import javax.xml.transform.Source;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.ws.test.server.MockWebServiceClient;
+import org.springframework.xml.transform.StringSource;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath*:spring-configuration/ws/soap-ws.xml" } )
+public class ExampleEndPointIntegrationTest {
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ private MockWebServiceClient mockClient;
+
+ @Before
+ public void createClient() {
+ mockClient = MockWebServiceClient.createClient(applicationContext);
+ }
+
+ @Test
+ public void exampleEndpoint() throws Exception {
+ final Source requestPayload = new StringSource(
+ "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
+ "<data>SCARLETT</data>" +
+ "</ExampleRequest>");
+ final Source responsePayload = new StringSource(
+ "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
+ "<ns2:data>SNAKE EYES AND SCARLETT</ns2:data>" +
+ "</ns2:ExampleResponse>");
+ mockClient.sendRequest(withPayload(requestPayload)).andExpect(
+ payload(responsePayload));
+
+
+ final Source customRequestPayload = new StringSource(
+ "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
+ "<data>SCARLETT</data>" +
+ "<exampleDate>2015-06-03T10:20:30Z</exampleDate>" +
+ "<parentEnum>FIRST</parentEnum>" +
+ "</CustomBindingExampleRequest>");
+ final Source customResponsePayload = new StringSource(
+ "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
+ "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT</ns2:data>" +
+ "<ns2:parentEnum>FIRST</ns2:parentEnum>" +
+ "</ns2:CustomBindingExampleResponse>");
+ mockClient.sendRequest(withPayload(customRequestPayload)).andExpect(
+ payload(customResponsePayload));
+ }
+}
+
--- /dev/null
+package de.spring.webservices.endpoints;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.services.ExampleService;
+
+
+public class ExampleEndPointTest {
+
+ private ExampleService exampleService;
+
+ private Operations.RequestResponse
+ <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
+
+ private ExampleEndPoint exampleEndPoint;
+
+ @Before
+ public void init() {
+ exampleService = mock(ExampleService.class);
+ customBindingExampleService = mock(Operations.RequestResponse.class);
+ exampleEndPoint = new ExampleEndPoint(customBindingExampleService, exampleService);
+ }
+
+ @Test
+ public void givenExampleRequestThenInvokeExampleService() {
+ ExampleRequest request = new ExampleRequest();
+ request.setData("SCARLETT");
+
+ exampleEndPoint.exampleResponse(request, null, null);
+
+ verify(exampleService).doResponse(request);
+ }
+
+ @Test
+ public void givenCustomBindingExampleRequestThenInvokeCustomBindingExampleService() {
+ CustomBindingExampleRequest request = new CustomBindingExampleRequest();
+ request.setData("SCARLETT");
+
+ exampleEndPoint.cuntomBindingExampleResponse(request, null, null);
+
+ verify(customBindingExampleService).requestResponse(request);
+ }
+
+}
--- /dev/null
+package de.spring.webservices.services;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.spring.webservices.operations.Operations;
+import de.spring.webservices.server.auto.CustomBindingExampleRequest;
+import de.spring.webservices.server.auto.CustomBindingExampleResponse;
+import de.spring.webservices.services.impl.CustomBindingExampleServiceImpl;
+
+
+public class CustomBindingExampleServiceTest {
+
+ private Operations.RequestResponse
+ <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
+
+ @Before
+ public void init() {
+ customBindingExampleService = new CustomBindingExampleServiceImpl();
+ }
+
+ @Test
+ public void givenCustomBindingExampleRequestThenReturnCustomBindingExampleResponse() {
+ CustomBindingExampleRequest request = new CustomBindingExampleRequest();
+ request.setData("SCARLETT");
+ CustomBindingExampleResponse expected = new CustomBindingExampleResponse();
+ expected.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
+
+ CustomBindingExampleResponse actual = customBindingExampleService.requestResponse(request);
+
+ Assert.assertEquals(expected.getData(), actual.getData());
+ }
+}
--- /dev/null
+package de.spring.webservices.services;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import de.spring.webservices.server.auto.ExampleRequest;
+import de.spring.webservices.server.auto.ExampleResponse;
+import de.spring.webservices.services.impl.ExampleServiceImpl;
+
+public class ExampleServiceTest {
+
+ private ExampleService exampleService;
+
+ @Before
+ public void init() {
+ exampleService = new ExampleServiceImpl();
+ }
+
+ @Test
+ public void givenExampleRequestThenReturnExampleResponse() {
+ ExampleRequest request = new ExampleRequest();
+ request.setData("SCARLETT");
+ ExampleResponse expected = new ExampleResponse();
+ expected.setData("SNAKE EYES AND " + request.getData());
+
+ ExampleResponse actual = exampleService.doResponse(request);
+
+ Assert.assertEquals(expected.getData(), actual.getData());
+ }
+
+}
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>de.spring.webservices</groupId>
+ <artifactId>web-services-spring-jaxb2</artifactId>
+ <packaging>pom</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <name>web-services-spring-jaxb2</name>
+ <url>http://gumartinm.name</url>
+ <description>Web Services Spring Framework</description>
+ <organization>
+ <name>Gustavo Martin Morcuende</name>
+ <url>http://www.gumartinm.name</url>
+ </organization>
+ <scm>
+ <developerConnection>scm:git:http://git.gumartinm.name/SpringWebServicesForFun</developerConnection>
+ <url>http://git.gumartinm.name/SpringWebServicesForFun</url>
+ </scm>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <!-- Be aware: spring-ws latest version does not follow spring-context
+ latest version -->
+ <spring.version>4.0.9.RELEASE</spring.version>
+ <spring.ws.version>2.2.1.RELEASE</spring.ws.version>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <properties>
+ <environment.profile>release</environment.profile>
+ </properties>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <!--
+ 1/3 Required dependency for log4j 2 with slf4j: binding between log4j 2 and slf4j
+ -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <!--
+ 2/3 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin (it is the log4j 2 implementation)
+ -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <!--
+ 3/3 Required dependency for getting rid of commons logging.
+ This is the BRIDGE (no binding) between Jakarta Commons Logging (used by Spring) and whatever
+ I am using for logging (in this case I am using log4j 2)
+ See: http://www.slf4j.org/legacy.html
+
+ We need exclusions in every dependency using Jakarta Commons Logging (see Spring dependencies below)
+ -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.12</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>2.2.2</version>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-core</artifactId>
+ <version>${spring.ws.version}</version>
+ <!--
+ Required dependency for getting rid of commons logging and use my own logging library
+ (in my case I decided to use log4j 2 under slf4j)
+ -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-xml</artifactId>
+ <version>${spring.ws.version}</version>
+ <!--
+ Required dependency for getting rid of commons logging and use my own logging library
+ (in my case I decided to use log4j 2 under slf4j)
+ -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ <version>2.0.2</version>
+ </dependency>
+
+ <!-- Required by spring-ws-core -->
+ <dependency>
+ <groupId>wsdl4j</groupId>
+ <artifactId>wsdl4j</artifactId>
+ <version>1.6.3</version>
+ </dependency>
+
+ <!-- Unitary and integration tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ws</groupId>
+ <artifactId>spring-ws-test</artifactId>
+ <version>${spring.ws.version}</version>
+ <scope>test</scope>
+ <!--
+ Required dependency for getting rid of commons logging and use my own logging library
+ (in my case I decided to use log4j 2 under slf4j)
+ -->
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.0.11-beta</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <build>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.18.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.18.1</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.3</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.7</version>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Specification-Title>${project.description}</Specification-Title>
+ <Specification-Version>${project.version}</Specification-Version>
+ <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+ <Implementation-Title>${project.description}</Implementation-Title>
+ <Implementation-Version>${project.version}</Implementation-Version>
+ <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/*IntegrationTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <includes>
+ <include>**/*IntegrationTest.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>web-services-spring-cxf</artifactId>
- <groupId>de.spring.webservices</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>web-services-spring-cxf-client</artifactId>
- <name>web-services-spring-cxf-client</name>
- <url>http://gumartinm.name</url>
-
- <properties>
- <project.wsdl.sources.path>src/main/build-resources/wsdl</project.wsdl.sources.path>
- <project.wsdl.target.path>${basedir}/target/generated-sources/src/main/java</project.wsdl.target.path>
- <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
- <!-- Requires absolute path (because of that I am using ${basedir} -->
- <project.catalogs.path>${basedir}/src/main/build-resources/catalogs</project.catalogs.path>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-xml</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jdom</groupId>
- <artifactId>jdom</artifactId>
- </dependency>
-
-
- <!-- Global types -->
- <dependency>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-cxf-globalxsds</artifactId>
- <version>${project.version}</version>
- </dependency>
-
-
- <!-- Required by spring-ws-core -->
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- </dependency>
-
- <!-- Required by jaxb2-basics as specified: http://confluence.highsource.org/display/J2B/Using+JAXB2+Basics+Plugins+with+CXF -->
- <dependency>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics-runtime</artifactId>
- <version>0.9.4</version>
- </dependency>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-test</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <resources>
- <resource>
- <directory>${basedir}/src/main/resources/</directory>
- <includes>
- <include>**/*.*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <!-- Generate code from wsdl files: We could use maven-jaxb2-plugin in
- order to generate Java classes from WSDL files but this plugin seems more
- useful so, I keep using it. Besides, it is based on Apache CXF which as well,
- uses jaxb. See: http://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html -->
- <plugin>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-codegen-plugin</artifactId>
- <version>3.1.0</version>
- <executions>
- <execution>
- <id>generate-sources-from-wsdl</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>wsdl2java</goal>
- </goals>
- <configuration>
- <fork>true</fork>
- <sourceRoot>${project.wsdl.target.path}</sourceRoot>
- <wsdlOptions>
- <wsdlOption>
- <wsdl>${project.wsdl.sources.path}/example.wsdl</wsdl>
- <bindingFiles>
- <bindingFile>${project.bindings.path}/custombinding.xjb</bindingFile>
- </bindingFiles>
- <extraargs>
- <extraarg>-xjc-Xinheritance</extraarg>
- <extraarg>-xjc-Xannotate</extraarg>
- <extraarg>-catalog</extraarg>
- <extraarg>${project.catalogs.path}/catalog.cat</extraarg>
- <extraarg>-verbose</extraarg>
- </extraargs>
- </wsdlOption>
- </wsdlOptions>
- </configuration>
- </execution>
- </executions>
- <dependencies>
- <!-- We make this plugin work with this jaxb2 version. This particular
- version let us generate inherited classes using the -Xinheritance argument.
- DO NOT FORGET: We can use <inheritance:implements> in xsd files or by means
- of custom bindings (see custombinding.xjb) This is useful when you may not
- modify xsd files because they are generated by other person or machine. -->
- <dependency>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics</artifactId>
- <version>0.9.4</version>
- </dependency>
-
- <!-- We make this plugin work with this jaxb2 version. This particular
- version let us generate annotated classes using the -Xannotate argument.
- DO NOT FORGET: We can use <annox:annotate> in xsd files or by means of custom
- bindings like I did with <inheritance:implements> (see custombinding.xjb)
- This is useful when you may not modify xsd files because they are generated
- by other person or machine. -->
- <dependency>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics-annotate</artifactId>
- <version>1.0.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <version>1.9.1</version>
- <executions>
- <execution>
- <id>add-source</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>${project.wsdl.target.path}</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<jaxws:bindings
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
- xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="xjc inheritance annox">
-
- <!--
- Perhaps it would be better to relay on the package generated automatically from WSDL
- In a real project, I guess, I should use the package generated from WSDL file...
- -->
- <jaxws:bindings
- node="wsdl:definitions">
- <jaxws:package name="de.spring.webservices.client.auto"/>
- </jaxws:bindings>
-
-
- <!--
- XSD namespace for included schema in WSDL: http://gumartinm.name/spring-ws/example
-
- I am skiping the XSD namespace for imported schema in WSDL: http://gumartinm.name/spring-ws/parent because I guess,
- there must be some way of using the already generated code in web-services-spring-globalxsds instead of generating new one
- (perhaps using maven-jaxb2-plugin with episodes)
- -->
- <jaxws:bindings
- node="wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://gumartinm.name/spring-ws/example']">
-
- <!--
- Perhaps it would be better to relay on the package generated automatically from WSDL
- In a real project, I guess, I should use the package generated from WSDL file...
- -->
- <jaxb:schemaBindings>
- <jaxb:package name="de.spring.webservices.client.auto"/>
- </jaxb:schemaBindings>
-
- <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleRequest']/xsd:complextype">
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- <annox:annotate>@java.lang.suppresswarnings({"unchecked","rawtypes"})</annox:annotate>
- </jaxb:bindings>
-
- <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleResponse']/xsd:complextype">
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- <annox:annotate>@java.lang.suppresswarnings({"unchecked","rawtypes"})</annox:annotate>
- </jaxb:bindings>
-
- <jaxb:globalBindings>
- <xjc:javaType adapter="de.spring.webservices.binders.XSDateTimeCustomBinder"
- name="java.util.Date" xmlType="xsd:dateTime" />
- </jaxb:globalBindings>
-
- </jaxws:bindings>
-
-</jaxws:bindings>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system|public" >
-
- <!--
- An XML catalog will allow us to specify real locations for our imported XML schemas.
- The XJC tool supports several different XML Catalog formats: TR9401, XCatalog, OASIS XML Catalog.
- I am using OASIS XML Catalog Format
-
- OASIS XML Catalog Format: https://www.oasis-open.org/committees/entity/specs/cs-entity-xml-catalogs-1.0.html
- TR9401: https://www.oasis-open.org/specs/a401.htm
-
-
- See: http://labs.bsb.com/2011/01/usage-of-an-xml-catalog-in-the-xmlbeans-cxf-integration/
- http://cxf.apache.org/cxf-xjc-plugin.html
- https://jaxb.java.net/2.2.4/docs/catalog.html
- -->
-
-
- <!-- I JUST NEED THIS CONFIGURATION, ANYHOW I AM WRITING ALL OF THEM -->
- <rewriteSystem systemIdStartString="http://gumartinm.name/spring-ws/parent"
- rewritePrefix="classpath:parent.xsd"/>
-
-
- <!-- THE FOLLOWING ONES ARE NOT REQUIRED EVEN IF I AM WRITING THEM -->
- <public
- publicId="http://gumartinm.name/spring-ws/parent"
- uri="classpath:parent.xsd"/>
-
-
- <system
- systemId="http://gumartinm.name/spring-ws/parent/parent.xsd"
- uri="classpath:parent.xsd"/>
-
-
- <rewriteURI uriStartString="http://gumartinm.name/spring-ws/parent"
- rewritePrefix="classpath:parent.xsd"/>
-
-</catalog>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://gumartinm.name/spring-ws/example" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://gumartinm.name/spring-ws/exampleService" targetNamespace="http://gumartinm.name/spring-ws/exampleService">
- <wsdl:types>
- <xsd:schema xmlns="http://gumartinm.name/spring-ws/example" xmlns:annox="http://annox.dev.java.net" xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:parent="http://gumartinm.name/spring-ws/parent" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" jaxb:extensionBindingPrefixes="inheritance annox" jaxb:version="2.1" targetNamespace="http://gumartinm.name/spring-ws/example">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <!--
- We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
- when creating Java objects from examples.xsd.
- -->
- <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd"/>
-
-
- <!-- Spring requires the following:
- 1. XSD elements being used as request must end with Request name.
- 2. XSD elements being used as response must end with Response name.
-
- IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
-
- ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
- the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
- The same for CustomBindingExample.
- -->
- <!-- Using inheritance and annox plugin -->
- <xsd:element name="ExampleRequest">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="parent:limitedString"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleResponse">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-
- <!-- Using custombinding.xjb instead of inheritance plugin.
- Useful when you can not modify your xsd files because they are provided
- by another person or company
- -->
- <xsd:element name="CustomBindingExampleRequest">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleResponse">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <!-- Example of creating array list by means of XSD -->
- <xsd:complexType name="car">
- <xsd:sequence>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="100" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:sequence>
- </xsd:complexType>
- <xsd:complexType name="truck">
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:all>
- </xsd:complexType>
- <xsd:element name="vehicles">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="cars" type="car"/>
- <xsd:element maxOccurs="100" minOccurs="0" name="trucks" type="truck"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
- </wsdl:types>
- <wsdl:message name="ExampleFault">
- <wsdl:part element="sch:ExampleFault" name="ExampleFault">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="CustomBindingExampleFault">
- <wsdl:part element="sch:CustomBindingExampleFault" name="CustomBindingExampleFault">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="ExampleRequest">
- <wsdl:part element="sch:ExampleRequest" name="ExampleRequest">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="ExampleResponse">
- <wsdl:part element="sch:ExampleResponse" name="ExampleResponse">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="CustomBindingExampleResponse">
- <wsdl:part element="sch:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="CustomBindingExampleRequest">
- <wsdl:part element="sch:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
- </wsdl:part>
- </wsdl:message>
- <wsdl:portType name="Examples">
- <wsdl:operation name="Example">
- <wsdl:input message="tns:ExampleRequest" name="ExampleRequest">
- </wsdl:input>
- <wsdl:output message="tns:ExampleResponse" name="ExampleResponse">
- </wsdl:output>
- <wsdl:fault message="tns:ExampleFault" name="ExampleFault">
- </wsdl:fault>
- </wsdl:operation>
- <wsdl:operation name="CustomBindingExample">
- <wsdl:input message="tns:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
- </wsdl:input>
- <wsdl:output message="tns:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
- </wsdl:output>
- <wsdl:fault message="tns:CustomBindingExampleFault" name="CustomBindingExampleFault">
- </wsdl:fault>
- </wsdl:operation>
- </wsdl:portType>
- <wsdl:binding name="ExamplesSoap12" type="tns:Examples">
- <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
- <wsdl:operation name="Example">
- <soap12:operation soapAction=""/>
- <wsdl:input name="ExampleRequest">
- <soap12:body use="literal"/>
- </wsdl:input>
- <wsdl:output name="ExampleResponse">
- <soap12:body use="literal"/>
- </wsdl:output>
- <wsdl:fault name="ExampleFault">
- <soap12:fault name="ExampleFault" use="literal"/>
- </wsdl:fault>
- </wsdl:operation>
- <wsdl:operation name="CustomBindingExample">
- <soap12:operation soapAction=""/>
- <wsdl:input name="CustomBindingExampleRequest">
- <soap12:body use="literal"/>
- </wsdl:input>
- <wsdl:output name="CustomBindingExampleResponse">
- <soap12:body use="literal"/>
- </wsdl:output>
- <wsdl:fault name="CustomBindingExampleFault">
- <soap12:fault name="CustomBindingExampleFault" use="literal"/>
- </wsdl:fault>
- </wsdl:operation>
- </wsdl:binding>
- <wsdl:service name="ExamplesService">
- <wsdl:port binding="tns:ExamplesSoap12" name="ExamplesSoap12">
- <soap12:address location="http://localhost:8080/web-services-spring-cxf-server/spring-ws/example"/>
- </wsdl:port>
- </wsdl:service>
-</wsdl:definitions>
\ No newline at end of file
+++ /dev/null
-package de.spring.webservices.client;
-
-import java.io.IOException;
-import java.util.Iterator;
-
-import javax.xml.transform.Source;
-
-// cxf-codegen-plugin DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
-// So I guess it is better to use the objects generated in this package
-// than the ones from globalxsds even if they should be the same.
-import name.gumartinm.spring_ws.parent.GeneralFault;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.oxm.Unmarshaller;
-import org.springframework.oxm.XmlMappingException;
-import org.springframework.ws.WebServiceMessage;
-import org.springframework.ws.client.core.FaultMessageResolver;
-import org.springframework.ws.soap.SoapBody;
-import org.springframework.ws.soap.SoapFault;
-import org.springframework.ws.soap.SoapFaultDetail;
-import org.springframework.ws.soap.SoapFaultDetailElement;
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
-
-/**
- * Enables us to log custom Fault remote messages.
- *
- */
-public class CustomFaultMessageResolver implements FaultMessageResolver {
-
-private static final Logger LOGGER = LoggerFactory.getLogger(CustomFaultMessageResolver.class);
-
- private final FaultMessageResolver defaultMessageResolver = new SoapFaultMessageResolver();
-
- private Unmarshaller unmarshaller;
-
- @Override
- public void resolveFault(WebServiceMessage message) throws IOException {
-
- // Same behavior as default message resolver (SoapFaultMessageResolver) but this implementation also
- // logs error information.
- if (LOGGER.isErrorEnabled()) {
- try {
- logErrorInformation(message);
- } catch (Exception ex) {
- LOGGER.error("CustomFaultMessageResolver exception:", ex);
- }
- }
-
- defaultMessageResolver.resolveFault(message);
- }
-
- private void logErrorInformation(WebServiceMessage message) throws XmlMappingException, IOException {
- SoapMessage soapMessage = (SoapMessage) message;
- SoapBody body = soapMessage.getSoapBody();
- SoapFault soapFault = body != null ? body.getFault() : null;
- SoapFaultDetail detail = soapFault != null ? soapFault.getFaultDetail() : null;
-
- if (detail != null) {
- Iterator<SoapFaultDetailElement> iterator = detail.getDetailEntries();
- while (iterator.hasNext()) {
- SoapFaultDetailElement bodyElement = iterator.next();
- Source detailSource = bodyElement.getSource();
- // TODO: How to check if I am receiving GeneralFault before trying to unmarshal?
- // Right now there will be exception if unmarshal doesn't return a GeneralFault object.
- GeneralFault error = (GeneralFault)this.unmarshaller.unmarshal(detailSource);
- LOGGER.error("TECHNICALERROR:");
- LOGGER.error(error.getTechnicalError());
- LOGGER.error("ELEMENTS:");
- error.getElements().forEach(element -> {
- LOGGER.error("MESSAGE: " + element.getMessage());
- LOGGER.error("MESSAGEARGS:");
- element.getMessageArgs().forEach(messageArg -> LOGGER.error(messageArg));
- });
- }
- }
- }
-
- public void setUnmarshaller(Unmarshaller unmarshaller) {
- this.unmarshaller = unmarshaller;
- }
-}
+++ /dev/null
-package de.spring.webservices.client;
-
-import name.gumartinm.spring_ws.parent.ParentEnumType;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.ws.client.core.WebServiceTemplate;
-
-import de.spring.webservices.client.auto.CustomBindingExampleFault_Exception;
-import de.spring.webservices.client.auto.CustomBindingExampleRequest;
-import de.spring.webservices.client.auto.CustomBindingExampleResponse;
-import de.spring.webservices.client.auto.ExampleFault_Exception;
-import de.spring.webservices.client.auto.ExampleRequest;
-import de.spring.webservices.client.auto.ExampleResponse;
-import de.spring.webservices.client.auto.Examples;
-import de.spring.webservices.client.auto.ExamplesService;
-
-/**
- * Someone could write code like this one in order to send and receive
- * information from our Web Services.
- *
- */
-@Service("exampleClientService")
-public class ExampleClientService {
- private final WebServiceTemplate webServiceTemplate;
-
- @Autowired
- public ExampleClientService(WebServiceTemplate webServiceTemplate) {
- this.webServiceTemplate = webServiceTemplate;
- }
-
- public ExampleResponse sendAndReceiveJava() throws ExampleFault_Exception {
- final ExampleRequest exampleRequest = new ExampleRequest();
- exampleRequest.setData("SCARLETT JAVA. IT IS CANON.");
-
- final Examples exampleService = new ExamplesService().getExamplesSoap12();
- final ExampleResponse exampleResponse = exampleService.example(exampleRequest);
-
- return exampleResponse;
- }
-
- public ExampleResponse sendAndReceiveSpring() {
- final ExampleRequest exampleRequest = new ExampleRequest();
- exampleRequest.setData("SCARLETT SPRING. IT IS CANON.");
-
- final ExampleResponse exampleResponse = (ExampleResponse)
- this.webServiceTemplate.marshalSendAndReceive(exampleRequest);
-
- return exampleResponse;
- }
-
- public CustomBindingExampleResponse sendAndReceiveJavaCustom() throws CustomBindingExampleFault_Exception {
- final CustomBindingExampleRequest customBindingxampleRequest =
- new CustomBindingExampleRequest();
- customBindingxampleRequest.setData("CUSTOM BINDING JAVA. SCARLETT. IT IS CANON.");
- customBindingxampleRequest.setParentEnum(ParentEnumType.FIRST);
-
- final Examples exampleService = new ExamplesService().getExamplesSoap12();
- final CustomBindingExampleResponse customBindingExampleResponse =
- exampleService.customBindingExample(customBindingxampleRequest);
-
- return customBindingExampleResponse;
- }
-
- public CustomBindingExampleResponse sendAndReceiveSpringCustom() {
- final CustomBindingExampleRequest customBindingxampleRequest =
- new CustomBindingExampleRequest();
- customBindingxampleRequest.setData("CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.");
-
- final CustomBindingExampleResponse customBindingExampleResponse =
- (CustomBindingExampleResponse) this.webServiceTemplate
- .marshalSendAndReceive(customBindingxampleRequest);
-
- return customBindingExampleResponse;
- }
-}
+++ /dev/null
-package de.spring.webservices.client;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-import de.spring.webservices.client.auto.CustomBindingExampleFault;
-import de.spring.webservices.client.auto.CustomBindingExampleResponse;
-import de.spring.webservices.client.auto.ExampleFault;
-import de.spring.webservices.client.auto.ExampleResponse;
-
-/**
- * This class is used just like a nice example about how to write and run client
- * code which will send data to and from the Web Services.
- *
- */
-public class MainTest {
- private static final Logger LOGGER = LoggerFactory.getLogger(MainTest.class);
-
- public ApplicationContext context;
-
- /**
- * @param args
- * @throws ExampleFault_Exception
- * @throws CustomBindingExampleFault_Exception
- */
- public static void main(final String[] args) {
- final MainTest test = new MainTest();
-
- test.context = new ClassPathXmlApplicationContext(
- "classpath:spring-configuration/ws/client-spring-configuration.xml");
-
- final ExampleClientService example =
- (ExampleClientService) test.context.getBean("exampleClientService");
-
- LOGGER.info("ExampleResponse Java:");
- ExampleResponse response;
- try {
- response = example.sendAndReceiveJava();
- LOGGER.info(response.getData());
- } catch (Exception e) {
- LOGGER.info("ExampleResponse Java error:", e);
- }
-
-
-
- LOGGER.info("CustomBindingExampleResponse Java:");
- CustomBindingExampleResponse customBindingResponse;
- try {
- customBindingResponse = example.sendAndReceiveJavaCustom();
- LOGGER.info(customBindingResponse.getData());
- } catch (Exception e) {
- LOGGER.info("CustomBindingExampleResponse Java error:", e);
- }
-
-
-
- LOGGER.info("ExampleResponse Spring:");
- response = example.sendAndReceiveSpring();
- LOGGER.info(response.getData());
-
-
- LOGGER.info("CustomBindingExampleResponse Spring:");
- customBindingResponse = example.sendAndReceiveSpringCustom();
- LOGGER.info(customBindingResponse.getData());
- }
-}
+++ /dev/null
-package de.spring.webservices.client.transport.http;
-
-import java.io.IOException;
-import java.net.URI;
-
-import org.springframework.http.HttpMethod;
-import org.springframework.http.client.ClientHttpRequest;
-import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.ws.transport.WebServiceConnection;
-import org.springframework.ws.transport.http.AbstractHttpWebServiceMessageSender;
-import org.springframework.ws.transport.http.ClientHttpRequestConnection;
-import org.springframework.ws.transport.http.HttpTransportConstants;
-
-
-/**
- * Based on ClientHttpRequestMessageSender from the Spring WS framework.
- *
- * <p>
- * Spring WS framework also provides implementations based on the HTTP clients by Jakarta and Apache HttpClient:
- * {@link https://hc.apache.org/httpcomponents-client-ga/} and {@link http://hc.apache.org/httpclient-3.x/}
- * </p>
- *
- * <p>
- * Four implementations for four HTTP clients:
- * <ul>
- * <li> org.springframework.ws.transport.http.ClientHttpRequestMessageSender (ClientHttpRequestFactory from the Spring framework) </li>
- * <li> org.springframework.ws.transport.http.CommonsHttpMessageSender (Jakarta implementation) </li>
- * <li> org.springframework.ws.transport.http.HttpComponentsMessageSender (Apache HttpClient) </li>
- * <li> org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
- * (org.springframework.ws.transport.http.HttpUrlConnection internal Spring framework implementation) </li>
- * </ul>
- * </p>
- */
-public class CustomHttpRequestMessageSender extends AbstractHttpWebServiceMessageSender {
- private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
-
- private final ClientHttpRequestFactory requestFactory;
-
- public CustomHttpRequestMessageSender() {
- requestFactory = new SimpleClientHttpRequestFactory();
- }
-
- @Override
- public WebServiceConnection createConnection(URI uri) throws IOException {
- ClientHttpRequest request = requestFactory.createRequest(uri, HttpMethod.POST);
- if (isAcceptGzipEncoding()) {
- request.getHeaders().add(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
- HttpTransportConstants.CONTENT_ENCODING_GZIP);
- }
-
- request.getHeaders().add(MY_CUSTOM_HEADER, "gumartinm.name");
-
- return new ClientHttpRequestConnection(request);
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:parent="http://gumartinm.name/spring-ws/parent"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="inheritance annox"
- targetNamespace="http://gumartinm.name/spring-ws/example"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <!--
- We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
- when creating Java objects from examples.xsd.
- -->
- <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
-
-
- <!-- Spring requires the following:
- 1. XSD elements being used as request must end with Request name.
- 2. XSD elements being used as response must end with Response name.
-
- IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
-
- ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
- the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
- The same for CustomBindingExample.
- -->
- <!-- Using inheritance and annox plugin -->
- <xsd:element name="ExampleRequest">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="parent:limitedString" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleResponse">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-
- <!-- Using custombinding.xjb instead of inheritance plugin.
- Useful when you can not modify your xsd files because they are provided
- by another person or company
- -->
- <xsd:element name="CustomBindingExampleRequest">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleResponse">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <!-- Example of creating array list by means of XSD -->
- <xsd:complexType name="car">
- <xsd:sequence>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- <xsd:complexType name="truck">
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- <xsd:element name="vehicles">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="cars" type="car" maxOccurs="unbounded" />
- <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- status: The level of internal Log4j events that should be logged to the console.
- Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
-
- monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
-
-
- see https://logging.apache.org/log4j/2.x/manual/configuration.html
- -->
-<Configuration status="error" strict="true" monitorInterval="30"
- name="XMLConfigTest" packages="org.apache.logging.log4j.test">
-
- <!--
- ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
-
- ERROR by default.
- -->
-
- <Appenders>
- <Appender type="Console" name="STDOUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
- </Appender>
- </Appenders>
- <Loggers>
-
-
- <!--
- Specific log when request message from this client or response message created by remote server contains validation errors.
-
- see client-spring-configuration.xml Spring configuration file.
-
- This configuration enables us to log validation errors of data sent from this client or data sent by remote server.
- -->
- <Logger name="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
- <!--
- Con esta configuración podemos loguear mensajes de error (SOAP Fault) procedentes del sevidor customizados. En mi caso
- usando GeneralFault. No se loguean los de validación (ni de envio de cliente ni de respuesta desde el servidor)
- porque esto lo hace PayloadValidatingInterceptor.
- -->
- <Logger name="de.spring.webservices.client.CustomFaultMessageResolver" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
- <!-- Specific log level for SOAP XML messages.
-
- see client-spring-configuration.xml Spring configuration file.
-
- This configuration enables us to log the SOAP XML Request (sent from this client), Response (sent by remote server) and Fault (sent by remote server).
- -->
- <Logger name="org.springframework.ws.client.MessageTracing" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
- <Logger name="org.springframework.ws.server.MessageTracing" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
- <!--
- Specific log level for Spring WS.
- -->
- <Logger name="org.springframework.ws" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- General logging Spring.
- -->
- <Logger name="org.springframework" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- Anything else will be using TRACE logging level.
- -->
- <Root level="INFO">
- <AppenderRef ref="STDOUT"/>
- </Root>
- </Loggers>
-</Configuration>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:sws="http://www.springframework.org/schema/web-services"
- xmlns:oxm="http://www.springframework.org/schema/oxm"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:util="http://www.springframework.org/schema/util"
-
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/web-services
- http://www.springframework.org/schema/web-services/web-services.xsd
- http://www.springframework.org/schema/oxm
- http://www.springframework.org/schema/oxm/spring-oxm.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
-
- <!--
- This file is an example about how someone should write code in order to send and
- receive data from the Web Services.
- -->
-
- <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Component, etc, etc) -->
- <context:component-scan base-package="de.spring.webservices"/>
-
- <!--
- Three ways of using a marshallers/unmarshallers.
-
- 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
- Esto equivale a esta configuracion en XML
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
- El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
-
- 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
- se hace de este modo:
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.auto"/>
- Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
- de especificar un context-path en concreto.
-
- 3. Especificando la implementación concreta del marshaller.
- Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
- cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
- De todos modos, probablemente habría que usar un package distinto para lo que hay
- en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
-
-
- <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
- <property name="packagesToScan" value="de.spring.webservices.auto"/>
- </bean>
-
- NO PUEDO USAR ESTA CONFIGURACION PORQUE SE PRODUCE ESTE ERROR:
-
- Caused by: org.springframework.oxm.UncategorizedMappingException: Unknown JAXB exception;
- nested exception is com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
- de.spring.webservices.auto.Examples es una interfaz y JAXB no puede manejar interfaces.
- this problem is related to the following location: at de.spring.webservices.auto.Examples
-
- at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:888)
-
- ESTE ERROR SE PRODUCE PORQUE cxf-codegen-plugin GENERA Examples QUE ES UN inteface @WebService
- maven-jaxb2-plugin NO GENERA ESTOS OBJETOS pero maven-jaxb2-plugin NO ES BUENO PARA GENERAR CLASES
- DESDE WSDLs POR LAS RAZONES EXPLICADAS EN EL pom.xml DEL PROYECTO web-services-spring-jaxb2-client.
- -->
- <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
- <!--
- contextPath because of Examples autogenerated class, which is an @Weberservice interface.
-
- cxf-codegen-plugin DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
- So we MAY NOT scan everything because there is more than one class representing
- the same XML element. :(
-
- We scan the objects generated in this package.
- -->
- <property name="contextPath" value="de.spring.webservices.client.auto:name.gumartinm.spring_ws.parent"/>
- </bean>
-
-
-
- <!-- Required in order to use SOAP 1.2
- id="messageFactory" is not a random choice, if you use another name it will not work
- (Spring will end up loading SOAP 1.1)
- -->
- <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
- <property name="soapVersion">
- <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
- </property>
- </bean>
-
-
- <!--
- ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
- del JAXB2 que estoy usando para generar las clases desde el xsd)
- Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
- debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
- funciona, así que supongo el validador tambien :/
- Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
- -->
- <bean id="payloadValidatingInterceptor"
- class="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor">
- <property name="schemas">
- <list>
- <!--
- ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
- OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
- EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
-
- IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
- EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
- REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
- CONFIGURATION.
- -->
- <value>classpath:parent.xsd</value>
-
- <value>classpath:examples.xsd</value>
- </list>
- </property>
- <property name="validateRequest" value="true"/>
- <property name="validateResponse" value="true"/>
- </bean>
-
- <!--
- Los errores de validacion se devuelven así:
-
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
- <env:Header/>
- <env:Body>
- <env:Fault>
- <env:Code>
- <env:Value>env:Sender</env:Value>
- </env:Code>
- <env:Reason>
- <env:Text xml:lang="en">Validation error</env:Text>
- </env:Reason>
- <env:Detail>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
- </env:Detail>
- </env:Fault>
- </env:Body>
- </env:Envelope>
-
- El manejador de errores de validación es implementado por AbstractValidatingInterceptor (PayloadValidatingInterceptor)
- luego si quisiéramos loguear los mensaje de error de validación de algún modo especial tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
- -->
-
- <!-- Enables us to log custom Fault remote messages. No loguea mensajes de error de validación :( -->
- <bean id="customFaultMessageResolver" class="de.spring.webservices.client.CustomFaultMessageResolver">
- <property name="unmarshaller" ref="marshaller"/>
- </bean>
-
- <!--
- WebServiceTemplate using these strategies by default (see WebServiceTemplate.properties file)
-
- org.springframework.ws.client.core.FaultMessageResolver=org.springframework.ws.soap.client.core.SoapFaultMessageResolver
- org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
- org.springframework.ws.transport.WebServiceMessageSender=org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
-
- -->
-
- <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
- <constructor-arg ref="messageFactory"/>
- <property name="marshaller" ref="marshaller" />
- <property name="unmarshaller" ref="marshaller" />
-
- <!-- For local deployments change to http://localhost:8080/web-services-spring-cxf-server/spring-ws/example -->
- <property name="defaultUri" value="http://gumartinm.name/spring-ws/example"/>
-
- <property name="interceptors">
- <list>
- <ref bean="payloadValidatingInterceptor" />
- </list>
- </property>
-
- <property name="faultMessageResolver" ref="customFaultMessageResolver" />
-
- <property name="messageSenders">
- <list>
- <bean class="de.spring.webservices.client.transport.http.CustomHttpRequestMessageSender" />
- </list>
- </property>
- </bean>
-
- <!--
- Using @Service and @Autowired
- We could use just XML configuration, or XML confirguration and @Autowired or as I am doing now @Service and @Autowired.
- <bean id="exampleClientService" class="de.spring.webservices.client.ExampleClientService">
-
- @Autowired works even using XML configuration as long as you use context:component-scan
- <property name="webServiceTemplate" ref="webServiceTemplate"/>
- </bean>
- -->
-
-</beans>
+++ /dev/null
-package de.spring.webservices.client;
-
-import static org.junit.Assert.assertEquals;
-import static org.springframework.ws.test.client.RequestMatchers.payload;
-import static org.springframework.ws.test.client.ResponseCreators.withPayload;
-
-import javax.xml.transform.Source;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.ws.client.core.WebServiceTemplate;
-import org.springframework.ws.test.client.MockWebServiceServer;
-import org.springframework.xml.transform.StringSource;
-
-import de.spring.webservices.client.auto.CustomBindingExampleResponse;
-import de.spring.webservices.client.auto.ExampleResponse;
-
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration("classpath*:spring-configuration/ws/client-spring-configuration.xml")
-public class ExampleClientServiceIntegrationTest {
-
- @Autowired
- ExampleClientService exampleClientService;
-
- @Autowired
- private WebServiceTemplate webServiceTemplate;
-
- private MockWebServiceServer mockServer;
-
- @Before
- public void createServer() throws Exception {
- mockServer = MockWebServiceServer.createServer(webServiceTemplate);
- }
-
- @Test
- public void customerClient() throws Exception {
- final Source requestPayload = new StringSource(
- "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>"
- + "<data>SCARLETT SPRING. IT IS CANON.</data>"
- + "</ExampleRequest>");
- final Source responsePayload = new StringSource(
- "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>"
- + "<ns2:data>SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>"
- + "</ns2:ExampleResponse>");
- mockServer.expect(payload(requestPayload)).andRespond(
- withPayload(responsePayload));
-
- final ExampleResponse response = exampleClientService.sendAndReceiveSpring();
-
- assertEquals(response.getData(), "SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
- mockServer.verify();
- }
-
- @Test
- public void customerCustomClient() throws Exception {
- final Source customRequestPayload = new StringSource(
- "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
- "<data>CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.</data>" +
- "</CustomBindingExampleRequest>");
- final Source customResponsePayload = new StringSource(
- "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
- "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>" +
- "</ns2:CustomBindingExampleResponse>");
- mockServer.expect(payload(customRequestPayload)).andRespond(
- withPayload(customResponsePayload));
-
- final CustomBindingExampleResponse response = exampleClientService.sendAndReceiveSpringCustom();
-
- assertEquals(response.getData(), "CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
- mockServer.verify();
- }
-}
-
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>web-services-spring-cxf</artifactId>
- <groupId>de.spring.webservices</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>web-services-spring-cxf-globalxsds</artifactId>
- <name>web-services-spring-cxf-globalxsds</name>
- <url>http://gumartinm.name</url>
-
- <properties>
- <project.xsd.schemas.source.path>src/main/resources</project.xsd.schemas.source.path>
- <project.xsd.schemas.target.path>${basedir}/target/generated-sources/src/main/java</project.xsd.schemas.target.path>
- <project.xsd.schemas.package.name>de.spring.webservices.parent.auto</project.xsd.schemas.package.name>
- <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
- </properties>
-
- <dependencies>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <resources>
- <resource>
- <directory>${basedir}/src/main/resources</directory>
- <includes>
- <include>**/*.*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <!-- Generate code from xsd files: We could use maven-jaxb2-plugin in
- order to generate Java classes from XSD files but this plugin seems more
- useful so, I keep using it. Besides, it is based on Apache CXF which as well,
- uses jaxb. See: http://cxf.apache.org/cxf-xjc-plugin.html -->
- <plugin>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-xjc-plugin</artifactId>
- <version>3.0.3</version>
- <configuration>
- <fork>true</fork>
- <extensions>
- <extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:3.0.3</extension>
- </extensions>
- </configuration>
- <executions>
- <execution>
- <id>generate-sources-from-xsd</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>xsdtojava</goal>
- </goals>
- <configuration>
- <sourceRoot>${project.xsd.schemas.target.path}</sourceRoot>
- <xsdOptions>
- <xsdOption>
- <extension>true</extension>
- <xsd>${project.xsd.schemas.source.path}/parent.xsd</xsd>
- <bindingFile>${project.bindings.path}/custombinding.xjb</bindingFile>
- <packagename>${project.xsd.schemas.package.name}</packagename>
- </xsdOption>
- </xsdOptions>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <version>1.9.1</version>
- <executions>
- <execution>
- <id>add-source</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>${project.xsd.schemas.target.path}</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="">
-
-</jaxb:bindings>
+++ /dev/null
-package de.spring.webservices.binders;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-
-
-/**
- * ATTENTION: if you are using this custombinder you will have to create custom payload
- * validators for Spring (AS FAR AS I KNOW)
- *
- */
-public class XSDateTimeCustomBinder extends XmlAdapter<String, Date> {
-
- @Override
- public Date unmarshal(final String dateTime) throws Exception {
- // X pattern just works from Java >= 1.7
- final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
- formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
-
- return formatter.parse(dateTime);
- }
-
- @Override
- public String marshal(final Date dateTime) throws Exception {
- // X pattern just works from Java >= 1.7
- final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
- formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
-
- return formatter.format(dateTime);
- }
-}
+++ /dev/null
-package de.spring.webservices.operations;
-
-/**
- * <p>
- * Operations: WSDL v1.1 and v2.0
- * </p>
- * See: <a href="http://www.w3.org/TR/wsdl#_porttypes">http://www.w3.org/TR/wsdl#_porttypes</a><br>
- * See: <a href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- */
-public interface Operations {
-
- /**
- * <p>
- * Request-response operation WSDL v1.1
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/wsdl#_request-response">http://www.w3.org
- * /TR/wsdl#_request-response</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public static interface RequestResponse<T extends Response, E extends Request> {
- T requestResponse(E request);
- }
-
- /**
- * <p>
- * One-way operation WSDL v1.1
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/wsdl#_one-way">http://www.w3.org/TR/wsdl
- * #_one-way</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public interface OneWay<E extends Request> {
- void oneWay(E request);
- }
-
- /**
- * <p>
- * Notification operation WSDL v1.1
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/wsdl#_notification">http://www.w3.org/TR
- * /wsdl#_notification</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public interface Notification<T extends Response> {
- T notification();
- }
-
- /**
- * <p>
- * In-Only message exchange pattern WSDL 2.0
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- * @param <E>
- * Describes {@link Request}
- */
- public interface InOnly<E extends Request> {
- void inOnly(E request);
- }
-
- /**
- * <p>
- * Robust In-Only message exchange pattern WSDL 2.0
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- * @param <E>
- * Describes {@link Request}
- */
- public interface RobustInOnly<E extends Request> {
- void robustInOnly(E request);
- }
-
- /**
- * <p>
- * In-Out message exchange pattern WSDL 2.0
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public interface InOut<T extends Response, E extends Request> {
- T inOut(E request);
- }
-}
\ No newline at end of file
+++ /dev/null
-package de.spring.webservices.operations;
-
-public interface Request {
-
-}
+++ /dev/null
-package de.spring.webservices.operations;
-
-public interface Response {
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsd:schema xmlns="http://gumartinm.name/spring-ws/parent"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- targetNamespace="http://gumartinm.name/spring-ws/parent">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <xsd:simpleType name="parentEnumType">
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="FIRST"/>
- <xsd:enumeration value="SECOND"/>
- <xsd:enumeration value="THIRD"/>
- <xsd:enumeration value="FOURTH"/>
- <xsd:enumeration value="FIVETH"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:simpleType name="limitedString">
- <xsd:restriction base="xsd:string">
- <xsd:maxLength value="30" />
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:complexType name="element">
- <xsd:sequence>
- <xsd:element name="message" type="xsd:string"/>
- <xsd:element name="messageArgs" type="xsd:string" minOccurs="0" maxOccurs="100"/>
- </xsd:sequence>
- </xsd:complexType>
-
- <xsd:element name="GeneralFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="technicalError" type="xsd:string" />
- <xsd:element name="elements" type="element" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>web-services-spring-cxf</artifactId>
- <groupId>de.spring.webservices</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>web-services-spring-cxf-server</artifactId>
- <packaging>war</packaging>
- <name>web-services-spring-cxf-server</name>
- <url>http://gumartinm.name</url>
-
- <properties>
- <jetty.version>9.3.0.RC0</jetty.version>
- <project.xsd.schemas.source.path>src/main/resources</project.xsd.schemas.source.path>
- <project.xsd.schemas.target.path>${basedir}/target/generated-sources/src/main/java</project.xsd.schemas.target.path>
- <project.xsd.schemas.package.name>de.spring.webservices.server.auto</project.xsd.schemas.package.name>
- <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
- <!-- Requires absolute path (because of that I am using ${basedir} -->
- <project.catalogs.path>${basedir}/src/main/build-resources/catalogs</project.catalogs.path>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-xml</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jdom</groupId>
- <artifactId>jdom</artifactId>
- </dependency>
-
-
- <!-- Global types -->
- <dependency>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-cxf-globalxsds</artifactId>
- <version>${project.version}</version>
- </dependency>
-
-
- <!-- Required by spring-ws-core -->
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- </dependency>
-
- <!-- Required by jaxb2-basics as specified: http://confluence.highsource.org/display/J2B/Using+JAXB2+Basics+Plugins+with+CXF -->
- <dependency>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics-runtime</artifactId>
- <version>0.9.4</version>
- </dependency>
-
- <!-- Required by my CustomHeaderInterceptor -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>4.0.0-b01</version>
- <scope>provided</scope>
- </dependency>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <resources>
- <resource>
- <directory>${basedir}/src/main/webapp</directory>
- <excludes>
- <exclude>**/*.*</exclude>
- </excludes>
- </resource>
- <resource>
- <directory>${basedir}/src/main/resources/</directory>
- <includes>
- <include>**/*.*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <!-- Generate code from xsd files: We could use maven-jaxb2-plugin in
- order to generate Java classes from XSD files but this plugin seems more
- useful so, I keep using it. Besides, it is based on Apache CXF which as well,
- uses jaxb. See: http://cxf.apache.org/cxf-xjc-plugin.html -->
- <plugin>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-xjc-plugin</artifactId>
- <configuration>
- <fork>true</fork>
- <extensions>
- <extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:3.0.3</extension>
- </extensions>
- </configuration>
- <executions>
- <execution>
- <id>generate-sources-from-xsd</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>xsdtojava</goal>
- </goals>
- <configuration>
- <sourceRoot>${project.xsd.schemas.target.path}</sourceRoot>
- <xsdOptions>
- <xsdOption>
- <extension>true</extension>
- <xsd>${project.xsd.schemas.source.path}/examples.xsd</xsd>
- <bindingFile>${project.bindings.path}/custombinding.xjb</bindingFile>
- <catalog>${project.catalogs.path}/catalog.cat</catalog>
- <packagename>${project.xsd.schemas.package.name}</packagename>
- <extensionArgs>
- <extraarg>-Xinheritance</extraarg>
- <extraarg>-Xannotate</extraarg>
- </extensionArgs>
- </xsdOption>
- </xsdOptions>
- </configuration>
- </execution>
- </executions>
- <dependencies>
- <!-- We make this plugin work with this jaxb2 version. This particular
- version let us generate inherited classes using the -Xinheritance argument.
- DO NOT FORGET: We can use <inheritance:implements> in xsd files or by means
- of custom bindings (see custombinding.xjb) This useful when you may not modify
- xsd files because they are generated by other person or machine. -->
- <dependency>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics</artifactId>
- <version>0.9.4</version>
- </dependency>
-
- <!-- We make this plugin work with this jaxb2 version. This particular
- version let us generate annotated classes using the -Xannotate argument.
- DO NOT FORGET: We can use <annox:annotate> in xsd files or by means of custom
- bindings like I did with <inheritance:implements> (see custombinding.xjb)
- This useful when you may not modify xsd files because they are generated
- by other person or machine. -->
- <dependency>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics-annotate</artifactId>
- <version>1.0.1</version>
- </dependency>
- </dependencies>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <version>1.9.1</version>
- <executions>
- <execution>
- <id>add-source</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>${project.xsd.schemas.target.path}</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <version>2.6</version>
- <configuration>
- <webResources>
- <resource>
- <filtering>true</filtering>
- <directory>src/main/webapp</directory>
- <includes>
- <include>WEB-INF/web.xml</include>
- </includes>
- </resource>
- </webResources>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-maven-plugin</artifactId>
- <version>${jetty.version}</version>
- <configuration>
- <jettyXml>${basedir}/src/main/jetty/jetty-http.xml</jettyXml>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="xjc inheritance annox">
-
- <!--
- Se procesa con Xpath si quieres meter expresiones regulares y cosas así en teoría dependes de Xpath
- por ejemplo esto: @name=match[.] se supone que debería funcionar pero me dice que no puede
- cambiar mas de un nodo a la vez. Puede que sea un bug de xjc que se carga las opciones de Xpath :/
- <jaxb:bindings schemaLocation="examples.xsd">
- <jaxb:bindings node="//xsd:element[@name='ExampleRequest']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </jaxb:bindings>
- <jaxb:bindings node="//xsd:element[@name='ExampleResponse']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </jaxb:bindings>
- </jaxb:bindings>
- -->
-
- <jaxb:bindings schemaLocation="../../resources/examples.xsd">
- <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleRequest']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- </jaxb:bindings>
- </jaxb:bindings>
-
-
- <jaxb:bindings schemaLocation="../../resources/examples.xsd">
- <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleResponse']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- </jaxb:bindings>
- </jaxb:bindings>
-
- <!-- The same applies to annotate. If you do not want or you may not modify your xsd files you can
- modify instead this file with your custom binding :) -->
-
- <!-- Custom xsd:dateTime adapter
- See: https://jaxb.java.net/2.2.4/docs/vendorCustomizations.html#javaType
- -->
- <jaxb:globalBindings>
- <xjc:javaType adapter="de.spring.webservices.binders.XSDateTimeCustomBinder"
- name="java.util.Date" xmlType="xsd:dateTime" />
- </jaxb:globalBindings>
-
-</jaxb:bindings>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system|public" >
-
- <!--
- An XML catalog will allow us to specify real locations for our imported XML schemas.
- The XJC tool supports several different XML Catalog formats: TR9401, XCatalog, OASIS XML Catalog.
- I am using OASIS XML Catalog Format
-
- OASIS XML Catalog Format: https://www.oasis-open.org/committees/entity/specs/cs-entity-xml-catalogs-1.0.html
- TR9401: https://www.oasis-open.org/specs/a401.htm
-
-
- See: http://labs.bsb.com/2011/01/usage-of-an-xml-catalog-in-the-xmlbeans-cxf-integration/
- http://cxf.apache.org/cxf-xjc-plugin.html
- https://jaxb.java.net/2.2.4/docs/catalog.html
- -->
-
-
- <!-- I JUST NEED THIS CONFIGURATION, ANYHOW I AM WRITING ALL OF THEM -->
- <rewriteSystem systemIdStartString="http://gumartinm.name/spring-ws/parent"
- rewritePrefix="classpath:parent.xsd"/>
-
-
- <!-- THE FOLLOWING ONES ARE NOT REQUIRED EVEN IF I AM WRITING THEM -->
- <public
- publicId="http://gumartinm.name/spring-ws/parent"
- uri="classpath:parent.xsd"/>
-
-
- <system
- systemId="http://gumartinm.name/spring-ws/parent/parent.xsd"
- uri="classpath:parent.xsd"/>
-
-
- <rewriteURI uriStartString="http://gumartinm.name/spring-ws/parent"
- rewritePrefix="classpath:parent.xsd"/>
-
-</catalog>
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.util.StringUtils;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.server.EndpointInterceptor;
-import org.springframework.ws.transport.context.TransportContext;
-import org.springframework.ws.transport.context.TransportContextHolder;
-import org.springframework.ws.transport.http.HttpServletConnection;
-
-public class CustomHeaderInterceptor implements EndpointInterceptor {
- private static final Logger LOGGER = LoggerFactory.getLogger(CustomHeaderInterceptor.class);
- private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
-
- @Override
- public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
- TransportContext transport = TransportContextHolder.getTransportContext();
-
- if (transport != null) {
- HttpServletConnection connection = (HttpServletConnection) transport.getConnection();
- HttpServletRequest headers = connection.getHttpServletRequest();
- String headerValue = headers.getHeader(MY_CUSTOM_HEADER);
-
- if (!StringUtils.isEmpty(headerValue)) {
- LOGGER.info("Custom header value: " + headerValue);
- }
- }
-
- return true;
- }
-
- @Override
- public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
- return true;
- }
-
- @Override
- public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
- return true;
- }
-
- @Override
- public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
-
- }
-
-}
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import org.jdom2.Element;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.server.endpoint.annotation.Endpoint;
-import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
-import org.springframework.ws.server.endpoint.annotation.RequestPayload;
-import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.operations.Operations.RequestResponse;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-import de.spring.webservices.services.ExampleService;
-
-
-@Endpoint
-public class ExampleEndPoint {
- private static final String NAMESPACE_URI = "http://gumartinm.name/spring-ws/example";
-
- private final Operations.RequestResponse
- <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
-
- private final ExampleService exampleService;
-
- @Autowired
- public ExampleEndPoint(
- RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService,
- ExampleService exampleService) {
- this.customBindingExampleService = customBindingExampleService;
- this.exampleService = exampleService;
- }
-
- @PayloadRoot(localPart = "ExampleRequest", namespace = NAMESPACE_URI)
- @ResponsePayload
- public ExampleResponse exampleResponse(
- @RequestPayload final ExampleRequest request,
- @RequestPayload final Element element,
- final MessageContext messageContext) {
-
- return this.exampleService.doResponse(request);
- }
-
- @PayloadRoot(localPart = "CustomBindingExampleRequest", namespace = NAMESPACE_URI)
- @ResponsePayload
- public CustomBindingExampleResponse cuntomBindingExampleResponse(
- @RequestPayload final CustomBindingExampleRequest requestObject,
- @RequestPayload final Element element,
- final MessageContext messageContext) {
-
- return this.customBindingExampleService.requestResponse(requestObject);
- }
-}
-
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.xml.transform.Result;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.oxm.Marshaller;
-import org.springframework.util.CollectionUtils;
-import org.springframework.ws.soap.SoapFault;
-import org.springframework.ws.soap.SoapFaultDetail;
-import org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver;
-import org.springframework.ws.soap.server.endpoint.SoapFaultDefinition;
-import org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor;
-
-import de.spring.webservices.exceptions.CustomBusinessException;
-import de.spring.webservices.server.auto.Element;
-import de.spring.webservices.server.auto.GeneralFault;
-
-public class MyCustomMappingExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver {
- private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomMappingExceptionResolver.class);
-
- private Marshaller marshaller;
-
- private Map<String, String> exceptionMappings = new LinkedHashMap<>();
-
- /**
- * Set the mappings between exception class names and SOAP Faults. The exception class name can be a substring, with
- * no wildcard support at present.
- *
- * <p>The values of the given properties object should use the format described in
- * {@code SoapFaultDefinitionEditor}.
- *
- * <p>Follows the same matching algorithm as {@code SimpleMappingExceptionResolver}.
- *
- * @param mappings exception patterns (can also be fully qualified class names) as keys, fault definition texts as
- * values
- * @see SoapFaultDefinitionEditor
- */
- public void setExceptionMappings(Properties mappings) {
- for (Map.Entry<Object, Object> entry : mappings.entrySet()) {
- if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
- exceptionMappings.put((String)entry.getKey(), (String)entry.getValue());
- }
- }
- }
-
- @Override
- protected SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) {
- if (!CollectionUtils.isEmpty(exceptionMappings)) {
- String definitionText = null;
- int deepest = Integer.MAX_VALUE;
- for (String exceptionMapping : exceptionMappings.keySet()) {
- int depth = getDepth(exceptionMapping, ex);
- if (depth >= 0 && depth < deepest) {
- deepest = depth;
- definitionText = exceptionMappings.get(exceptionMapping);
- }
- }
- if (definitionText != null) {
- SoapFaultDefinitionEditor editor = new SoapFaultDefinitionEditor();
- editor.setAsText(definitionText);
- return (SoapFaultDefinition) editor.getValue();
- }
- }
- return null;
- }
-
- /**
- * Return the depth to the superclass matching. {@code 0} means ex matches exactly. Returns {@code -1} if
- * there's no match. Otherwise, returns depth. Lowest depth wins.
- *
- * <p>Follows the same algorithm as RollbackRuleAttribute, and SimpleMappingExceptionResolver
- */
- protected int getDepth(String exceptionMapping, Exception ex) {
- return getDepth(exceptionMapping, ex.getClass(), 0);
- }
-
- @SuppressWarnings("unchecked")
- private int getDepth(String exceptionMapping, Class<? extends Exception> exceptionClass, int depth) {
- if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
- return depth;
- }
- if (exceptionClass.equals(Throwable.class)) {
- return -1;
- }
- return getDepth(exceptionMapping, (Class<? extends Exception>) exceptionClass.getSuperclass(), depth + 1);
- }
-
- protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
- GeneralFault customFault = new GeneralFault();
- customFault.setTechnicalError(getStackTrace(ex));
-
- Element element = buildElement(ex);
- List<Element> elements = customFault.getElements();
- elements.add(element);
-
- SoapFaultDetail detail = fault.addFaultDetail();
- Result result = detail.getResult();
- try {
- marshaller.marshal(customFault, result);
- } catch (Exception marshallEx) {
- LOGGER.error("MyCustomMappingExceptionResolver: marshaller error", marshallEx);
- }
- }
-
- public void setMarshaller(Marshaller marshaller) {
- this.marshaller = marshaller;
- }
-
- private Element buildElement(Exception ex) {
- Element element = new Element();
- element.setMessage(ex.getMessage());
-
- if (ex instanceof CustomBusinessException) {
- CustomBusinessException customEx = (CustomBusinessException) ex;
- List<String> messageArgs = element.getMessageArgs();
- List<String> argumentsEx = customEx.getArguments();
-
- for (String argumentEx: argumentsEx) {
- messageArgs.add(argumentEx);
- }
- }
-
- return element;
- }
-
- private String getStackTrace(Throwable throwable) {
- final StringWriter sw = new StringWriter();
- final PrintWriter pw = new PrintWriter(sw, true);
- throwable.printStackTrace(pw);
- return sw.getBuffer().toString();
- }
-}
+++ /dev/null
-package de.spring.webservices.exceptions;
-
-/**
- * This exception will be caught by org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
- *
- */
-public class BusinessException extends RuntimeException {
-
- private static final long serialVersionUID = -4042139454770293299L;
-
- public BusinessException() {
- super();
- }
-
- public BusinessException(String message) {
- super(message);
- }
-
- public BusinessException(String message, Throwable cause) {
- super(message, cause);
- }
-}
+++ /dev/null
-package de.spring.webservices.exceptions;
-
-import java.util.List;
-
-/**
- * This exception will be caught by de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
- *
- */
-public class CustomBusinessException extends RuntimeException {
- private final List<String> arguments;
-
- public CustomBusinessException(List<String> arguments) {
- super();
- this.arguments = arguments;
- }
-
- public CustomBusinessException(String message, List<String> arguments) {
- super(message);
-
- this.arguments = arguments;
- }
-
- public CustomBusinessException(String message, Throwable cause, List<String> arguments) {
- super(message, cause);
-
- this.arguments = arguments;
- }
-
- public List<String> getArguments() {
- return arguments;
- }
-}
+++ /dev/null
-package de.spring.webservices.services;
-
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-
-
-public interface ExampleService {
-
- public ExampleResponse doResponse(ExampleRequest request);
-
-}
+++ /dev/null
-package de.spring.webservices.services.impl;
-
-//import java.util.ArrayList;
-//import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.server.auto.ParentEnumType;
-//import de.spring.webservices.exceptions.BusinessException;
-//import de.spring.webservices.exceptions.CustomBusinessException;
-
-
-@Service("customBindingExampleService")
-public class CustomBindingExampleServiceImpl implements
- Operations.RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> {
-
-
- @Override
- public CustomBindingExampleResponse requestResponse(final CustomBindingExampleRequest request) {
-
-
- // Example about how works org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
- // see soap-ws.xml Spring configuration file.
-// throw new BusinessException("This feature has not been implemented yet.");
-
- // Example about how works de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
- // see soap-ws.xml Spring configuration file.
-// List<String> arguments = new ArrayList<>();
-// arguments.add("ARGUMENT 1");
-// arguments.add("ARGUMENT 2");
-// throw new CustomBusinessException("This feature has not been implemented yet.", arguments);
-
- CustomBindingExampleResponse response = new CustomBindingExampleResponse();
-
- response.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
- response.setParentEnum(ParentEnumType.FIRST);
-
- return response;
- }
-
-}
+++ /dev/null
-package de.spring.webservices.services.impl;
-
-import org.springframework.stereotype.Service;
-
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-import de.spring.webservices.services.ExampleService;
-
-
-@Service("exampleService")
-public class ExampleServiceImpl implements ExampleService {
-
- @Override
- public ExampleResponse doResponse(final ExampleRequest request) {
-
- ExampleResponse response = new ExampleResponse();
-
- response.setData("SNAKE EYES AND " + request.getData());
-
- return response;
- }
-
-}
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-
-<!-- ============================================================= -->
-<!-- Configure the Jetty Server instance with an ID "Server" -->
-<!-- by adding a HTTP connector. -->
-<!-- This configuration must be used in conjunction with jetty.xml -->
-<!-- ============================================================= -->
-<Configure id="Server" class="org.eclipse.jetty.server.Server">
-
- <New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
- <Set name="secureScheme">https</Set>
- <Set name="securePort">
- <Property name="jetty.secure.port" default="8443" />
- </Set>
- <Set name="outputBufferSize">32768</Set>
- <Set name="requestHeaderSize">8192</Set>
- <Set name="responseHeaderSize">8192</Set>
- <Set name="sendServerVersion">true</Set>
- <Set name="sendDateHeader">false</Set>
- <Set name="headerCacheSize">512</Set>
-
- <!-- Uncomment to enable handling of X-Forwarded- style headers
- <Call name="addCustomizer">
- <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
- </Call>
- -->
- </New>
-
-
- <!-- =========================================================== -->
- <!-- Add a HTTP Connector. -->
- <!-- Configure an o.e.j.server.ServerConnector with a single -->
- <!-- HttpConnectionFactory instance using the common httpConfig -->
- <!-- instance defined in jetty.xml -->
- <!-- -->
- <!-- Consult the javadoc of o.e.j.server.ServerConnector and -->
- <!-- o.e.j.server.HttpConnectionFactory for all configuration -->
- <!-- that may be set here. -->
- <!-- =========================================================== -->
- <Call name="addConnector">
- <Arg>
- <New class="org.eclipse.jetty.server.ServerConnector">
- <Arg name="server">
- <Ref refid="Server" />
- </Arg>
- <Arg name="factories">
- <Array type="org.eclipse.jetty.server.ConnectionFactory">
- <Item>
- <New class="org.eclipse.jetty.server.HttpConnectionFactory">
- <Arg name="config">
- <Ref refid="httpConfig" />
- </Arg>
- </New>
- </Item>
- </Array>
- </Arg>
- <Set name="host">
- <Property name="jetty.host" default="127.0.0.1"/>
- </Set>
- <Set name="port">
- <Property name="jetty.port" default="8080" />
- </Set>
- <Set name="idleTimeout">
- <Property name="http.timeout" default="30000"/>
- </Set>
- </New>
- </Arg>
- </Call>
-
-</Configure>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:parent="http://gumartinm.name/spring-ws/parent"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="inheritance annox"
- targetNamespace="http://gumartinm.name/spring-ws/example"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <!--
- We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
- when creating Java objects from examples.xsd.
- -->
- <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
-
-
- <!-- Spring requires the following:
- 1. XSD elements being used as request must end with Request name.
- 2. XSD elements being used as response must end with Response name.
-
- IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
-
- ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
- the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
- The same for CustomBindingExample.
- -->
- <!-- Using inheritance and annox plugin -->
- <xsd:element name="ExampleRequest">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="parent:limitedString" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleResponse">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-
- <!-- Using custombinding.xjb instead of inheritance plugin.
- Useful when you can not modify your xsd files because they are provided
- by another person or company
- -->
- <xsd:element name="CustomBindingExampleRequest">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleResponse">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <!-- Example of creating array list by means of XSD -->
- <xsd:complexType name="car">
- <xsd:sequence>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- <xsd:complexType name="truck">
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- <xsd:element name="vehicles">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="cars" type="car" maxOccurs="unbounded" />
- <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- status: The level of internal Log4j events that should be logged to the console.
- Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
-
- monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
-
-
- see https://logging.apache.org/log4j/2.x/manual/configuration.html
- -->
-<Configuration status="error" strict="true" monitorInterval="30"
- name="XMLConfigTest" packages="org.apache.logging.log4j.test">
-
- <!--
- ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
-
- ERROR by default.
- -->
-
- <Appenders>
- <Appender type="Console" name="STDOUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
- </Appender>
- </Appenders>
- <Loggers>
-
-
- <!--
- Specific log when request message from remote client or response message created by this server contains validation errors.
-
- see soap-ws.xml Spring configuration file.
-
- This configuration enables us to log validation errors of data sent from remote client or data created by this server.
-
- Los errores de validación se loguean aquí (tanto de validación de datos de respuesta de servidor como de datos recibidos desde cliente)
- -->
- <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!-- Specific log level for SOAP SoapEnvelopeLoggingInterceptor.
-
- see soap-ws.xml Spring configuration file.
-
- This configuration enables us to log the SOAP XML Request (received from remote client), Response (sent by this server) and Fault (sent by this server).
-
- Aquí no se loguean errores de validación.
- -->
- <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
-
- <!--
- Specific log level for Spring WS.
- -->
- <Logger name="org.springframework.ws" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- General logging Spring.
- -->
- <Logger name="org.springframework" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- Anything else will be using TRACE logging level.
- -->
- <Root level="INFO">
- <AppenderRef ref="STDOUT"/>
- </Root>
- </Loggers>
-</Configuration>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util"
-
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
-
-</beans>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:sws="http://www.springframework.org/schema/web-services"
- xmlns:util="http://www.springframework.org/schema/util"
-
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/web-services
- http://www.springframework.org/schema/web-services/web-services.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
-
- <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Endpoint, etc, etc) -->
- <context:component-scan base-package="de.spring.webservices"/>
-
- <!--
- Three ways of using a marshallers/unmarshallers.
-
- 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
- Esto equivale a esta configuracion en XML
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
- El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
-
- 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
- se hace de este modo:
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.server.auto"/>
- Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
- de especificar un context-path en concreto.
-
- 3. Especificando la implementación concreta del marshaller.
- Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
- cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
- De todos modos, probablemente habría que usar un package distinto para lo que hay
- en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
- -->
- <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
- <!--
- cxf-xjc-plugin generates again the objects in web-services-spring-cxf-globalxsds :(
- So we MAY NOT scan everything because there is more than one class representing
- the same XML element. :(
- -->
- <property name="packagesToScan" value="de.spring.webservices.server.auto"/>
- </bean>
- <!-- Searches for @PayloadRoot -->
- <sws:annotation-driven marshaller="marshaller" unmarshaller="marshaller" />
-
-
- <!--
- CONSECUENCIAS DE USAR sws:annotation-driven VER: org.springframework.ws.config.AnnotationDrivenBeanDefinitionParser
- Cuanto más bajo es el valor de order mayor es la prioridad.
-
- 1. Manejadores de excepción, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
- a) SoapFaultAnnotationExceptionResolver será el primer manejador de excepciones que se intente usar por defecto. order = 0
- b) SimpleSoapExceptionResolver será el último manejador de excepciones que se intente usar por defecto. order = Ordered.LOWEST_PRECEDENCE
- Se usará si la excepción generada no pudo ser manejada por SoapFaultAnnotationExceptionResolver (porque la excepción no fue anotada con
- @SoapFault. Este manejador se traga cualquier excepción.
-
- 2. Endpoints a buscar, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
- a) PayloadRootAnnotationMethodEndpointMapping será el primer tipo de endpoints que se buscará y que se intentará usar. order = 0
- Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a b).
- b) SoapActionAnnotationMethodEndpointMapping será el segundo tipo de endpoints que se intentará usar. order = 1
- Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a c).
- c) AnnotationActionEndpointMapping será el último tipo de endpoints que se buscará. order = 2
- Si el XML SOAP que llega no machea tampoco métodos anotado con este EndPoint se
- lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
-
-
- EN LUGAR DE USAR LA ANOTACIÓN PODRÍAMOS HABER DECLARADO EXPLÍCITAMENTE CADA BEAN TAL QUE ASÍ:
-
- <bean id="soapFaultMappingExceptionResolver"
- class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
- <property name="order" value="0" />
- </bean>
-
- <bean id="payloadRootAnnotationMethodEndpointMapping"
- class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
- <property name="order" value="0" />
- </bean>
-
- CON LA ANOTACIÓN ME AHORRO DECLARAR bean POR bean PERO LO MALO ES QUE INSTANCIO MANEJADORES QUE LUEGO NO USO :(
-
-
- ATENCION:
- Solo se usa una instancia de org.springframework.oxm.jaxb.Jaxb2Marshaller que será usada por todas las llamadas (todos los hilos).
- Es hilo seguro, por debajo usa javax.xml.bind.JAXBContext que es hilo seguro.
- JAXBContext debe ser siempre un singleton porque la primera vez tarda mucho en inicializarse. Cada vez que se haga marshalling y unmarshalling
- se deben crear objetos ligeros y no seguros mediante los métodos JAXBContext.createMarshaller() y JAXBContext.createUnmarshaller()
- (esto es lo que hace Jaxb2Marshaller por nosotros) Los objetos ligeros creados son javax.xml.bind.Marshaller y javax.xml.bind.Unmarshaller
- que no son hilo seguro y por tanto serán creados por cada petición (todo esto lo está haciendo Spring ya, así que genial)
- -->
-
- <!--
- Spring makes the WSDL file for us from the XSD file.
- Launch the Jetty server and download WSDL file from this URL:
- http://localhost:8080/web-services-spring-cxf-server/spring-ws/example/example.wsdl
- -->
- <sws:dynamic-wsdl id="example" portTypeName="Examples"
- createSoap12Binding="true" createSoap11Binding="false"
- locationUri="/spring-ws/example"
- targetNamespace="http://gumartinm.name/spring-ws/exampleService">
- <sws:xsd location="classpath:examples.xsd"/>
- </sws:dynamic-wsdl>
-
-
- <!-- Required in order to use SOAP 1.2
- id="messageFactory" is not a random choice, if you use another name it will not work
- (Spring will end up loading SOAP 1.1)
- -->
- <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
- <property name="soapVersion">
- <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
- </property>
- </bean>
-
- <!-- The interceptors in this set are automatically configured on each registered EndpointMapping
- What means, every class annotated with @Endpoint will be using these interceptors.
-
- This configuration enables us to log the SOAP XML Request (received from client), Response (sent by this server) and Fault (sent by this server).
- -->
- <sws:interceptors>
- <bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor">
- <property name="logRequest" value="true"/>
- <property name="logResponse" value="true"/>
- <property name="logFault" value="true"/>
- </bean>
-
- <!--
- ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
- del JAXB2 que estoy usando para generar las clases desde el xsd)
- Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
- debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
- funciona, así que supongo el validador tambien :/
- Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
- -->
- <bean id="validatingInterceptor"
- class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
- <property name="schemas">
- <list>
- <!--
- ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
- OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
- EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
-
- IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
- EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
- REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
- CONFIGURATION.
- -->
- <value>classpath:parent.xsd</value>
-
- <value>classpath:examples.xsd</value>
- </list>
- </property>
- <property name="validateRequest" value="true"/>
- <property name="validateResponse" value="true"/>
- </bean>
-
- <!-- My custom header interceptor -->
- <bean class="de.spring.webservices.endpoints.CustomHeaderInterceptor" />
- </sws:interceptors>
-
-
- <!--
- PARA METER MAS COSAS A LA RESPUESTA CON ERROR, por ejemplo si quisiéramos enviar en Reason Text la pila de excepción tengo que
- implementar mi propio manejador de excepción que extienda de AbstractSoapFaultDefinitionExceptionResolver y añada todo aquello
- que yo necesite.
-
- A mí me parecen muy pobres las implementaciones que trae Spring así que implementaré el mío propio que devuelva la pila
- de excepción si la hay.
- -->
- <bean id="soapFaultMappingExceptionResolver"
- class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
- <!--
- No quiero usar un valor por defecto porque si no, si mi manejador no machea ninguna excepción
- devolvera este valor por defecto. Y no se probará con otros manejadores de excepción que tengan un order con menor precedencia.
-
- Cuando se escribe value="SERVER" Spring está seteando SoapFaultDefinition.SERVER en defaultValue
- de org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver Esto parece
- magia pero Spring lo logra usando org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor.setAsText("SERVER")
-
- <property name="defaultFault" value="SERVER"/>
- -->
- <property name="exceptionMappings">
- <props>
- <!--
- <prop key="de.spring.webservices.exceptions.BusinessException">SERVER,something went wrong in server side,en_US</prop>
-
- Si hago esto en lugar de devolver al cliente el mensaje que va dentro de la excepcion devuelvo siempre:
-
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
- <env:Header/>
- <env:Body>
- <env:Fault>
- <env:Code>
- <env:Value>env:Receiver</env:Value> Receiver y Server significa lo mismo. Cuando pongo "SERVER" en primer token aquí aparece Receiver.
- </env:Code>
- <env:Reason>
- <env:Text xml:lang="en-US">something went wrong in server side</env:Text> en-US porque puse como Locale en_US en el tercer token.
- </env:Reason>
- </env:Fault>
- </env:Body>
- </env:Envelope>
-
- El primer token es el Value. Si es SERVER o RECEIVER se muestra Receiver. Si es CLIENT o SENDER se muestra Sender.
-
- El segundo token es el mensaje que SIEMPRE se mostrará.
-
- El tercer token mapea a un Locale en SoapFaultDefinition (por defecto Locale.ENGLISH). El mapeo se hace con
- org.springframework.util.StringUtils.parseLocaleString("en_US")
-
-
-
-
-
- Yo prefiero que se devuelva el mensaje que va dentro de la excepción. Para eso SOLO puede haber un token y
- el Locale siempre será entonces Locale.ENGLISH.
-
- Uso SERVER porque de.spring.webservices.exceptions.BusinessException es una excepción generada en el lado servidor.
- -->
- <prop key="de.spring.webservices.exceptions.BusinessException">SERVER</prop>
- </props>
- </property>
- <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
- SoapFaultAnnotationExceptionResolver
- -->
- <property name="order" value="1" />
- </bean>
-
-
-
- <bean id="myCustomMappingExceptionResolver" class="de.spring.webservices.endpoints.MyCustomMappingExceptionResolver">
- <!--
- Voy a usar un valor por defecto porque este va a ser el último manejador que haya antes de
- SimpleSoapExceptionResolver. SimpleSoapExceptionResolver será siempre por el order que he puesto
- el último manejador de excepciones.
- Así todas las excepciones que no hayan sido macheadas por los otros manejadores serán siempre
- cogidas por este y se les asignará un SoapFaultDefinition.SERVER. En este caso SimpleSoapExceptionResolver
- nunca será usado.
- -->
- <property name="defaultFault" value="SERVER"/>
- <property name="exceptionMappings">
- <props>
- <!--
- Los errores de validacion se devuelven así:
-
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
- <env:Header/>
- <env:Body>
- <env:Fault>
- <env:Code>
- <env:Value>env:Sender</env:Value>
- </env:Code>
- <env:Reason>
- <env:Text xml:lang="en">Validation error</env:Text>
- </env:Reason>
- <env:Detail>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
- </env:Detail>
- </env:Fault>
- </env:Body>
- </env:Envelope>
-
- El manejador de errores de validación es implementado por AbstractFaultCreatingValidatingInterceptor (PayloadValidatingInterceptor)
- luego si quisiéramos devolver un mensaje de error distinto al implementado por AbstractFaultCreatingValidatingInterceptor
- tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
- -->
- <prop key="de.spring.webservices.exceptions.CustomBusinessException">SERVER</prop>
- </props>
- </property>
- <property name="marshaller" ref="marshaller"/>
- <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
- SoapFaultAnnotationExceptionResolver y SoapFaultMappingExceptionResolver
- -->
- <property name="order" value="2" />
- </bean>
-
-</beans>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
-
- <display-name>Spring Web Services: example</display-name>
-
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
-
- <context-param>
- <param-name>spring.profiles.active</param-name>
- <param-value>${environment.profile}</param-value>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath*:spring-configuration/*.xml
- </param-value>
- </context-param>
-
- <!-- Spring SOAP servlet -->
- <servlet>
- <servlet-name>spring-ws</servlet-name>
- <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- <async-supported>true</async-supported>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath*:spring-configuration/ws/*.xml</param-value>
- </init-param>
- <init-param>
- <param-name>transformWsdlLocations</param-name>
- <param-value>true</param-value>
- </init-param>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>spring-ws</servlet-name>
- <url-pattern>/spring-ws/*</url-pattern>
- </servlet-mapping>
-
-</web-app>
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import static org.springframework.ws.test.server.RequestCreators.withPayload;
-import static org.springframework.ws.test.server.ResponseMatchers.payload;
-
-import javax.xml.transform.Source;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.ws.test.server.MockWebServiceClient;
-import org.springframework.xml.transform.StringSource;
-
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = { "classpath*:spring-configuration/ws/soap-ws.xml" } )
-public class ExampleEndPointIntegrationTest {
-
- @Autowired
- private ApplicationContext applicationContext;
-
- private MockWebServiceClient mockClient;
-
- @Before
- public void createClient() {
- mockClient = MockWebServiceClient.createClient(applicationContext);
- }
-
- @Test
- public void exampleEndpoint() throws Exception {
- final Source requestPayload = new StringSource(
- "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
- "<data>SCARLETT</data>" +
- "</ExampleRequest>");
- final Source responsePayload = new StringSource(
- "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
- "<ns2:data>SNAKE EYES AND SCARLETT</ns2:data>" +
- "</ns2:ExampleResponse>");
- mockClient.sendRequest(withPayload(requestPayload)).andExpect(
- payload(responsePayload));
-
-
- final Source customRequestPayload = new StringSource(
- "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
- "<data>SCARLETT</data>" +
- "<exampleDate>2015-06-03T10:20:30Z</exampleDate>" +
- "<parentEnum>FIRST</parentEnum>" +
- "</CustomBindingExampleRequest>");
- final Source customResponsePayload = new StringSource(
- "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
- "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT</ns2:data>" +
- "<ns2:parentEnum>FIRST</ns2:parentEnum>" +
- "</ns2:CustomBindingExampleResponse>");
- mockClient.sendRequest(withPayload(customRequestPayload)).andExpect(
- payload(customResponsePayload));
- }
-}
-
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.services.ExampleService;
-
-
-public class ExampleEndPointTest {
-
- private ExampleService exampleService;
-
- private Operations.RequestResponse
- <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
-
- private ExampleEndPoint exampleEndPoint;
-
- @Before
- public void init() {
- exampleService = mock(ExampleService.class);
- customBindingExampleService = mock(Operations.RequestResponse.class);
- exampleEndPoint = new ExampleEndPoint(customBindingExampleService, exampleService);
- }
-
- @Test
- public void givenExampleRequestThenInvokeExampleService() {
- ExampleRequest request = new ExampleRequest();
- request.setData("SCARLETT");
-
- exampleEndPoint.exampleResponse(request, null, null);
-
- verify(exampleService).doResponse(request);
- }
-
- @Test
- public void givenCustomBindingExampleRequestThenInvokeCustomBindingExampleService() {
- CustomBindingExampleRequest request = new CustomBindingExampleRequest();
- request.setData("SCARLETT");
-
- exampleEndPoint.cuntomBindingExampleResponse(request, null, null);
-
- verify(customBindingExampleService).requestResponse(request);
- }
-
-}
+++ /dev/null
-package de.spring.webservices.services;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.services.impl.CustomBindingExampleServiceImpl;
-
-
-public class CustomBindingExampleServiceTest {
-
- private Operations.RequestResponse
- <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
-
- @Before
- public void init() {
- customBindingExampleService = new CustomBindingExampleServiceImpl();
- }
-
- @Test
- public void givenCustomBindingExampleRequestThenReturnCustomBindingExampleResponse() {
- CustomBindingExampleRequest request = new CustomBindingExampleRequest();
- request.setData("SCARLETT");
- CustomBindingExampleResponse expected = new CustomBindingExampleResponse();
- expected.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
-
- CustomBindingExampleResponse actual = customBindingExampleService.requestResponse(request);
-
- Assert.assertEquals(expected.getData(), actual.getData());
- }
-}
+++ /dev/null
-package de.spring.webservices.services;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-import de.spring.webservices.services.impl.ExampleServiceImpl;
-
-public class ExampleServiceTest {
-
- private ExampleService exampleService;
-
- @Before
- public void init() {
- exampleService = new ExampleServiceImpl();
- }
-
- @Test
- public void givenExampleRequestThenReturnExampleResponse() {
- ExampleRequest request = new ExampleRequest();
- request.setData("SCARLETT");
- ExampleResponse expected = new ExampleResponse();
- expected.setData("SNAKE EYES AND " + request.getData());
-
- ExampleResponse actual = exampleService.doResponse(request);
-
- Assert.assertEquals(expected.getData(), actual.getData());
- }
-
-}
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-cxf</artifactId>
- <packaging>pom</packaging>
- <version>1.0-SNAPSHOT</version>
- <name>web-services-spring-cxf</name>
- <url>http://gumartinm.name</url>
- <description>Web Services Spring Framework</description>
- <organization>
- <name>Gustavo Martin Morcuende</name>
- <url>http://www.gumartinm.name</url>
- </organization>
- <scm>
- <developerConnection>scm:git:http://git.gumartinm.name/SpringWebServicesForFun</developerConnection>
- <url>http://git.gumartinm.name/SpringWebServicesForFun</url>
- </scm>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <!-- Be aware: spring-ws latest version does not follow spring-context
- latest version -->
- <spring.version>4.0.9.RELEASE</spring.version>
- <spring.ws.version>2.2.1.RELEASE</spring.ws.version>
- </properties>
-
- <profiles>
- <profile>
- <id>release</id>
- <properties>
- <environment.profile>release</environment.profile>
- </properties>
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
- </profile>
- </profiles>
-
- <dependencies>
- <!--
- 1/3 Required dependency for log4j 2 with slf4j: binding between log4j 2 and slf4j
- -->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- <version>2.3</version>
- </dependency>
- <!--
- 2/3 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin (it is the log4j 2 implementation)
- -->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.3</version>
- </dependency>
- <!--
- 3/3 Required dependency for getting rid of commons logging.
- This is the BRIDGE (no binding) between Jakarta Commons Logging (used by Spring) and whatever
- I am using for logging (in this case I am using log4j 2)
- See: http://www.slf4j.org/legacy.html
-
- We need exclusions in every dependency using Jakarta Commons Logging (see Spring dependencies below)
- -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib</artifactId>
- <version>2.2.2</version>
- </dependency>
- </dependencies>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-core</artifactId>
- <version>${spring.ws.version}</version>
- <!--
- Required dependency for getting rid of commons logging and use my own logging library
- (in my case I decided to use log4j 2 under slf4j)
- -->
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-xml</artifactId>
- <version>${spring.ws.version}</version>
- <!--
- Required dependency for getting rid of commons logging and use my own logging library
- (in my case I decided to use log4j 2 under slf4j)
- -->
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.jdom</groupId>
- <artifactId>jdom</artifactId>
- <version>2.0.2</version>
- </dependency>
-
- <!-- Required by spring-ws-core -->
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- <version>1.6.3</version>
- </dependency>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>${spring.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-test</artifactId>
- <version>${spring.ws.version}</version>
- <scope>test</scope>
- <!--
- Required dependency for getting rid of commons logging and use my own logging library
- (in my case I decided to use log4j 2 under slf4j)
- -->
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>2.0.11-beta</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <build>
-
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.18.1</version>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-failsafe-plugin</artifactId>
- <version>2.18.1</version>
- </plugin>
- </plugins>
- </pluginManagement>
-
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.3</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- <encoding>${project.build.sourceEncoding}</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <version>2.7</version>
- <configuration>
- <encoding>${project.build.sourceEncoding}</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.4</version>
- <configuration>
- <archive>
- <manifestEntries>
- <Specification-Title>${project.description}</Specification-Title>
- <Specification-Version>${project.version}</Specification-Version>
- <Specification-Vendor>${project.organization.name}</Specification-Vendor>
- <Implementation-Title>${project.description}</Implementation-Title>
- <Implementation-Version>${project.version}</Implementation-Version>
- <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
- </manifestEntries>
- </archive>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>**/*IntegrationTest.java</exclude>
- </excludes>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-failsafe-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>integration-test</goal>
- <goal>verify</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <includes>
- <include>**/*IntegrationTest.java</include>
- </includes>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>web-services-spring-jaxb2</artifactId>
- <groupId>de.spring.webservices</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>web-services-spring-jaxb2-client</artifactId>
- <name>web-services-spring-jaxb2-client</name>
- <url>http://gumartinm.name</url>
-
- <properties>
- <project.xsd.schemas.source.path>src/main/build-resources/wsdl</project.xsd.schemas.source.path>
- <project.xsd.schemas.target.path>${project.build.directory}/generated-sources/src/main/java</project.xsd.schemas.target.path>
- <project.xsd.schemas.package.name>de.spring.webservices.client.auto</project.xsd.schemas.package.name>
- <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-xml</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jdom</groupId>
- <artifactId>jdom</artifactId>
- </dependency>
-
-
- <!-- Global types -->
- <dependency>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
- <version>${project.version}</version>
- </dependency>
-
-
- <!-- Required by spring-ws-core -->
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- </dependency>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <resources>
- <resource>
- <directory>${basedir}/src/main/resources/</directory>
- <includes>
- <include>**/*.*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.jvnet.jaxb2.maven2</groupId>
- <artifactId>maven-jaxb2-plugin</artifactId>
- <version>0.13.1</version>
- <executions>
- <execution>
- <id>generate-sources-from-xsd</id>
- <goals>
- <goal>generate</goal>
- </goals>
- <phase>generate-sources</phase>
- </execution>
- </executions>
- <configuration>
- <!-- REQUIRED FOR USING THIS PLUGIN WITH WSDL FILES!!!!! -->
- <schemaLanguage>WSDL</schemaLanguage>
- <schemaDirectory>${project.xsd.schemas.source.path}</schemaDirectory>
- <schemaIncludes>
- <include>*.wsdl</include>
- </schemaIncludes>
-
-
- <!--
- GRANDES DIFERENCIAS:
-
- :( CON ESTE PLUGIN A DIFERENCIA DE cxf-codegen-plugin NO SE PUEDEN USAR BINDINGS PARA WSDL
- LLAMADOS jaxws:bindings :( ESTO PUEDE SER UN PROBLEMA SI SE QUIERE MODIFICAR EL WSDL PROPORCIONADO
- POR ALGUIEN SIN TENER QUE EDITARLO :( POR EJEMPLO, AQUÍ YA NO PUEDO METER MI XSDateTimeCustomBinder
- SIN EDITAR EL WSDL :(
-
- :( CON ESTE PLUGIN AL IGUAL QUE CON cxf-codegen-plugin SE VUELVEN A GENERAR LOS OBJETOS DE parent.xsd
- QUE SE ENCONTRABAN EN web-services-spring-jaxb2-globalxsds
-
- :( CON ESTE PLUGIN NO CONSIGO GENERAR LAS CLASES @WebService, @WebServiceClient y @WebEndpoint
- CON cxf-codegen-plugin SÍ PUEDO :( VER ExamplesService EN web-services-spring-cxf-client
-
- CONCLUSION: ESTE PLUGIN PARA WSDLs ES PEOR QUE cxf-codegen-plugin
-
- ¡¡¡¡¡PARA WSDLs MEJOR USAR cxf-codegen-plugin!!!!!
- -->
-
- <!-- DOESN'T WORK FOR WSDL FILES!!!!
- Specifies the binding directory, default to the schemaDirectory
- <bindingDirectory>${project.bindings.path}</bindingDirectory>
- -->
- <!-- Do not scan for *.xjb files in dependencies -->
- <scanDependenciesForBindings>false</scanDependenciesForBindings>
-
- <!-- Target directory for the generated code, target/generated-sources/xjc
- by default. -->
- <generateDirectory>${project.xsd.schemas.target.path}</generateDirectory>
-
- <!-- The generated classes will all be placed under this Java package
- (XJC's -p option), unless otherwise specified in the schemas. If left unspecified,
- the package will be derived from the schemas only. -->
- <generatePackage>${project.xsd.schemas.package.name}</generatePackage>
-
- <!-- I don't think I need the next two options because mvn clean should
- make the trick, anyhow, I am using them. If true, the generateDirectory will
- be deleted before the XJC binding compiler recompiles the source files. Default
- is false. -->
- <removeOldOutput>true</removeOldOutput>
- <!-- If true (default), package directories will be cleaned before the
- XJC binding compiler generates the source files. -->
- <cleanPackageDirectories>true</cleanPackageDirectories>
-
- <!-- Encoding for the generated sources, defaults to ${project.build.sourceEncoding}. -->
- <encoding>${project.build.sourceEncoding}</encoding>
-
- <!-- Locale used during generation, for instance en, de, fr etc. This
- will, for instance, influence the language of the generated JavaDoc comments. -->
- <locale>en</locale>
-
- <!-- This nice configuration avoids to use build-helper-maven-plugin -->
- <addCompileSourceRoot>true</addCompileSourceRoot>
- <addTestCompileSourceRoot>false</addTestCompileSourceRoot>
-
- <!-- If true (default), XJC will perform strict validation of the input
- schema. If strict is set to false XJC will be run with -nv, this disables
- strict validation of schemas.
-
- The plugin is configured to use catalogs and strict mode at the
- same time. Using catalogs to resolve schema URIs in strict mode is known
- to be problematic and may fail. Please refer to the following link for more
- information: https://github.com/highsource/maven-jaxb2-plugin/wiki/Catalogs-in-Strict-Mode
- Consider setting <strict>false</strict> in your plugin configuration. -->
- <strict>false</strict>
-
- <verbose>true</verbose>
-
- <extension>true</extension>
- <args>
- <arg>-Xinheritance</arg>
- <arg>-Xannotate</arg>
- </args>
- <plugins>
- <plugin>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics</artifactId>
- <version>0.9.5</version>
- </plugin>
- <plugin>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics-annotate</artifactId>
- <version>1.0.2</version>
- </plugin>
- </plugins>
-
- <!-- Avoids the annoying SCD "x-schema::tns" didn't match any schema component errors. -->
- <addIfExistsToEpisodeSchemaBindings>true</addIfExistsToEpisodeSchemaBindings>
-
- <!--
- :( CON ESTE PLUGIN COMO CON cxf-xjc-plugin SE VUELVEN A GENERAR LOS OBJETOS DE parent.xsd
- QUE SE ENCONTRABAN EN web-services-spring-jaxb2-globalxsds
-
- ESTE PLUGIN PARA WSDLs SE COMPORTA COMO cxf-xjc-plugin EN CUANTO A QUE GENERA
- OTRA VEZ LOS OBJETOS QUE YA ESTÁN EN web-services-spring-jaxb2-globalxsds :(
- -->
-
- <!-- You can use the useDependenciesAsEpisodes instead of configuring
- individual episodes. In this case all the dependencies will be treated as
- episodes which is very convenient (less configuration). I am going to use
- the long way (individual episodes) -->
- <useDependenciesAsEpisodes>false</useDependenciesAsEpisodes>
- <catalog>src/main/build-resources/catalogs/catalog.cat</catalog>
- <episodes>
- <episode>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
- </episode>
- </episodes>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-
-
-REWRITE_SYSTEM "http://gumartinm.name/spring-ws/parent/parent.xsd" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
-
---
- This configuration is better (it relies on namespace instead of schemaLocation) but it doesn't work
- because of this bug: https://java.net/jira/browse/JAXB-942
-
- PUBLIC "xmlns:parent" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
-
---
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://gumartinm.name/spring-ws/example" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://gumartinm.name/spring-ws/exampleService" targetNamespace="http://gumartinm.name/spring-ws/exampleService">
- <wsdl:types>
- <xsd:schema xmlns="http://gumartinm.name/spring-ws/example" xmlns:annox="http://annox.dev.java.net" xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:parent="http://gumartinm.name/spring-ws/parent" xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified" jaxb:extensionBindingPrefixes="inheritance annox" jaxb:version="2.1" targetNamespace="http://gumartinm.name/spring-ws/example">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <!--
- We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
- when creating Java objects from examples.xsd.
- -->
- <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd"/>
-
-
- <!-- Spring requires the following:
- 1. XSD elements being used as request must end with Request name.
- 2. XSD elements being used as response must end with Response name.
-
- IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
-
- ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
- the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
- The same for CustomBindingExample.
- -->
- <!-- Using inheritance and annox plugin -->
- <xsd:element name="ExampleRequest">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="parent:limitedString"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleResponse">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-
- <!-- Using custombinding.xjb instead of inheritance plugin.
- Useful when you can not modify your xsd files because they are provided
- by another person or company
- -->
- <xsd:element name="CustomBindingExampleRequest">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleResponse">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="exampleDate" type="xsd:dateTime"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <!-- Example of creating array list by means of XSD -->
- <xsd:complexType name="car">
- <xsd:sequence>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="100" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:sequence>
- </xsd:complexType>
- <xsd:complexType name="truck">
- <xsd:all>
- <xsd:element name="data" type="xsd:string"/>
- <xsd:element maxOccurs="1" minOccurs="0" name="parentEnum" type="parent:parentEnumType"/>
- </xsd:all>
- </xsd:complexType>
- <xsd:element name="vehicles">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" name="cars" type="car"/>
- <xsd:element maxOccurs="100" minOccurs="0" name="trucks" type="truck"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
- </wsdl:types>
- <wsdl:message name="ExampleFault">
- <wsdl:part element="sch:ExampleFault" name="ExampleFault">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="CustomBindingExampleFault">
- <wsdl:part element="sch:CustomBindingExampleFault" name="CustomBindingExampleFault">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="ExampleRequest">
- <wsdl:part element="sch:ExampleRequest" name="ExampleRequest">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="ExampleResponse">
- <wsdl:part element="sch:ExampleResponse" name="ExampleResponse">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="CustomBindingExampleResponse">
- <wsdl:part element="sch:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
- </wsdl:part>
- </wsdl:message>
- <wsdl:message name="CustomBindingExampleRequest">
- <wsdl:part element="sch:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
- </wsdl:part>
- </wsdl:message>
- <wsdl:portType name="Examples">
- <wsdl:operation name="Example">
- <wsdl:input message="tns:ExampleRequest" name="ExampleRequest">
- </wsdl:input>
- <wsdl:output message="tns:ExampleResponse" name="ExampleResponse">
- </wsdl:output>
- <wsdl:fault message="tns:ExampleFault" name="ExampleFault">
- </wsdl:fault>
- </wsdl:operation>
- <wsdl:operation name="CustomBindingExample">
- <wsdl:input message="tns:CustomBindingExampleRequest" name="CustomBindingExampleRequest">
- </wsdl:input>
- <wsdl:output message="tns:CustomBindingExampleResponse" name="CustomBindingExampleResponse">
- </wsdl:output>
- <wsdl:fault message="tns:CustomBindingExampleFault" name="CustomBindingExampleFault">
- </wsdl:fault>
- </wsdl:operation>
- </wsdl:portType>
- <wsdl:binding name="ExamplesSoap12" type="tns:Examples">
- <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
- <wsdl:operation name="Example">
- <soap12:operation soapAction=""/>
- <wsdl:input name="ExampleRequest">
- <soap12:body use="literal"/>
- </wsdl:input>
- <wsdl:output name="ExampleResponse">
- <soap12:body use="literal"/>
- </wsdl:output>
- <wsdl:fault name="ExampleFault">
- <soap12:fault name="ExampleFault" use="literal"/>
- </wsdl:fault>
- </wsdl:operation>
- <wsdl:operation name="CustomBindingExample">
- <soap12:operation soapAction=""/>
- <wsdl:input name="CustomBindingExampleRequest">
- <soap12:body use="literal"/>
- </wsdl:input>
- <wsdl:output name="CustomBindingExampleResponse">
- <soap12:body use="literal"/>
- </wsdl:output>
- <wsdl:fault name="CustomBindingExampleFault">
- <soap12:fault name="CustomBindingExampleFault" use="literal"/>
- </wsdl:fault>
- </wsdl:operation>
- </wsdl:binding>
- <wsdl:service name="ExamplesService">
- <wsdl:port binding="tns:ExamplesSoap12" name="ExamplesSoap12">
- <soap12:address location="http://localhost:8080/web-services-spring-jaxb2-server/spring-ws/example"/>
- </wsdl:port>
- </wsdl:service>
-</wsdl:definitions>
\ No newline at end of file
+++ /dev/null
-package de.spring.webservices.client;
-
-import java.io.IOException;
-import java.util.Iterator;
-
-import javax.xml.transform.Source;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.oxm.Unmarshaller;
-import org.springframework.oxm.XmlMappingException;
-import org.springframework.ws.WebServiceMessage;
-import org.springframework.ws.client.core.FaultMessageResolver;
-import org.springframework.ws.soap.SoapBody;
-import org.springframework.ws.soap.SoapFault;
-import org.springframework.ws.soap.SoapFaultDetail;
-import org.springframework.ws.soap.SoapFaultDetailElement;
-import org.springframework.ws.soap.SoapMessage;
-import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
-
-// maven-jaxb2-plugin for WSDL DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
-// So I guess it is better to use the objects generated in this package
-// than the ones from globalxsds even if they should be the same.
-import de.spring.webservices.client.auto.GeneralFault;
-
-/**
- * Enables us to log custom Fault remote messages.
- *
- */
-public class CustomFaultMessageResolver implements FaultMessageResolver {
-
-private static final Logger LOGGER = LoggerFactory.getLogger(CustomFaultMessageResolver.class);
-
- private final FaultMessageResolver defaultMessageResolver = new SoapFaultMessageResolver();
-
- private Unmarshaller unmarshaller;
-
- @Override
- public void resolveFault(WebServiceMessage message) throws IOException {
-
- // Same behavior as default message resolver (SoapFaultMessageResolver) but this implementation also
- // logs error information.
- if (LOGGER.isErrorEnabled()) {
- try {
- logErrorInformation(message);
- } catch (Exception ex) {
- LOGGER.error("CustomFaultMessageResolver exception:", ex);
- }
- }
-
- defaultMessageResolver.resolveFault(message);
- }
-
- private void logErrorInformation(WebServiceMessage message) throws XmlMappingException, IOException {
- SoapMessage soapMessage = (SoapMessage) message;
- SoapBody body = soapMessage.getSoapBody();
- SoapFault soapFault = body != null ? body.getFault() : null;
- SoapFaultDetail detail = soapFault != null ? soapFault.getFaultDetail() : null;
-
- if (detail != null) {
- Iterator<SoapFaultDetailElement> iterator = detail.getDetailEntries();
- while (iterator.hasNext()) {
- SoapFaultDetailElement bodyElement = iterator.next();
- Source detailSource = bodyElement.getSource();
- // TODO: How to check if I am receiving GeneralFault before trying to unmarshal?
- // Right now there will be exception if unmarshal doesn't return a GeneralFault object.
- GeneralFault error = (GeneralFault)this.unmarshaller.unmarshal(detailSource);
- LOGGER.error("TECHNICALERROR:");
- LOGGER.error(error.getTechnicalError());
- LOGGER.error("ELEMENTS:");
- error.getElements().forEach(element -> {
- LOGGER.error("MESSAGE: " + element.getMessage());
- LOGGER.error("MESSAGEARGS:");
- element.getMessageArgs().forEach(messageArg -> LOGGER.error(messageArg));
- });
- }
- }
- }
-
- public void setUnmarshaller(Unmarshaller unmarshaller) {
- this.unmarshaller = unmarshaller;
- }
-}
+++ /dev/null
-package de.spring.webservices.client;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.ws.client.core.WebServiceTemplate;
-
-import de.spring.webservices.client.auto.CustomBindingExampleRequest;
-import de.spring.webservices.client.auto.CustomBindingExampleResponse;
-import de.spring.webservices.client.auto.ExampleRequest;
-import de.spring.webservices.client.auto.ExampleResponse;
-//import de.spring.webservices.client.auto.Examples;
-//import de.spring.webservices.client.auto.ExamplesService;
-//import de.spring.webservices.client.auto.ParentEnumType;
-
-/**
- * Someone could write code like this one in order to send and receive
- * information from our Web Services.
- *
- */
-@Service("exampleClientService")
-public class ExampleClientService {
- private final WebServiceTemplate webServiceTemplate;
-
- @Autowired
- public ExampleClientService(WebServiceTemplate webServiceTemplate) {
- this.webServiceTemplate = webServiceTemplate;
- }
-
-// maven-jaxb2-plugin DOESN'T CREATE @WebService, @WebServiceClient y @WebEndpoint
-// public ExampleResponse sendAndReceiveJava() {
-// final ExampleRequest exampleRequest = new ExampleRequest();
-// exampleRequest.setData("SCARLETT JAVA. IT IS CANON.");
-//
-// final Examples exampleService = new ExamplesService().getExamplesSoap12();
-// final ExampleResponse exampleResponse = exampleService.example(exampleRequest);
-//
-// return exampleResponse;
-// }
-
- public ExampleResponse sendAndReceiveSpring() {
- final ExampleRequest exampleRequest = new ExampleRequest();
- exampleRequest.setData("SCARLETT SPRING. IT IS CANON.");
-
- final ExampleResponse exampleResponse = (ExampleResponse)
- this.webServiceTemplate.marshalSendAndReceive(exampleRequest);
-
- return exampleResponse;
- }
-
-// maven-jaxb2-plugin DOESN'T CREATE @WebService, @WebServiceClient y @WebEndpoint
-// public CustomBindingExampleResponse sendAndReceiveJavaCustom() {
-// final CustomBindingExampleRequest customBindingxampleRequest =
-// new CustomBindingExampleRequest();
-// customBindingxampleRequest.setData("CUSTOM BINDING JAVA. SCARLETT. IT IS CANON.");
-// customBindingxampleRequest.setParentEnum(ParentEnumType.FIRST);
-//
-// final Examples exampleService = new ExamplesService().getExamplesSoap12();
-// final CustomBindingExampleResponse customBindingExampleResponse =
-// exampleService.customBindingExample(customBindingxampleRequest);
-//
-// return customBindingExampleResponse;
-// }
-
- public CustomBindingExampleResponse sendAndReceiveSpringCustom() {
- final CustomBindingExampleRequest customBindingxampleRequest =
- new CustomBindingExampleRequest();
- customBindingxampleRequest.setData("CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.");
-
- final CustomBindingExampleResponse customBindingExampleResponse =
- (CustomBindingExampleResponse) this.webServiceTemplate
- .marshalSendAndReceive(customBindingxampleRequest);
-
- return customBindingExampleResponse;
- }
-}
+++ /dev/null
-package de.spring.webservices.client;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-
-import de.spring.webservices.client.auto.CustomBindingExampleResponse;
-import de.spring.webservices.client.auto.ExampleResponse;
-
-/**
- * This class is used just like a nice example about how to write and run client
- * code which will send data to and from the Web Services.
- *
- */
-public class MainTest {
- private static final Logger LOGGER = LoggerFactory.getLogger(MainTest.class);
-
- public ApplicationContext context;
-
- /**
- * @param args
- */
- public static void main(final String[] args) {
- final MainTest test = new MainTest();
-
- test.context = new ClassPathXmlApplicationContext(
- "classpath:spring-configuration/ws/client-spring-configuration.xml");
-
- final ExampleClientService example =
- (ExampleClientService) test.context.getBean("exampleClientService");
-
-// maven-jaxb2-plugin DOESN'T CREATE @WebService, @WebServiceClient y @WebEndpoint
-// logger.info("ExampleResponse Java:");
-// ExampleResponse response = example.sendAndReceiveJava();
-// logger.info(response.getData());
-
-
-// logger.info("CustomBindingExampleResponse Java:");
-// CustomBindingExampleResponse customBindingResponse = example.sendAndReceiveJavaCustom();
-// logger.info(customBindingResponse.getData());
-
-
- LOGGER.info("ExampleResponse Spring:");
- ExampleResponse response = example.sendAndReceiveSpring();
- LOGGER.info(response.getData());
-
-
- LOGGER.info("CustomBindingExampleResponse Spring:");
- CustomBindingExampleResponse customBindingResponse = example.sendAndReceiveSpringCustom();
- LOGGER.info(customBindingResponse.getData());
- }
-}
+++ /dev/null
-package de.spring.webservices.client.transport.http;
-
-import java.io.IOException;
-import java.net.URI;
-
-import org.springframework.http.HttpMethod;
-import org.springframework.http.client.ClientHttpRequest;
-import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.ws.transport.WebServiceConnection;
-import org.springframework.ws.transport.http.AbstractHttpWebServiceMessageSender;
-import org.springframework.ws.transport.http.ClientHttpRequestConnection;
-import org.springframework.ws.transport.http.HttpTransportConstants;
-
-
-/**
- * Based on ClientHttpRequestMessageSender from the Spring WS framework.
- *
- * <p>
- * Spring WS framework also provides implementations based on the HTTP clients by Jakarta and Apache HttpClient:
- * {@link https://hc.apache.org/httpcomponents-client-ga/} and {@link http://hc.apache.org/httpclient-3.x/}
- * </p>
- *
- * <p>
- * Four implementations for four HTTP clients:
- * <ul>
- * <li> org.springframework.ws.transport.http.ClientHttpRequestMessageSender (ClientHttpRequestFactory from the Spring framework) </li>
- * <li> org.springframework.ws.transport.http.CommonsHttpMessageSender (Jakarta implementation) </li>
- * <li> org.springframework.ws.transport.http.HttpComponentsMessageSender (Apache HttpClient) </li>
- * <li> org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
- * (org.springframework.ws.transport.http.HttpUrlConnection internal Spring framework implementation) </li>
- * </ul>
- * </p>
- */
-public class CustomHttpRequestMessageSender extends AbstractHttpWebServiceMessageSender {
- private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
-
- private final ClientHttpRequestFactory requestFactory;
-
- public CustomHttpRequestMessageSender() {
- requestFactory = new SimpleClientHttpRequestFactory();
- }
-
- @Override
- public WebServiceConnection createConnection(URI uri) throws IOException {
- ClientHttpRequest request = requestFactory.createRequest(uri, HttpMethod.POST);
- if (isAcceptGzipEncoding()) {
- request.getHeaders().add(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
- HttpTransportConstants.CONTENT_ENCODING_GZIP);
- }
-
- request.getHeaders().add(MY_CUSTOM_HEADER, "gumartinm.name");
-
- return new ClientHttpRequestConnection(request);
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- status: The level of internal Log4j events that should be logged to the console.
- Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
-
- monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
-
-
- see https://logging.apache.org/log4j/2.x/manual/configuration.html
- -->
-<Configuration status="error" strict="true" monitorInterval="30"
- name="XMLConfigTest" packages="org.apache.logging.log4j.test">
-
- <!--
- ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
-
- ERROR by default.
- -->
-
- <Appenders>
- <Appender type="Console" name="STDOUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
- </Appender>
- </Appenders>
- <Loggers>
-
-
- <!--
- Specific log when request message from this client or response message created by remote server contains validation errors.
-
- see client-spring-configuration.xml Spring configuration file.
-
- This configuration enables us to log validation errors of data sent from this client or data sent by remote server.
- -->
- <Logger name="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
- <!--
- Con esta configuración podemos loguear mensajes de error (SOAP Fault) procedentes del sevidor customizados. En mi caso
- usando GeneralFault. No se loguean los de validación (ni de envio de cliente ni de respuesta desde el servidor)
- porque esto lo hace PayloadValidatingInterceptor.
- -->
- <Logger name="de.spring.webservices.client.CustomFaultMessageResolver" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
- <!-- Specific log level for SOAP XML messages.
-
- see client-spring-configuration.xml Spring configuration file.
-
- This configuration enables us to log the SOAP XML Request (sent from this client), Response (sent by remote server) and Fault (sent by remote server).
- -->
- <Logger name="org.springframework.ws.client.MessageTracing" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
- <Logger name="org.springframework.ws.server.MessageTracing" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
- <!--
- Specific log level for Spring WS.
- -->
- <Logger name="org.springframework.ws" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- General logging Spring.
- -->
- <Logger name="org.springframework" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- Anything else will be using TRACE logging level.
- -->
- <Root level="INFO">
- <AppenderRef ref="STDOUT"/>
- </Root>
- </Loggers>
-</Configuration>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:parent="http://gumartinm.name/spring-ws/parent"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="inheritance annox"
- targetNamespace="http://gumartinm.name/spring-ws/example"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <!--
- We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
- when creating Java objects from examples.xsd.
- -->
- <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
-
-
- <!-- Spring requires the following:
- 1. XSD elements being used as request must end with Request name.
- 2. XSD elements being used as response must end with Response name.
-
- IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
-
- ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
- the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
- The same for CustomBindingExample.
- -->
- <!-- Using inheritance and annox plugin -->
- <xsd:element name="ExampleRequest">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="parent:limitedString" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleResponse">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-
- <!-- Using custombinding.xjb instead of inheritance plugin.
- Useful when you can not modify your xsd files because they are provided
- by another person or company
- -->
- <xsd:element name="CustomBindingExampleRequest">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleResponse">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <!-- Example of creating array list by means of XSD -->
- <xsd:complexType name="car">
- <xsd:sequence>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- <xsd:complexType name="truck">
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- <xsd:element name="vehicles">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="cars" type="car" maxOccurs="unbounded" />
- <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:sws="http://www.springframework.org/schema/web-services"
- xmlns:oxm="http://www.springframework.org/schema/oxm"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:util="http://www.springframework.org/schema/util"
-
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/web-services
- http://www.springframework.org/schema/web-services/web-services.xsd
- http://www.springframework.org/schema/oxm
- http://www.springframework.org/schema/oxm/spring-oxm.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
-
- <!--
- This file is an example about how someone should write code in order to send and
- receive data from the Web Services.
- -->
-
- <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Component, etc, etc) -->
- <context:component-scan base-package="de.spring.webservices"/>
-
- <!--
- Three ways of using a marshallers/unmarshallers.
-
- 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
- Esto equivale a esta configuracion en XML
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
- El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
-
- 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
- se hace de este modo:
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.auto"/>
- Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
- de especificar un context-path en concreto.
-
- 3. Especificando la implementación concreta del marshaller.
- Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
- cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
- De todos modos, probablemente habría que usar un package distinto para lo que hay
- en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
- -->
- <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
- <!--
- maven-jaxb2-plugin for WSDL DOES generate again the objects in web-services-spring-jaxb2-globalxsds :(
- So we MAY NOT scan everything because there is more than one class representing
- the same XML element. :(
-
- We scan the objects generated in this package.
- -->
- <property name="packagesToScan" value="de.spring.webservices.client.auto"/>
- </bean>
-
-
- <!-- Required in order to use SOAP 1.2
- id="messageFactory" is not a random choice, if you use another name it will not work
- (Spring will end up loading SOAP 1.1)
- -->
- <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
- <property name="soapVersion">
- <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
- </property>
- </bean>
-
-
- <!--
- ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
- del JAXB2 que estoy usando para generar las clases desde el xsd)
- Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
- debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
- funciona, así que supongo el validador tambien :/
- Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
- -->
- <bean id="payloadValidatingInterceptor"
- class="org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor">
- <property name="schemas">
- <list>
- <!--
- ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
- OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
- EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
-
- IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
- EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
- REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
- CONFIGURATION.
- -->
- <value>classpath:schemas/parent.xsd</value>
-
- <value>classpath:schemas/examples.xsd</value>
- </list>
- </property>
- <property name="validateRequest" value="true"/>
- <property name="validateResponse" value="true"/>
- </bean>
-
- <!--
- Los errores de validacion se devuelven así:
-
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
- <env:Header/>
- <env:Body>
- <env:Fault>
- <env:Code>
- <env:Value>env:Sender</env:Value>
- </env:Code>
- <env:Reason>
- <env:Text xml:lang="en">Validation error</env:Text>
- </env:Reason>
- <env:Detail>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
- </env:Detail>
- </env:Fault>
- </env:Body>
- </env:Envelope>
-
- El manejador de errores de validación es implementado por AbstractValidatingInterceptor (PayloadValidatingInterceptor)
- luego si quisiéramos loguear los mensaje de error de validación de algún modo especial tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
- -->
-
- <!-- Enables us to log custom Fault remote messages. No loguea mensajes de error de validación :( -->
- <bean id="customFaultMessageResolver" class="de.spring.webservices.client.CustomFaultMessageResolver">
- <property name="unmarshaller" ref="marshaller"/>
- </bean>
-
- <!--
- WebServiceTemplate using these strategies by default (see WebServiceTemplate.properties file)
-
- org.springframework.ws.client.core.FaultMessageResolver=org.springframework.ws.soap.client.core.SoapFaultMessageResolver
- org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
- org.springframework.ws.transport.WebServiceMessageSender=org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
-
- -->
-
- <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
- <constructor-arg ref="messageFactory"/>
- <property name="marshaller" ref="marshaller" />
- <property name="unmarshaller" ref="marshaller" />
-
- <!-- For local deployments change to http://localhost:8080/web-services-spring-jaxb2-server/spring-ws/example -->
- <property name="defaultUri" value="http://gumartinm.name/spring-ws/example"/>
-
- <property name="interceptors">
- <list>
- <ref bean="payloadValidatingInterceptor" />
- </list>
- </property>
-
- <property name="faultMessageResolver" ref="customFaultMessageResolver" />
-
- <property name="messageSenders">
- <list>
- <bean class="de.spring.webservices.client.transport.http.CustomHttpRequestMessageSender" />
- </list>
- </property>
- </bean>
-
- <!--
- Using @Service and @Autowired
- We could use just XML configuration, or XML confirguration and @Autowired or as I am doing now @Service and @Autowired.
- <bean id="exampleClientService" class="de.spring.webservices.client.ExampleClientService">
-
- @Autowired works even using XML configuration as long as you use context:component-scan
- <property name="webServiceTemplate" ref="webServiceTemplate"/>
- </bean>
- -->
-
-</beans>
+++ /dev/null
-package de.spring.webservices.client;
-
-import static org.junit.Assert.assertEquals;
-import static org.springframework.ws.test.client.RequestMatchers.payload;
-import static org.springframework.ws.test.client.ResponseCreators.withPayload;
-
-import javax.xml.transform.Source;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.ws.client.core.WebServiceTemplate;
-import org.springframework.ws.test.client.MockWebServiceServer;
-import org.springframework.xml.transform.StringSource;
-
-import de.spring.webservices.client.auto.CustomBindingExampleResponse;
-import de.spring.webservices.client.auto.ExampleResponse;
-
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration("classpath*:spring-configuration/ws/client-spring-configuration.xml")
-public class ExampleClientServiceIntegrationTest {
-
- @Autowired
- ExampleClientService exampleClientService;
-
- @Autowired
- private WebServiceTemplate webServiceTemplate;
-
- private MockWebServiceServer mockServer;
-
- @Before
- public void createServer() throws Exception {
- mockServer = MockWebServiceServer.createServer(webServiceTemplate);
- }
-
- @Test
- public void customerClient() throws Exception {
- final Source requestPayload = new StringSource(
- "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>"
- + "<data>SCARLETT SPRING. IT IS CANON.</data>"
- + "</ExampleRequest>");
- final Source responsePayload = new StringSource(
- "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>"
- + "<ns2:data>SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>"
- + "</ns2:ExampleResponse>");
- mockServer.expect(payload(requestPayload)).andRespond(
- withPayload(responsePayload));
-
- final ExampleResponse response = exampleClientService.sendAndReceiveSpring();
-
- assertEquals(response.getData(), "SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
- mockServer.verify();
- }
-
- @Test
- public void customerCustomClient() throws Exception {
- final Source customRequestPayload = new StringSource(
- "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
- "<data>CUSTOM BINDING SPRING. SCARLETT. IT IS CANON.</data>" +
- "</CustomBindingExampleRequest>");
- final Source customResponsePayload = new StringSource(
- "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
- "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.</ns2:data>" +
- "</ns2:CustomBindingExampleResponse>");
- mockServer.expect(payload(customRequestPayload)).andRespond(
- withPayload(customResponsePayload));
-
- final CustomBindingExampleResponse response = exampleClientService.sendAndReceiveSpringCustom();
-
- assertEquals(response.getData(), "CUSTOM BINDING SNAKE EYES AND SCARLETT SPRING. IT IS CANON.");
- mockServer.verify();
- }
-}
-
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>web-services-spring-jaxb2</artifactId>
- <groupId>de.spring.webservices</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
- <name>web-services-spring-jaxb2-globalxsds</name>
- <url>http://gumartinm.name</url>
-
- <properties>
- <project.xsd.schemas.source.path>src/main/resources/schemas</project.xsd.schemas.source.path>
- <project.xsd.schemas.target.path>${project.build.directory}/generated-sources/src/main/java</project.xsd.schemas.target.path>
- <project.xsd.schemas.package.name>de.spring.webservices.parent.auto</project.xsd.schemas.package.name>
- <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
- </properties>
-
- <dependencies>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <resources>
- <resource>
- <directory>${basedir}/src/main/resources</directory>
- <includes>
- <include>**/*.*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.jvnet.jaxb2.maven2</groupId>
- <artifactId>maven-jaxb2-plugin</artifactId>
- <version>0.13.1</version>
- <executions>
- <execution>
- <id>generate-sources-from-xsd</id>
- <goals>
- <goal>generate</goal>
- </goals>
- <phase>generate-sources</phase>
- </execution>
- </executions>
- <configuration>
- <!-- Specifies the schema directory, src/main/resources by default. -->
- <schemaDirectory>${project.xsd.schemas.source.path}</schemaDirectory>
-
- <!-- Specifies the binding directory, default to the schemaDirectory -->
- <bindingDirectory>${project.bindings.path}</bindingDirectory>
- <!-- Do not scan for *.xjb files in dependencies -->
- <scanDependenciesForBindings>false</scanDependenciesForBindings>
-
- <!-- Target directory for the generated code, target/generated-sources/xjc
- by default. -->
- <generateDirectory>${project.xsd.schemas.target.path}</generateDirectory>
-
- <!-- The generated classes will all be placed under this Java package
- (XJC's -p option), unless otherwise specified in the schemas. If left unspecified,
- the package will be derived from the schemas only. -->
- <generatePackage>${project.xsd.schemas.package.name}</generatePackage>
-
- <!-- I don't think I need the next two options because mvn clean should
- make the trick, anyhow, I am using them. If true, the generateDirectory will
- be deleted before the XJC binding compiler recompiles the source files. Default
- is false. -->
- <removeOldOutput>true</removeOldOutput>
- <!-- If true (default), package directories will be cleaned before the
- XJC binding compiler generates the source files. -->
- <cleanPackageDirectories>true</cleanPackageDirectories>
-
- <!-- Encoding for the generated sources, defaults to ${project.build.sourceEncoding}. -->
- <encoding>${project.build.sourceEncoding}</encoding>
-
- <!-- Locale used during generation, for instance en, de, fr etc. This
- will, for instance, influence the language of the generated JavaDoc comments. -->
- <locale>en</locale>
-
- <!-- This nice configuration avoids to use build-helper-maven-plugin -->
- <addCompileSourceRoot>true</addCompileSourceRoot>
- <addTestCompileSourceRoot>false</addTestCompileSourceRoot>
-
- <!-- If true (default), XJC will perform strict validation of the input
- schema. If strict is set to false XJC will be run with -nv, this disables
- strict validation of schemas. -->
- <strict>true</strict>
-
- <verbose>true</verbose>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="">
-
-</jaxb:bindings>
+++ /dev/null
-package de.spring.webservices.binders;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-
-
-/**
- * ATTENTION: if you are using this custombinder you will have to create custom payload
- * validators for Spring (AS FAR AS I KNOW)
- *
- */
-public class XSDateTimeCustomBinder extends XmlAdapter<String, Date> {
-
- @Override
- public Date unmarshal(final String dateTime) throws Exception {
- // X pattern just works from Java >= 1.7
- final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
- formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
-
- return formatter.parse(dateTime);
- }
-
- @Override
- public String marshal(final Date dateTime) throws Exception {
- // X pattern just works from Java >= 1.7
- final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
- formatter.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
-
- return formatter.format(dateTime);
- }
-}
+++ /dev/null
-package de.spring.webservices.operations;
-
-/**
- * <p>
- * Operations: WSDL v1.1 and v2.0
- * </p>
- * See: <a href="http://www.w3.org/TR/wsdl#_porttypes">http://www.w3.org/TR/wsdl#_porttypes</a><br>
- * See: <a href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- */
-public interface Operations {
-
- /**
- * <p>
- * Request-response operation WSDL v1.1
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/wsdl#_request-response">http://www.w3.org
- * /TR/wsdl#_request-response</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public static interface RequestResponse<T extends Response, E extends Request> {
- T requestResponse(E request);
- }
-
- /**
- * <p>
- * One-way operation WSDL v1.1
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/wsdl#_one-way">http://www.w3.org/TR/wsdl
- * #_one-way</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public interface OneWay<E extends Request> {
- void oneWay(E request);
- }
-
- /**
- * <p>
- * Notification operation WSDL v1.1
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/wsdl#_notification">http://www.w3.org/TR
- * /wsdl#_notification</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public interface Notification<T extends Response> {
- T notification();
- }
-
- /**
- * <p>
- * In-Only message exchange pattern WSDL 2.0
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- * @param <E>
- * Describes {@link Request}
- */
- public interface InOnly<E extends Request> {
- void inOnly(E request);
- }
-
- /**
- * <p>
- * Robust In-Only message exchange pattern WSDL 2.0
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- * @param <E>
- * Describes {@link Request}
- */
- public interface RobustInOnly<E extends Request> {
- void robustInOnly(E request);
- }
-
- /**
- * <p>
- * In-Out message exchange pattern WSDL 2.0
- * </p>
- * See: <a
- * href="http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns">
- * http://www.w3.org/TR/2007/REC-wsdl20-adjuncts-20070626/#patterns</a>
- *
- * @param <T>
- * Describes {@link Response}
- * @param <E>
- * Describes {@link Request}
- */
- public interface InOut<T extends Response, E extends Request> {
- T inOut(E request);
- }
-}
\ No newline at end of file
+++ /dev/null
-package de.spring.webservices.operations;
-
-public interface Request {
-
-}
+++ /dev/null
-package de.spring.webservices.operations;
-
-public interface Response {
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsd:schema xmlns="http://gumartinm.name/spring-ws/parent"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- targetNamespace="http://gumartinm.name/spring-ws/parent">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <xsd:simpleType name="parentEnumType">
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="FIRST"/>
- <xsd:enumeration value="SECOND"/>
- <xsd:enumeration value="THIRD"/>
- <xsd:enumeration value="FOURTH"/>
- <xsd:enumeration value="FIVETH"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:simpleType name="limitedString">
- <xsd:restriction base="xsd:string">
- <xsd:maxLength value="30" />
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:complexType name="element">
- <xsd:sequence>
- <xsd:element name="message" type="xsd:string"/>
- <xsd:element name="messageArgs" type="xsd:string" minOccurs="0" maxOccurs="100"/>
- </xsd:sequence>
- </xsd:complexType>
-
- <xsd:element name="GeneralFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="technicalError" type="xsd:string" />
- <xsd:element name="elements" type="element" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>web-services-spring-jaxb2</artifactId>
- <groupId>de.spring.webservices</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>web-services-spring-jaxb2-server</artifactId>
- <packaging>war</packaging>
- <name>web-services-spring-jaxb2-server</name>
- <url>http://gumartinm.name</url>
-
- <properties>
- <jetty.version>9.3.0.RC0</jetty.version>
- <project.xsd.schemas.source.path>src/main/resources/schemas</project.xsd.schemas.source.path>
- <project.xsd.schemas.target.path>${project.build.directory}/generated-sources/src/main/java</project.xsd.schemas.target.path>
- <project.xsd.schemas.package.name>de.spring.webservices.server.auto</project.xsd.schemas.package.name>
- <project.bindings.path>src/main/build-resources/bindings</project.bindings.path>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-xml</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jdom</groupId>
- <artifactId>jdom</artifactId>
- </dependency>
-
-
- <!-- Global types -->
- <dependency>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
- <version>${project.version}</version>
- </dependency>
-
-
- <!-- Required by spring-ws-core -->
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- </dependency>
-
- <!-- Required by my CustomHeaderInterceptor -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>4.0.0-b01</version>
- <scope>provided</scope>
- </dependency>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>${project.artifactId}</finalName>
- <resources>
- <resource>
- <directory>${basedir}/src/main/webapp</directory>
- <excludes>
- <exclude>**/*.*</exclude>
- </excludes>
- </resource>
- <resource>
- <directory>${basedir}/src/main/resources/</directory>
- <includes>
- <include>**/*.*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.jvnet.jaxb2.maven2</groupId>
- <artifactId>maven-jaxb2-plugin</artifactId>
- <version>0.13.1</version>
- <executions>
- <execution>
- <id>generate-sources-from-xsd</id>
- <goals>
- <goal>generate</goal>
- </goals>
- <phase>generate-sources</phase>
- </execution>
- </executions>
- <configuration>
- <schemaLanguage>XMLSCHEMA</schemaLanguage>
-
- <!-- Specifies the schema directory, src/main/resources by default. -->
- <schemaDirectory>${project.xsd.schemas.source.path}</schemaDirectory>
-
- <!-- Specifies the binding directory, default to the schemaDirectory -->
- <bindingDirectory>${project.bindings.path}</bindingDirectory>
- <!-- Do not scan for *.xjb files in dependencies -->
- <scanDependenciesForBindings>false</scanDependenciesForBindings>
-
- <!-- Target directory for the generated code, target/generated-sources/xjc
- by default. -->
- <generateDirectory>${project.xsd.schemas.target.path}</generateDirectory>
-
- <!-- The generated classes will all be placed under this Java package
- (XJC's -p option), unless otherwise specified in the schemas. If left unspecified,
- the package will be derived from the schemas only. -->
- <generatePackage>${project.xsd.schemas.package.name}</generatePackage>
-
- <!-- I don't think I need the next two options because mvn clean should
- make the trick, anyhow, I am using them. If true, the generateDirectory will
- be deleted before the XJC binding compiler recompiles the source files. Default
- is false. -->
- <removeOldOutput>true</removeOldOutput>
- <!-- If true (default), package directories will be cleaned before the
- XJC binding compiler generates the source files. -->
- <cleanPackageDirectories>true</cleanPackageDirectories>
-
- <!-- Encoding for the generated sources, defaults to ${project.build.sourceEncoding}. -->
- <encoding>${project.build.sourceEncoding}</encoding>
-
- <!-- Locale used during generation, for instance en, de, fr etc. This
- will, for instance, influence the language of the generated JavaDoc comments. -->
- <locale>en</locale>
-
- <!-- This nice configuration avoids to use build-helper-maven-plugin -->
- <addCompileSourceRoot>true</addCompileSourceRoot>
- <addTestCompileSourceRoot>false</addTestCompileSourceRoot>
-
- <!-- If true (default), XJC will perform strict validation of the input
- schema. If strict is set to false XJC will be run with -nv, this disables
- strict validation of schemas.
-
- The plugin is configured to use catalogs and strict mode at the
- same time. Using catalogs to resolve schema URIs in strict mode is known
- to be problematic and may fail. Please refer to the following link for more
- information: https://github.com/highsource/maven-jaxb2-plugin/wiki/Catalogs-in-Strict-Mode
- Consider setting <strict>false</strict> in your plugin configuration. -->
- <strict>false</strict>
-
- <verbose>true</verbose>
-
- <extension>true</extension>
- <args>
- <arg>-Xinheritance</arg>
- <arg>-Xannotate</arg>
- </args>
- <plugins>
- <plugin>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics</artifactId>
- <version>0.9.5</version>
- </plugin>
- <plugin>
- <groupId>org.jvnet.jaxb2_commons</groupId>
- <artifactId>jaxb2-basics-annotate</artifactId>
- <version>1.0.2</version>
- </plugin>
- </plugins>
-
- <!-- Avoids the annoying SCD "x-schema::tns" didn't match any schema component errors. -->
- <addIfExistsToEpisodeSchemaBindings>true</addIfExistsToEpisodeSchemaBindings>
-
- <!--
- GRAN DIFERENCIA:
-
- :) CON ESTE PLUGIN A DIFERENCIA DE cxf-xjc-plugin NO SE VUELVEN A GENERAR LOS OBJETOS DE parent.xsd
- QUE SE ENCONTRABAN EN web-services-spring-jaxb2-globalxsds
-
- CON cxf-xjc-plugin SÍ SE VUELVEN A GENERAR INCLUSO AUNQUE USEMOS EPISODIOS :(
-
- CON ESTE PLUGIN CONSEGUIMOS NO EMPAQUETAR AQUÍ TAMBIÉN LAS MISMAS CLASES QUE
- TENÍAMOS EN web-services-spring-jaxb2-globalxsds
-
- ESTE PLUGIN ES MUCHO MEJOR QUE cxf-xjc-plugin :)
- -->
-
- <!-- You can use the useDependenciesAsEpisodes instead of configuring
- individual episodes. In this case all the dependencies will be treated as
- episodes which is very convenient (less configuration). I am going to use
- the long way (individual episodes) -->
- <useDependenciesAsEpisodes>false</useDependenciesAsEpisodes>
- <catalog>src/main/build-resources/catalogs/catalog.cat</catalog>
- <episodes>
- <episode>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-jaxb2-globalxsds</artifactId>
- </episode>
- </episodes>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <version>2.6</version>
- <configuration>
- <webResources>
- <resource>
- <filtering>true</filtering>
- <directory>src/main/webapp</directory>
- <includes>
- <include>WEB-INF/web.xml</include>
- </includes>
- </resource>
- </webResources>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-maven-plugin</artifactId>
- <version>${jetty.version}</version>
- <configuration>
- <jettyXml>${basedir}/src/main/jetty/jetty-http.xml</jettyXml>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="xjc inheritance annox">
-
- <!--
- Se procesa con Xpath si quieres meter expresiones regulares y cosas así en teoría dependes de Xpath
- por ejemplo esto: @name=match[.] se supone que debería funcionar pero me dice que no puede
- cambiar mas de un nodo a la vez. Puede que sea un bug de xjc que se carga las opciones de Xpath :/
- <jaxb:bindings schemaLocation="examples.xsd">
- <jaxb:bindings node="//xsd:element[@name='ExampleRequest']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </jaxb:bindings>
- <jaxb:bindings node="//xsd:element[@name='ExampleResponse']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </jaxb:bindings>
- </jaxb:bindings>
- -->
-
- <jaxb:bindings schemaLocation="../../resources/schemas/examples.xsd">
- <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleRequest']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- </jaxb:bindings>
- </jaxb:bindings>
-
-
- <jaxb:bindings schemaLocation="../../resources/schemas/examples.xsd">
- <jaxb:bindings node="//xsd:element[@name='CustomBindingExampleResponse']/xsd:complexType">
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- </jaxb:bindings>
- </jaxb:bindings>
-
- <!-- The same applies to annotate. If you do not want or you may not modify your xsd files you can
- modify instead this file with your custom binding :) -->
-
- <!-- Custom xsd:dateTime adapter
- See: https://jaxb.java.net/2.2.4/docs/vendorCustomizations.html#javaType
- -->
- <jaxb:globalBindings>
- <xjc:javaType adapter="de.spring.webservices.binders.XSDateTimeCustomBinder"
- name="java.util.Date" xmlType="xsd:dateTime" />
- </jaxb:globalBindings>
-
-</jaxb:bindings>
+++ /dev/null
-
-
-REWRITE_SYSTEM "http://gumartinm.name/spring-ws/parent/parent.xsd" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
-
---
- This configuration is better (it relies on namespace instead of schemaLocation) but it doesn't work
- because of this bug: https://java.net/jira/browse/JAXB-942
-
- PUBLIC "xmlns:parent" "maven:de.spring.webservices:web-services-spring-jaxb2-globalxsds:jar::!/schemas/parent.xsd"
-
---
-
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.util.StringUtils;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.server.EndpointInterceptor;
-import org.springframework.ws.transport.context.TransportContext;
-import org.springframework.ws.transport.context.TransportContextHolder;
-import org.springframework.ws.transport.http.HttpServletConnection;
-
-public class CustomHeaderInterceptor implements EndpointInterceptor {
- private static final Logger LOGGER = LoggerFactory.getLogger(CustomHeaderInterceptor.class);
- private static final String MY_CUSTOM_HEADER = "MY_CUSTOM_HEADER";
-
- @Override
- public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
- TransportContext transport = TransportContextHolder.getTransportContext();
-
- if (transport != null) {
- HttpServletConnection connection = (HttpServletConnection) transport.getConnection();
- HttpServletRequest headers = connection.getHttpServletRequest();
- String headerValue = headers.getHeader(MY_CUSTOM_HEADER);
-
- if (!StringUtils.isEmpty(headerValue)) {
- LOGGER.info("Custom header value: " + headerValue);
- }
- }
-
- return true;
- }
-
- @Override
- public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
- return true;
- }
-
- @Override
- public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
- return true;
- }
-
- @Override
- public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
-
- }
-
-}
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import org.jdom2.Element;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.ws.context.MessageContext;
-import org.springframework.ws.server.endpoint.annotation.Endpoint;
-import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
-import org.springframework.ws.server.endpoint.annotation.RequestPayload;
-import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.operations.Operations.RequestResponse;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-import de.spring.webservices.services.ExampleService;
-
-
-@Endpoint
-public class ExampleEndPoint {
- private static final String NAMESPACE_URI = "http://gumartinm.name/spring-ws/example";
-
- private final Operations.RequestResponse
- <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
-
- private final ExampleService exampleService;
-
- @Autowired
- public ExampleEndPoint(
- RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService,
- ExampleService exampleService) {
- this.customBindingExampleService = customBindingExampleService;
- this.exampleService = exampleService;
- }
-
- @PayloadRoot(localPart = "ExampleRequest", namespace = NAMESPACE_URI)
- @ResponsePayload
- public ExampleResponse exampleResponse(
- @RequestPayload final ExampleRequest request,
- @RequestPayload final Element element,
- final MessageContext messageContext) {
-
- return this.exampleService.doResponse(request);
- }
-
- @PayloadRoot(localPart = "CustomBindingExampleRequest", namespace = NAMESPACE_URI)
- @ResponsePayload
- public CustomBindingExampleResponse cuntomBindingExampleResponse(
- @RequestPayload final CustomBindingExampleRequest requestObject,
- @RequestPayload final Element element,
- final MessageContext messageContext) {
-
- return this.customBindingExampleService.requestResponse(requestObject);
- }
-}
-
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.xml.transform.Result;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.oxm.Marshaller;
-import org.springframework.util.CollectionUtils;
-import org.springframework.ws.soap.SoapFault;
-import org.springframework.ws.soap.SoapFaultDetail;
-import org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver;
-import org.springframework.ws.soap.server.endpoint.SoapFaultDefinition;
-import org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor;
-
-import de.spring.webservices.exceptions.CustomBusinessException;
-import de.spring.webservices.parent.auto.Element;
-import de.spring.webservices.parent.auto.GeneralFault;
-
-public class MyCustomMappingExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver {
- private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomMappingExceptionResolver.class);
-
- private Marshaller marshaller;
-
- private Map<String, String> exceptionMappings = new LinkedHashMap<>();
-
- /**
- * Set the mappings between exception class names and SOAP Faults. The exception class name can be a substring, with
- * no wildcard support at present.
- *
- * <p>The values of the given properties object should use the format described in
- * {@code SoapFaultDefinitionEditor}.
- *
- * <p>Follows the same matching algorithm as {@code SimpleMappingExceptionResolver}.
- *
- * @param mappings exception patterns (can also be fully qualified class names) as keys, fault definition texts as
- * values
- * @see SoapFaultDefinitionEditor
- */
- public void setExceptionMappings(Properties mappings) {
- for (Map.Entry<Object, Object> entry : mappings.entrySet()) {
- if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
- exceptionMappings.put((String)entry.getKey(), (String)entry.getValue());
- }
- }
- }
-
- @Override
- protected SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) {
- if (!CollectionUtils.isEmpty(exceptionMappings)) {
- String definitionText = null;
- int deepest = Integer.MAX_VALUE;
- for (String exceptionMapping : exceptionMappings.keySet()) {
- int depth = getDepth(exceptionMapping, ex);
- if (depth >= 0 && depth < deepest) {
- deepest = depth;
- definitionText = exceptionMappings.get(exceptionMapping);
- }
- }
- if (definitionText != null) {
- SoapFaultDefinitionEditor editor = new SoapFaultDefinitionEditor();
- editor.setAsText(definitionText);
- return (SoapFaultDefinition) editor.getValue();
- }
- }
- return null;
- }
-
- /**
- * Return the depth to the superclass matching. {@code 0} means ex matches exactly. Returns {@code -1} if
- * there's no match. Otherwise, returns depth. Lowest depth wins.
- *
- * <p>Follows the same algorithm as RollbackRuleAttribute, and SimpleMappingExceptionResolver
- */
- protected int getDepth(String exceptionMapping, Exception ex) {
- return getDepth(exceptionMapping, ex.getClass(), 0);
- }
-
- @SuppressWarnings("unchecked")
- private int getDepth(String exceptionMapping, Class<? extends Exception> exceptionClass, int depth) {
- if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
- return depth;
- }
- if (exceptionClass.equals(Throwable.class)) {
- return -1;
- }
- return getDepth(exceptionMapping, (Class<? extends Exception>) exceptionClass.getSuperclass(), depth + 1);
- }
-
- protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
- GeneralFault customFault = new GeneralFault();
- customFault.setTechnicalError(getStackTrace(ex));
-
- Element element = buildElement(ex);
- List<Element> elements = customFault.getElements();
- elements.add(element);
-
- SoapFaultDetail detail = fault.addFaultDetail();
- Result result = detail.getResult();
- try {
- marshaller.marshal(customFault, result);
- } catch (Exception marshallEx) {
- LOGGER.error("MyCustomMappingExceptionResolver: marshaller error", marshallEx);
- }
- }
-
- public void setMarshaller(Marshaller marshaller) {
- this.marshaller = marshaller;
- }
-
- private Element buildElement(Exception ex) {
- Element element = new Element();
- element.setMessage(ex.getMessage());
-
- if (ex instanceof CustomBusinessException) {
- CustomBusinessException customEx = (CustomBusinessException) ex;
- List<String> messageArgs = element.getMessageArgs();
- List<String> argumentsEx = customEx.getArguments();
-
- for (String argumentEx: argumentsEx) {
- messageArgs.add(argumentEx);
- }
- }
-
- return element;
- }
-
- private String getStackTrace(Throwable throwable) {
- final StringWriter sw = new StringWriter();
- final PrintWriter pw = new PrintWriter(sw, true);
- throwable.printStackTrace(pw);
- return sw.getBuffer().toString();
- }
-}
+++ /dev/null
-package de.spring.webservices.exceptions;
-
-/**
- * This exception will be caught by org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
- *
- */
-public class BusinessException extends RuntimeException {
-
- private static final long serialVersionUID = -4042139454770293299L;
-
- public BusinessException() {
- super();
- }
-
- public BusinessException(String message) {
- super(message);
- }
-
- public BusinessException(String message, Throwable cause) {
- super(message, cause);
- }
-}
+++ /dev/null
-package de.spring.webservices.exceptions;
-
-import java.util.List;
-
-/**
- * This exception will be caught by de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
- *
- */
-public class CustomBusinessException extends RuntimeException {
- private final List<String> arguments;
-
- public CustomBusinessException(List<String> arguments) {
- super();
- this.arguments = arguments;
- }
-
- public CustomBusinessException(String message, List<String> arguments) {
- super(message);
-
- this.arguments = arguments;
- }
-
- public CustomBusinessException(String message, Throwable cause, List<String> arguments) {
- super(message, cause);
-
- this.arguments = arguments;
- }
-
- public List<String> getArguments() {
- return arguments;
- }
-}
+++ /dev/null
-package de.spring.webservices.services;
-
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-
-
-public interface ExampleService {
-
- public ExampleResponse doResponse(ExampleRequest request);
-
-}
+++ /dev/null
-package de.spring.webservices.services.impl;
-
-//import java.util.ArrayList;
-//import java.util.List;
-
-import org.springframework.stereotype.Service;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.parent.auto.ParentEnumType;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-//import de.spring.webservices.exceptions.BusinessException;
-//import de.spring.webservices.exceptions.CustomBusinessException;
-
-
-@Service("customBindingExampleService")
-public class CustomBindingExampleServiceImpl implements
- Operations.RequestResponse<CustomBindingExampleResponse, CustomBindingExampleRequest> {
-
-
- @Override
- public CustomBindingExampleResponse requestResponse(final CustomBindingExampleRequest request) {
-
-
- // Example about how works org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver
- // see soap-ws.xml Spring configuration file.
-// throw new BusinessException("This feature has not been implemented yet.");
-
- // Example about how works de.spring.webservices.endpoints.MyCustomMappingExceptionResolver
- // see soap-ws.xml Spring configuration file.
-// List<String> arguments = new ArrayList<>();
-// arguments.add("ARGUMENT 1");
-// arguments.add("ARGUMENT 2");
-// throw new CustomBusinessException("This feature has not been implemented yet.", arguments);
-
- CustomBindingExampleResponse response = new CustomBindingExampleResponse();
-
- response.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
- response.setParentEnum(ParentEnumType.FIRST);
-
- return response;
- }
-
-}
+++ /dev/null
-package de.spring.webservices.services.impl;
-
-import org.springframework.stereotype.Service;
-
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-import de.spring.webservices.services.ExampleService;
-
-
-@Service("exampleService")
-public class ExampleServiceImpl implements ExampleService {
-
- @Override
- public ExampleResponse doResponse(final ExampleRequest request) {
-
- ExampleResponse response = new ExampleResponse();
-
- response.setData("SNAKE EYES AND " + request.getData());
-
- return response;
- }
-
-}
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
-
-<!-- ============================================================= -->
-<!-- Configure the Jetty Server instance with an ID "Server" -->
-<!-- by adding a HTTP connector. -->
-<!-- This configuration must be used in conjunction with jetty.xml -->
-<!-- ============================================================= -->
-<Configure id="Server" class="org.eclipse.jetty.server.Server">
-
- <New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
- <Set name="secureScheme">https</Set>
- <Set name="securePort">
- <Property name="jetty.secure.port" default="8443" />
- </Set>
- <Set name="outputBufferSize">32768</Set>
- <Set name="requestHeaderSize">8192</Set>
- <Set name="responseHeaderSize">8192</Set>
- <Set name="sendServerVersion">true</Set>
- <Set name="sendDateHeader">false</Set>
- <Set name="headerCacheSize">512</Set>
-
- <!-- Uncomment to enable handling of X-Forwarded- style headers
- <Call name="addCustomizer">
- <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
- </Call>
- -->
- </New>
-
-
- <!-- =========================================================== -->
- <!-- Add a HTTP Connector. -->
- <!-- Configure an o.e.j.server.ServerConnector with a single -->
- <!-- HttpConnectionFactory instance using the common httpConfig -->
- <!-- instance defined in jetty.xml -->
- <!-- -->
- <!-- Consult the javadoc of o.e.j.server.ServerConnector and -->
- <!-- o.e.j.server.HttpConnectionFactory for all configuration -->
- <!-- that may be set here. -->
- <!-- =========================================================== -->
- <Call name="addConnector">
- <Arg>
- <New class="org.eclipse.jetty.server.ServerConnector">
- <Arg name="server">
- <Ref refid="Server" />
- </Arg>
- <Arg name="factories">
- <Array type="org.eclipse.jetty.server.ConnectionFactory">
- <Item>
- <New class="org.eclipse.jetty.server.HttpConnectionFactory">
- <Arg name="config">
- <Ref refid="httpConfig" />
- </Arg>
- </New>
- </Item>
- </Array>
- </Arg>
- <Set name="host">
- <Property name="jetty.host" default="127.0.0.1"/>
- </Set>
- <Set name="port">
- <Property name="jetty.port" default="8080" />
- </Set>
- <Set name="idleTimeout">
- <Property name="http.timeout" default="30000"/>
- </Set>
- </New>
- </Arg>
- </Call>
-
-</Configure>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- status: The level of internal Log4j events that should be logged to the console.
- Valid values for this attribute are "trace", "debug", "info", "warn", "error" and "fatal".
-
- monitorInterval: The minimum amount of time, in seconds, that must elapse before the file configuration is checked for changes.
-
-
- see https://logging.apache.org/log4j/2.x/manual/configuration.html
- -->
-<Configuration status="error" strict="true" monitorInterval="30"
- name="XMLConfigTest" packages="org.apache.logging.log4j.test">
-
- <!--
- ALL > TRACE > DEBUG > INFO > WARN > ERROR > OFF
-
- ERROR by default.
- -->
-
- <Appenders>
- <Appender type="Console" name="STDOUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
- </Appender>
- </Appenders>
- <Loggers>
-
-
- <!--
- Specific log when request message from remote client or response message created by this server contains validation errors.
-
- see soap-ws.xml Spring configuration file.
-
- This configuration enables us to log validation errors of data sent from remote client or data created by this server.
-
- Los errores de validación se loguean aquí (tanto de validación de datos de respuesta de servidor como de datos recibidos desde cliente)
- -->
- <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!-- Specific log level for SOAP SoapEnvelopeLoggingInterceptor.
-
- see soap-ws.xml Spring configuration file.
-
- This configuration enables us to log the SOAP XML Request (received from remote client), Response (sent by this server) and Fault (sent by this server).
-
- Aquí no se loguean errores de validación.
- -->
- <Logger name="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
-
- <!--
- Specific log level for Spring WS.
- -->
- <Logger name="org.springframework.ws" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- General logging Spring.
- -->
- <Logger name="org.springframework" level="INFO" additivity="false">
- <AppenderRef ref="STDOUT" />
- </Logger>
-
-
- <!--
- Anything else will be using TRACE logging level.
- -->
- <Root level="INFO">
- <AppenderRef ref="STDOUT"/>
- </Root>
- </Loggers>
-</Configuration>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsd:schema xmlns="http://gumartinm.name/spring-ws/example"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:parent="http://gumartinm.name/spring-ws/parent"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
- xmlns:annox="http://annox.dev.java.net"
- jaxb:version="2.1"
- jaxb:extensionBindingPrefixes="inheritance annox"
- targetNamespace="http://gumartinm.name/spring-ws/example"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
-
- <!--
- When should an item be declared as an element versus when should it be defined as a type?
- When in doubt, make it a type. You can always create an element from the type, if needed. With a type, other elements can reuse that type.
-
- <xsd:all> specifies that the child elements can appear in any order.
-
- <xsd:sequence> specifies child elements can only appear in the order mentioned.
- -->
-
- <!--
- We are going to use catalog.cat in order to avoid downloading parent.xsd from remote server
- when creating Java objects from examples.xsd.
- -->
- <xsd:import namespace="http://gumartinm.name/spring-ws/parent" schemaLocation="http://gumartinm.name/spring-ws/parent/parent.xsd" />
-
-
- <!-- Spring requires the following:
- 1. XSD elements being used as request must end with Request name.
- 2. XSD elements being used as response must end with Response name.
-
- IN THIS WAY SPRING FINDS OUT HOW TO CREATE THE wsdl:operation IN THE AUTOGENERATED WSDL.
-
- ExampleRequest and ExampleResponse will be associated to the wsdl:operation Example in the autogenerated wsdl and
- the wsdl:operation Example will have the wsdl:request ExampleRequest and wsdl:response ExampleResponse elements.
- The same for CustomBindingExample.
- -->
- <!-- Using inheritance and annox plugin -->
- <xsd:element name="ExampleRequest">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <annox:annotate>@java.lang.SuppressWarnings({"unchecked","rawtypes"})</annox:annotate>
- <inheritance:implements>de.spring.webservices.operations.Request</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="parent:limitedString" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleResponse">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:appinfo>
- <inheritance:implements>de.spring.webservices.operations.Response</inheritance:implements>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-
- <!-- Using custombinding.xjb instead of inheritance plugin.
- Useful when you can not modify your xsd files because they are provided
- by another person or company
- -->
- <xsd:element name="CustomBindingExampleRequest">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleResponse">
- <xsd:complexType>
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="exampleDate" type="xsd:dateTime" minOccurs="0" maxOccurs="1" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="CustomBindingExampleFault">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="parent:GeneralFault" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- <!-- Example of creating array list by means of XSD -->
- <xsd:complexType name="car">
- <xsd:sequence>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- <xsd:complexType name="truck">
- <xsd:all>
- <xsd:element name="data" type="xsd:string" />
- <xsd:element name="parentEnum" type="parent:parentEnumType" minOccurs="0" maxOccurs="1" />
- </xsd:all>
- </xsd:complexType>
- <xsd:element name="vehicles">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="cars" type="car" maxOccurs="unbounded" />
- <xsd:element name="trucks" type="truck" minOccurs="0" maxOccurs="100" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util"
-
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
-
-</beans>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:sws="http://www.springframework.org/schema/web-services"
- xmlns:util="http://www.springframework.org/schema/util"
-
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/web-services
- http://www.springframework.org/schema/web-services/web-services.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
-
- <!-- Searches for beans in packages (instead of XML configuration we can use in this way annotations like @Service, @Endpoint, etc, etc) -->
- <context:component-scan base-package="de.spring.webservices"/>
-
- <!--
- Three ways of using a marshallers/unmarshallers.
-
- 1. No declarar nada en el XML y dejar que Spring lo haga internamente todo por nosotros.
- Esto equivale a esta configuracion en XML
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices"/>
- El context-path Spring supongo que lo rellena automáticamente en base al component-scan declarado arriba.
-
- 2. Especificando el context-path para ser escaneado por Spring usando anotaciones. Esto
- se hace de este modo:
-
- <oxm:jaxb2-marshaller id="marshaller" context-path="de.spring.webservices.server.auto"/>
- Esto es lo mismo que haría Spring si no declaramos nada en el XML pero así tenemos opción de
- de especificar un context-path en concreto.
-
- 3. Especificando la implementación concreta del marshaller.
- Con esta opción además puedo usar packagesToScan, contest-path si no recuerdo mal tenía problemas
- cuando había dos ObjectFactory con el mismo package. Uno está en globalxsds y otro en este proyecto.
- De todos modos, probablemente habría que usar un package distinto para lo que hay
- en globalxsds (quizás incluso basado en el namespace del xsd) y así podría evitar esta configuración.
- -->
- <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
- <!--
- maven-jaxb2-plugin does NOT generate again the objects in web-services-spring-jaxb2-globalxsds
- So we MAY scan everything and there is no trouble because there is not more than one class representing
- the same XML element.
- -->
- <property name="packagesToScan" value="de.spring.webservices"/>
- </bean>
- <!-- Searches for @PayloadRoot -->
- <sws:annotation-driven marshaller="marshaller" unmarshaller="marshaller" />
-
-
- <!--
- CONSECUENCIAS DE USAR sws:annotation-driven VER: org.springframework.ws.config.AnnotationDrivenBeanDefinitionParser
- Cuanto más bajo es el valor de order mayor es la prioridad.
-
- 1. Manejadores de excepción, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
- a) SoapFaultAnnotationExceptionResolver será el primer manejador de excepciones que se intente usar por defecto. order = 0
- b) SimpleSoapExceptionResolver será el último manejador de excepciones que se intente usar por defecto. order = Ordered.LOWEST_PRECEDENCE
- Se usará si la excepción generada no pudo ser manejada por SoapFaultAnnotationExceptionResolver (porque la excepción no fue anotada con
- @SoapFault. Este manejador se traga cualquier excepción.
-
- 2. Endpoints a buscar, orden por defecto inicializado en AnnotationDrivenBeanDefinitionParser:
- a) PayloadRootAnnotationMethodEndpointMapping será el primer tipo de endpoints que se buscará y que se intentará usar. order = 0
- Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a b).
- b) SoapActionAnnotationMethodEndpointMapping será el segundo tipo de endpoints que se intentará usar. order = 1
- Si el XML SOAP que llega no machea ningún metodo anotado con este EndPoint pasamos a c).
- c) AnnotationActionEndpointMapping será el último tipo de endpoints que se buscará. order = 2
- Si el XML SOAP que llega no machea tampoco métodos anotado con este EndPoint se
- lanza NoEndpointFoundException desde org.springframework.ws.server.MessageDispatcher.dispatch()
-
-
- EN LUGAR DE USAR LA ANOTACIÓN PODRÍAMOS HABER DECLARADO EXPLÍCITAMENTE CADA BEAN TAL QUE ASÍ:
-
- <bean id="soapFaultMappingExceptionResolver"
- class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
- <property name="order" value="0" />
- </bean>
-
- <bean id="payloadRootAnnotationMethodEndpointMapping"
- class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
- <property name="order" value="0" />
- </bean>
-
- CON LA ANOTACIÓN ME AHORRO DECLARAR bean POR bean PERO LO MALO ES QUE INSTANCIO MANEJADORES QUE LUEGO NO USO :(
-
-
- ATENCION:
- Solo se usa una instancia de org.springframework.oxm.jaxb.Jaxb2Marshaller que será usada por todas las llamadas (todos los hilos).
- Es hilo seguro, por debajo usa javax.xml.bind.JAXBContext que es hilo seguro.
- JAXBContext debe ser siempre un singleton porque la primera vez tarda mucho en inicializarse. Cada vez que se haga marshalling y unmarshalling
- se deben crear objetos ligeros y no seguros mediante los métodos JAXBContext.createMarshaller() y JAXBContext.createUnmarshaller()
- (esto es lo que hace Jaxb2Marshaller por nosotros) Los objetos ligeros creados son javax.xml.bind.Marshaller y javax.xml.bind.Unmarshaller
- que no son hilo seguro y por tanto serán creados por cada petición (todo esto lo está haciendo Spring ya, así que genial)
- -->
-
- <!--
- Spring makes the WSDL file for us from the XSD file.
- Launch the Jetty server and download WSDL file from this URL:
- http://localhost:8080/web-services-spring-jaxb2-server/spring-ws/example/example.wsdl
- -->
- <sws:dynamic-wsdl id="example" portTypeName="Examples"
- createSoap12Binding="true" createSoap11Binding="false"
- locationUri="/spring-ws/example"
- targetNamespace="http://gumartinm.name/spring-ws/exampleService">
- <sws:xsd location="classpath:schemas/examples.xsd"/>
- </sws:dynamic-wsdl>
-
-
- <!-- Required in order to use SOAP 1.2
- id="messageFactory" is not a random choice, if you use another name it will not work
- (Spring will end up loading SOAP 1.1)
- -->
- <bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
- <property name="soapVersion">
- <util:constant static-field="org.springframework.ws.soap.SoapVersion.SOAP_12" />
- </property>
- </bean>
-
- <!-- The interceptors in this set are automatically configured on each registered EndpointMapping
- What means, every class annotated with @Endpoint will be using these interceptors.
-
- This configuration enables us to log the SOAP XML Request (received from client), Response (sent by this server) and Fault (sent by this server).
- -->
- <sws:interceptors>
- <bean class="org.springframework.ws.soap.server.endpoint.interceptor.SoapEnvelopeLoggingInterceptor">
- <property name="logRequest" value="true"/>
- <property name="logResponse" value="true"/>
- <property name="logFault" value="true"/>
- </bean>
-
- <!--
- ¿Este validador funciona teniendo inheritance en el xsd? (inheritances es una cosa especial
- del JAXB2 que estoy usando para generar las clases desde el xsd)
- Parece que el unmarshal (que supongo que se hace con el JAXB2 que está en el classpath
- debido al tipo de Endpoint que estoy usando, que por cierto no sé cual JAXB2 está cogiendo realmente)
- funciona, así que supongo el validador tambien :/
- Lo que realmente tampoco sé es si hay alguna relación entre los validadores y JAXB2 :/
- -->
- <bean id="validatingInterceptor"
- class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
- <property name="schemas">
- <list>
- <!--
- ALWAYS FIRST THE XSD FILES TO BE IMPORTED!!!!! O.o
- OTHERWISE THE import IN examples.xsd WILL BE SOLVED BY MEANS OF DOWNLOADING THE
- EXTERNAL parent.xsd (USING THE URL LINKED BY THE IMPORT STATEMENT IN examples.xsd)
-
- IF YOU DON'T DO THIS, PayloadValidatingInterceptor WILL TRY TO CONNECT TO THE
- EXTERNAL SERVER WHERE parent.xsd IS LOCATED AND IT WILL FAIL IF BECAUSE SOME
- REASON YOU DON'T HAVE IN THAT VERY MOMENT NETWORK CONNECTION. SO, DON'T MESS WITH THIS
- CONFIGURATION.
- -->
- <value>classpath:schemas/parent.xsd</value>
-
- <value>classpath:schemas/examples.xsd</value>
- </list>
- </property>
- <property name="validateRequest" value="true"/>
- <property name="validateResponse" value="true"/>
- </bean>
-
- <!-- My custom header interceptor -->
- <bean class="de.spring.webservices.endpoints.CustomHeaderInterceptor" />
- </sws:interceptors>
-
-
- <!--
- PARA METER MAS COSAS A LA RESPUESTA CON ERROR, por ejemplo si quisiéramos enviar en Reason Text la pila de excepción tengo que
- implementar mi propio manejador de excepción que extienda de AbstractSoapFaultDefinitionExceptionResolver y añada todo aquello
- que yo necesite.
-
- A mí me parecen muy pobres las implementaciones que trae Spring así que implementaré el mío propio que devuelva la pila
- de excepción si la hay.
- -->
- <bean id="soapFaultMappingExceptionResolver"
- class="org.springframework.ws.soap.server.endpoint.SoapFaultMappingExceptionResolver">
- <!--
- No quiero usar un valor por defecto porque si no, si mi manejador no machea ninguna excepción
- devolvera este valor por defecto. Y no se probará con otros manejadores de excepción que tengan un order con menor precedencia.
-
- Cuando se escribe value="SERVER" Spring está seteando SoapFaultDefinition.SERVER en defaultValue
- de org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver Esto parece
- magia pero Spring lo logra usando org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor.setAsText("SERVER")
-
- <property name="defaultFault" value="SERVER"/>
- -->
- <property name="exceptionMappings">
- <props>
- <!--
- <prop key="de.spring.webservices.exceptions.BusinessException">SERVER,something went wrong in server side,en_US</prop>
-
- Si hago esto en lugar de devolver al cliente el mensaje que va dentro de la excepcion devuelvo siempre:
-
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
- <env:Header/>
- <env:Body>
- <env:Fault>
- <env:Code>
- <env:Value>env:Receiver</env:Value> Receiver y Server significa lo mismo. Cuando pongo "SERVER" en primer token aquí aparece Receiver.
- </env:Code>
- <env:Reason>
- <env:Text xml:lang="en-US">something went wrong in server side</env:Text> en-US porque puse como Locale en_US en el tercer token.
- </env:Reason>
- </env:Fault>
- </env:Body>
- </env:Envelope>
-
- El primer token es el Value. Si es SERVER o RECEIVER se muestra Receiver. Si es CLIENT o SENDER se muestra Sender.
-
- El segundo token es el mensaje que SIEMPRE se mostrará.
-
- El tercer token mapea a un Locale en SoapFaultDefinition (por defecto Locale.ENGLISH). El mapeo se hace con
- org.springframework.util.StringUtils.parseLocaleString("en_US")
-
-
-
-
-
- Yo prefiero que se devuelva el mensaje que va dentro de la excepción. Para eso SOLO puede haber un token y
- el Locale siempre será entonces Locale.ENGLISH.
-
- Uso SERVER porque de.spring.webservices.exceptions.BusinessException es una excepción generada en el lado servidor.
- -->
- <prop key="de.spring.webservices.exceptions.BusinessException">SERVER</prop>
- </props>
- </property>
- <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
- SoapFaultAnnotationExceptionResolver
- -->
- <property name="order" value="1" />
- </bean>
-
-
-
- <bean id="myCustomMappingExceptionResolver" class="de.spring.webservices.endpoints.MyCustomMappingExceptionResolver">
- <!--
- Voy a usar un valor por defecto porque este va a ser el último manejador que haya antes de
- SimpleSoapExceptionResolver. SimpleSoapExceptionResolver será siempre por el order que he puesto
- el último manejador de excepciones.
- Así todas las excepciones que no hayan sido macheadas por los otros manejadores serán siempre
- cogidas por este y se les asignará un SoapFaultDefinition.SERVER. En este caso SimpleSoapExceptionResolver
- nunca será usado.
- -->
- <property name="defaultFault" value="SERVER"/>
- <property name="exceptionMappings">
- <props>
- <!--
- Los errores de validacion se devuelven así:
-
- <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
- <env:Header/>
- <env:Body>
- <env:Fault>
- <env:Code>
- <env:Value>env:Sender</env:Value>
- </env:Code>
- <env:Reason>
- <env:Text xml:lang="en">Validation error</env:Text>
- </env:Reason>
- <env:Detail>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-maxLength-valid: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' con la longitud = '91' no es de faceta válida con respecto a maxLength '30' para el tipo 'limitedString'.</spring-ws:ValidationError>
- <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.3.1.3: El valor 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' del elemento 'exam:data' no es válido.</spring-ws:ValidationError>
- </env:Detail>
- </env:Fault>
- </env:Body>
- </env:Envelope>
-
- El manejador de errores de validación es implementado por AbstractFaultCreatingValidatingInterceptor (PayloadValidatingInterceptor)
- luego si quisiéramos devolver un mensaje de error distinto al implementado por AbstractFaultCreatingValidatingInterceptor
- tendríamos que crear nuestro propio PayloadValidatingInterceptor :(
- -->
- <prop key="de.spring.webservices.exceptions.CustomBusinessException">SERVER</prop>
- </props>
- </property>
- <property name="marshaller" ref="marshaller"/>
- <!-- Así mi manejador de excepciones entra antes que SimpleSoapExceptionResolver pero después que
- SoapFaultAnnotationExceptionResolver y SoapFaultMappingExceptionResolver
- -->
- <property name="order" value="2" />
- </bean>
-
-</beans>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
-
- <display-name>Spring Web Services: example</display-name>
-
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
-
- <context-param>
- <param-name>spring.profiles.active</param-name>
- <param-value>${environment.profile}</param-value>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath*:spring-configuration/*.xml
- </param-value>
- </context-param>
-
- <!-- Spring SOAP servlet -->
- <servlet>
- <servlet-name>spring-ws</servlet-name>
- <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- <async-supported>true</async-supported>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath*:spring-configuration/ws/*.xml</param-value>
- </init-param>
- <init-param>
- <param-name>transformWsdlLocations</param-name>
- <param-value>true</param-value>
- </init-param>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>spring-ws</servlet-name>
- <url-pattern>/spring-ws/*</url-pattern>
- </servlet-mapping>
-
-</web-app>
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import static org.springframework.ws.test.server.RequestCreators.withPayload;
-import static org.springframework.ws.test.server.ResponseMatchers.payload;
-
-import javax.xml.transform.Source;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.ws.test.server.MockWebServiceClient;
-import org.springframework.xml.transform.StringSource;
-
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = { "classpath*:spring-configuration/ws/soap-ws.xml" } )
-public class ExampleEndPointIntegrationTest {
-
- @Autowired
- private ApplicationContext applicationContext;
-
- private MockWebServiceClient mockClient;
-
- @Before
- public void createClient() {
- mockClient = MockWebServiceClient.createClient(applicationContext);
- }
-
- @Test
- public void exampleEndpoint() throws Exception {
- final Source requestPayload = new StringSource(
- "<ExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
- "<data>SCARLETT</data>" +
- "</ExampleRequest>");
- final Source responsePayload = new StringSource(
- "<ns2:ExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
- "<ns2:data>SNAKE EYES AND SCARLETT</ns2:data>" +
- "</ns2:ExampleResponse>");
- mockClient.sendRequest(withPayload(requestPayload)).andExpect(
- payload(responsePayload));
-
-
- final Source customRequestPayload = new StringSource(
- "<CustomBindingExampleRequest xmlns='http://gumartinm.name/spring-ws/example'>" +
- "<data>SCARLETT</data>" +
- "<exampleDate>2015-06-03T10:20:30Z</exampleDate>" +
- "<parentEnum>FIRST</parentEnum>" +
- "</CustomBindingExampleRequest>");
- final Source customResponsePayload = new StringSource(
- "<ns2:CustomBindingExampleResponse xmlns:ns2='http://gumartinm.name/spring-ws/example'>" +
- "<ns2:data>CUSTOM BINDING SNAKE EYES AND SCARLETT</ns2:data>" +
- "<ns2:parentEnum>FIRST</ns2:parentEnum>" +
- "</ns2:CustomBindingExampleResponse>");
- mockClient.sendRequest(withPayload(customRequestPayload)).andExpect(
- payload(customResponsePayload));
- }
-}
-
+++ /dev/null
-package de.spring.webservices.endpoints;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.services.ExampleService;
-
-
-public class ExampleEndPointTest {
-
- private ExampleService exampleService;
-
- private Operations.RequestResponse
- <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
-
- private ExampleEndPoint exampleEndPoint;
-
- @Before
- public void init() {
- exampleService = mock(ExampleService.class);
- customBindingExampleService = mock(Operations.RequestResponse.class);
- exampleEndPoint = new ExampleEndPoint(customBindingExampleService, exampleService);
- }
-
- @Test
- public void givenExampleRequestThenInvokeExampleService() {
- ExampleRequest request = new ExampleRequest();
- request.setData("SCARLETT");
-
- exampleEndPoint.exampleResponse(request, null, null);
-
- verify(exampleService).doResponse(request);
- }
-
- @Test
- public void givenCustomBindingExampleRequestThenInvokeCustomBindingExampleService() {
- CustomBindingExampleRequest request = new CustomBindingExampleRequest();
- request.setData("SCARLETT");
-
- exampleEndPoint.cuntomBindingExampleResponse(request, null, null);
-
- verify(customBindingExampleService).requestResponse(request);
- }
-
-}
+++ /dev/null
-package de.spring.webservices.services;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import de.spring.webservices.operations.Operations;
-import de.spring.webservices.server.auto.CustomBindingExampleRequest;
-import de.spring.webservices.server.auto.CustomBindingExampleResponse;
-import de.spring.webservices.services.impl.CustomBindingExampleServiceImpl;
-
-
-public class CustomBindingExampleServiceTest {
-
- private Operations.RequestResponse
- <CustomBindingExampleResponse, CustomBindingExampleRequest> customBindingExampleService;
-
- @Before
- public void init() {
- customBindingExampleService = new CustomBindingExampleServiceImpl();
- }
-
- @Test
- public void givenCustomBindingExampleRequestThenReturnCustomBindingExampleResponse() {
- CustomBindingExampleRequest request = new CustomBindingExampleRequest();
- request.setData("SCARLETT");
- CustomBindingExampleResponse expected = new CustomBindingExampleResponse();
- expected.setData("CUSTOM BINDING SNAKE EYES AND " + request.getData());
-
- CustomBindingExampleResponse actual = customBindingExampleService.requestResponse(request);
-
- Assert.assertEquals(expected.getData(), actual.getData());
- }
-}
+++ /dev/null
-package de.spring.webservices.services;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import de.spring.webservices.server.auto.ExampleRequest;
-import de.spring.webservices.server.auto.ExampleResponse;
-import de.spring.webservices.services.impl.ExampleServiceImpl;
-
-public class ExampleServiceTest {
-
- private ExampleService exampleService;
-
- @Before
- public void init() {
- exampleService = new ExampleServiceImpl();
- }
-
- @Test
- public void givenExampleRequestThenReturnExampleResponse() {
- ExampleRequest request = new ExampleRequest();
- request.setData("SCARLETT");
- ExampleResponse expected = new ExampleResponse();
- expected.setData("SNAKE EYES AND " + request.getData());
-
- ExampleResponse actual = exampleService.doResponse(request);
-
- Assert.assertEquals(expected.getData(), actual.getData());
- }
-
-}
+++ /dev/null
-<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/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>de.spring.webservices</groupId>
- <artifactId>web-services-spring-jaxb2</artifactId>
- <packaging>pom</packaging>
- <version>1.0-SNAPSHOT</version>
- <name>web-services-spring-jaxb2</name>
- <url>http://gumartinm.name</url>
- <description>Web Services Spring Framework</description>
- <organization>
- <name>Gustavo Martin Morcuende</name>
- <url>http://www.gumartinm.name</url>
- </organization>
- <scm>
- <developerConnection>scm:git:http://git.gumartinm.name/SpringWebServicesForFun</developerConnection>
- <url>http://git.gumartinm.name/SpringWebServicesForFun</url>
- </scm>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <!-- Be aware: spring-ws latest version does not follow spring-context
- latest version -->
- <spring.version>4.0.9.RELEASE</spring.version>
- <spring.ws.version>2.2.1.RELEASE</spring.ws.version>
- </properties>
-
- <profiles>
- <profile>
- <id>release</id>
- <properties>
- <environment.profile>release</environment.profile>
- </properties>
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
- </profile>
- </profiles>
-
- <dependencies>
- <!--
- 1/3 Required dependency for log4j 2 with slf4j: binding between log4j 2 and slf4j
- -->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- <version>2.3</version>
- </dependency>
- <!--
- 2/3 Required dependency for log4j 2 with slf4j: log4j 2 maven plugin (it is the log4j 2 implementation)
- -->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.3</version>
- </dependency>
- <!--
- 3/3 Required dependency for getting rid of commons logging.
- This is the BRIDGE (no binding) between Jakarta Commons Logging (used by Spring) and whatever
- I am using for logging (in this case I am using log4j 2)
- See: http://www.slf4j.org/legacy.html
-
- We need exclusions in every dependency using Jakarta Commons Logging (see Spring dependencies below)
- -->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.12</version>
- </dependency>
- <dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib</artifactId>
- <version>2.2.2</version>
- </dependency>
- </dependencies>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-core</artifactId>
- <version>${spring.ws.version}</version>
- <!--
- Required dependency for getting rid of commons logging and use my own logging library
- (in my case I decided to use log4j 2 under slf4j)
- -->
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-xml</artifactId>
- <version>${spring.ws.version}</version>
- <!--
- Required dependency for getting rid of commons logging and use my own logging library
- (in my case I decided to use log4j 2 under slf4j)
- -->
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.jdom</groupId>
- <artifactId>jdom</artifactId>
- <version>2.0.2</version>
- </dependency>
-
- <!-- Required by spring-ws-core -->
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- <version>1.6.3</version>
- </dependency>
-
- <!-- Unitary and integration tests -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>${spring.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.ws</groupId>
- <artifactId>spring-ws-test</artifactId>
- <version>${spring.ws.version}</version>
- <scope>test</scope>
- <!--
- Required dependency for getting rid of commons logging and use my own logging library
- (in my case I decided to use log4j 2 under slf4j)
- -->
- <exclusions>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>2.0.11-beta</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <build>
-
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.18.1</version>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-failsafe-plugin</artifactId>
- <version>2.18.1</version>
- </plugin>
- </plugins>
- </pluginManagement>
-
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.3</version>
- <configuration>
- <source>1.8</source>
- <target>1.8</target>
- <encoding>${project.build.sourceEncoding}</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <version>2.7</version>
- <configuration>
- <encoding>${project.build.sourceEncoding}</encoding>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <version>2.4</version>
- <configuration>
- <archive>
- <manifestEntries>
- <Specification-Title>${project.description}</Specification-Title>
- <Specification-Version>${project.version}</Specification-Version>
- <Specification-Vendor>${project.organization.name}</Specification-Vendor>
- <Implementation-Title>${project.description}</Implementation-Title>
- <Implementation-Version>${project.version}</Implementation-Version>
- <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
- </manifestEntries>
- </archive>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>**/*IntegrationTest.java</exclude>
- </excludes>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-failsafe-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>integration-test</goal>
- <goal>verify</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <includes>
- <include>**/*IntegrationTest.java</include>
- </includes>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>