From 7e865220b218d9bb59e290645fb20e710dba10bc Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Mon, 21 Dec 2015 01:33:13 +0100 Subject: [PATCH] jaxb2 and cxf: CustomFaultMessageResolver --- .../src/main/build-resources/wsdl/example.wsdl | 16 ++++- .../client/CustomFaultMessageResolver.java | 83 ++++++++++++++++++++++ .../webservices/client/ExampleClientService.java | 8 +-- .../de/spring/webservices/client/MainTest.java | 36 ++++++---- .../src/main/resources/examples.xsd | 16 ++++- .../src/main/resources/log4j2.xml | 13 +++- .../ws/client-spring-configuration.xml | 37 ++++++++++ .../src/main/resources/parent.xsd | 14 ++-- .../src/main/resources/examples.xsd | 16 ++++- .../src/main/resources/log4j2.xml | 4 ++ .../src/main/build-resources/wsdl/example.wsdl | 16 ++++- .../client/CustomFaultMessageResolver.java | 83 ++++++++++++++++++++++ .../de/spring/webservices/client/MainTest.java | 10 +-- .../src/main/resources/log4j2.xml | 13 +++- .../src/main/resources/schemas/examples.xsd | 16 ++++- .../ws/client-spring-configuration.xml | 36 +++++++++- .../src/main/resources/schemas/parent.xsd | 14 ++-- .../src/main/resources/log4j2.xml | 4 ++ .../src/main/resources/schemas/examples.xsd | 16 ++++- 19 files changed, 401 insertions(+), 50 deletions(-) create mode 100644 cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java create mode 100644 jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java diff --git a/cxf/web-services-spring-cxf-client/src/main/build-resources/wsdl/example.wsdl b/cxf/web-services-spring-cxf-client/src/main/build-resources/wsdl/example.wsdl index 9b3fdaf..20ce10e 100644 --- a/cxf/web-services-spring-cxf-client/src/main/build-resources/wsdl/example.wsdl +++ b/cxf/web-services-spring-cxf-client/src/main/build-resources/wsdl/example.wsdl @@ -54,7 +54,13 @@ - + + + + + + + diff --git a/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java b/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java new file mode 100644 index 0000000..244be4e --- /dev/null +++ b/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java @@ -0,0 +1,83 @@ +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 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; + } +} diff --git a/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/ExampleClientService.java b/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/ExampleClientService.java index c7d9758..32e1435 100644 --- a/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/ExampleClientService.java +++ b/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/ExampleClientService.java @@ -6,10 +6,10 @@ 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; +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; +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; @@ -29,7 +29,7 @@ public class ExampleClientService { this.webServiceTemplate = webServiceTemplate; } - public ExampleResponse sendAndReceiveJava() throws ExampleFault { + public ExampleResponse sendAndReceiveJava() throws ExampleFault_Exception { final ExampleRequest exampleRequest = new ExampleRequest(); exampleRequest.setData("SCARLETT JAVA. IT IS CANON."); @@ -49,7 +49,7 @@ public class ExampleClientService { return exampleResponse; } - public CustomBindingExampleResponse sendAndReceiveJavaCustom() throws CustomBindingExampleFault { + public CustomBindingExampleResponse sendAndReceiveJavaCustom() throws CustomBindingExampleFault_Exception { final CustomBindingExampleRequest customBindingxampleRequest = new CustomBindingExampleRequest(); customBindingxampleRequest.setData("CUSTOM BINDING JAVA. SCARLETT. IT IS CANON."); diff --git a/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/MainTest.java b/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/MainTest.java index 8527ab5..54cc644 100644 --- a/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/MainTest.java +++ b/cxf/web-services-spring-cxf-client/src/main/java/de/spring/webservices/client/MainTest.java @@ -16,7 +16,7 @@ import de.spring.webservices.client.auto.ExampleResponse; * */ public class MainTest { - private static final Logger logger = LoggerFactory.getLogger(MainTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MainTest.class); public ApplicationContext context; @@ -25,7 +25,7 @@ public class MainTest { * @throws ExampleFault_Exception * @throws CustomBindingExampleFault_Exception */ - public static void main(final String[] args) throws ExampleFault, CustomBindingExampleFault { + public static void main(final String[] args) { final MainTest test = new MainTest(); test.context = new ClassPathXmlApplicationContext( @@ -34,23 +34,35 @@ public class MainTest { final ExampleClientService example = (ExampleClientService) test.context.getBean("exampleClientService"); - logger.info("ExampleResponse Java:"); - ExampleResponse response = example.sendAndReceiveJava(); - logger.info(response.getData()); + 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 = example.sendAndReceiveJavaCustom(); - logger.info(customBindingResponse.getData()); + 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:"); + + + LOGGER.info("ExampleResponse Spring:"); response = example.sendAndReceiveSpring(); - logger.info(response.getData()); + LOGGER.info(response.getData()); - logger.info("CustomBindingExampleResponse Spring:"); + LOGGER.info("CustomBindingExampleResponse Spring:"); customBindingResponse = example.sendAndReceiveSpringCustom(); - logger.info(customBindingResponse.getData()); + LOGGER.info(customBindingResponse.getData()); } } diff --git a/cxf/web-services-spring-cxf-client/src/main/resources/examples.xsd b/cxf/web-services-spring-cxf-client/src/main/resources/examples.xsd index 26cd175..e419711 100644 --- a/cxf/web-services-spring-cxf-client/src/main/resources/examples.xsd +++ b/cxf/web-services-spring-cxf-client/src/main/resources/examples.xsd @@ -62,7 +62,13 @@ - + + + + + + + diff --git a/cxf/web-services-spring-cxf-client/src/main/resources/log4j2.xml b/cxf/web-services-spring-cxf-client/src/main/resources/log4j2.xml index 5aa51de..5d47d57 100644 --- a/cxf/web-services-spring-cxf-client/src/main/resources/log4j2.xml +++ b/cxf/web-services-spring-cxf-client/src/main/resources/log4j2.xml @@ -36,6 +36,15 @@ + + + + + - + - + diff --git a/cxf/web-services-spring-cxf-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml b/cxf/web-services-spring-cxf-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml index b701475..a824d54 100644 --- a/cxf/web-services-spring-cxf-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml +++ b/cxf/web-services-spring-cxf-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml @@ -69,6 +69,12 @@ @@ -117,6 +123,35 @@ + + + + + + diff --git a/cxf/web-services-spring-cxf-server/src/main/resources/log4j2.xml b/cxf/web-services-spring-cxf-server/src/main/resources/log4j2.xml index 28a4ed7..ea6ded3 100644 --- a/cxf/web-services-spring-cxf-server/src/main/resources/log4j2.xml +++ b/cxf/web-services-spring-cxf-server/src/main/resources/log4j2.xml @@ -32,6 +32,8 @@ 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) --> @@ -43,6 +45,8 @@ 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. --> diff --git a/jaxb2/web-services-spring-jaxb2-client/src/main/build-resources/wsdl/example.wsdl b/jaxb2/web-services-spring-jaxb2-client/src/main/build-resources/wsdl/example.wsdl index 374ed46..2018a37 100644 --- a/jaxb2/web-services-spring-jaxb2-client/src/main/build-resources/wsdl/example.wsdl +++ b/jaxb2/web-services-spring-jaxb2-client/src/main/build-resources/wsdl/example.wsdl @@ -54,7 +54,13 @@ - + + + + + + + diff --git a/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java b/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java new file mode 100644 index 0000000..9fdea6b --- /dev/null +++ b/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/CustomFaultMessageResolver.java @@ -0,0 +1,83 @@ +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 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; + } +} diff --git a/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/MainTest.java b/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/MainTest.java index 8d79220..92b1638 100644 --- a/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/MainTest.java +++ b/jaxb2/web-services-spring-jaxb2-client/src/main/java/de/spring/webservices/client/MainTest.java @@ -14,7 +14,7 @@ import de.spring.webservices.client.auto.ExampleResponse; * */ public class MainTest { - private static final Logger logger = LoggerFactory.getLogger(MainTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MainTest.class); public ApplicationContext context; @@ -41,13 +41,13 @@ public class MainTest { // logger.info(customBindingResponse.getData()); - logger.info("ExampleResponse Spring:"); + LOGGER.info("ExampleResponse Spring:"); ExampleResponse response = example.sendAndReceiveSpring(); - logger.info(response.getData()); + LOGGER.info(response.getData()); - logger.info("CustomBindingExampleResponse Spring:"); + LOGGER.info("CustomBindingExampleResponse Spring:"); CustomBindingExampleResponse customBindingResponse = example.sendAndReceiveSpringCustom(); - logger.info(customBindingResponse.getData()); + LOGGER.info(customBindingResponse.getData()); } } diff --git a/jaxb2/web-services-spring-jaxb2-client/src/main/resources/log4j2.xml b/jaxb2/web-services-spring-jaxb2-client/src/main/resources/log4j2.xml index 5aa51de..5d47d57 100644 --- a/jaxb2/web-services-spring-jaxb2-client/src/main/resources/log4j2.xml +++ b/jaxb2/web-services-spring-jaxb2-client/src/main/resources/log4j2.xml @@ -36,6 +36,15 @@ + + + + + - + - + diff --git a/jaxb2/web-services-spring-jaxb2-client/src/main/resources/schemas/examples.xsd b/jaxb2/web-services-spring-jaxb2-client/src/main/resources/schemas/examples.xsd index 26cd175..e419711 100644 --- a/jaxb2/web-services-spring-jaxb2-client/src/main/resources/schemas/examples.xsd +++ b/jaxb2/web-services-spring-jaxb2-client/src/main/resources/schemas/examples.xsd @@ -62,7 +62,13 @@ - + + + + + + + diff --git a/jaxb2/web-services-spring-jaxb2-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml b/jaxb2/web-services-spring-jaxb2-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml index cd67e3e..389f361 100644 --- a/jaxb2/web-services-spring-jaxb2-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml +++ b/jaxb2/web-services-spring-jaxb2-client/src/main/resources/spring-configuration/ws/client-spring-configuration.xml @@ -53,6 +53,8 @@ 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. --> @@ -101,6 +103,36 @@ + + + + + + + - + + + @@ -43,6 +45,8 @@ 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. --> diff --git a/jaxb2/web-services-spring-jaxb2-server/src/main/resources/schemas/examples.xsd b/jaxb2/web-services-spring-jaxb2-server/src/main/resources/schemas/examples.xsd index 26cd175..e419711 100644 --- a/jaxb2/web-services-spring-jaxb2-server/src/main/resources/schemas/examples.xsd +++ b/jaxb2/web-services-spring-jaxb2-server/src/main/resources/schemas/examples.xsd @@ -62,7 +62,13 @@ - + + + + + + + -- 2.1.4