From ce60369ef12a85c80b9e16c08377748504cc8ee6 Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Sun, 20 Dec 2015 06:23:06 +0100 Subject: [PATCH] cxf: web-services-spring-cxf-server, MyCustomExceptionResolver --- .../endpoints/MyCustomExceptionResolver.java | 131 +++++++++++++++++++++ .../exceptions/CustomBusinessException.java | 32 +++++ .../impl/CustomBindingExampleServiceImpl.java | 13 ++ .../resources/spring-configuration/ws/soap-ws.xml | 16 +++ 4 files changed, 192 insertions(+) create mode 100644 cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/endpoints/MyCustomExceptionResolver.java create mode 100644 cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/exceptions/CustomBusinessException.java diff --git a/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/endpoints/MyCustomExceptionResolver.java b/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/endpoints/MyCustomExceptionResolver.java new file mode 100644 index 0000000..f2a375f --- /dev/null +++ b/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/endpoints/MyCustomExceptionResolver.java @@ -0,0 +1,131 @@ +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.auto.Element; +import de.spring.webservices.auto.ExampleFault; +import de.spring.webservices.exceptions.CustomBusinessException; + +public class MyCustomExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver { + private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomExceptionResolver.class); + + private Marshaller marshaller; + + private Map 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. + * + *

The values of the given properties object should use the format described in + * {@code SoapFaultDefinitionEditor}. + * + *

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 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. + * + *

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 exceptionClass, int depth) { + if (exceptionClass.getName().indexOf(exceptionMapping) != -1) { + return depth; + } + if (exceptionClass.equals(Throwable.class)) { + return -1; + } + return getDepth(exceptionMapping, (Class) exceptionClass.getSuperclass(), depth + 1); + } + + protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) { + SoapFaultDetail detail = fault.addFaultDetail(); + Result result = detail.getResult(); + + Element element = new Element(); + element.setMessage(ex.getMessage()); + + if (ex instanceof CustomBusinessException) { + List arguments = element.getMessageArgs(); + arguments.add("ARGUMENT 1"); + arguments.add("ARGUMENT 2"); + } + + ExampleFault customFault = new ExampleFault(); + customFault.setTechnicalError(getStackTrace(ex)); + List elements = customFault.getElements(); + elements.add(element); + + try { + marshaller.marshal(customFault, result); + } catch (Exception marshallEx) { + LOGGER.error("", marshallEx); + } + } + + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + private static String getStackTrace(final Throwable throwable) { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw, true); + throwable.printStackTrace(pw); + return sw.getBuffer().toString(); + } +} diff --git a/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/exceptions/CustomBusinessException.java b/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/exceptions/CustomBusinessException.java new file mode 100644 index 0000000..952e765 --- /dev/null +++ b/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/exceptions/CustomBusinessException.java @@ -0,0 +1,32 @@ +package de.spring.webservices.exceptions; + +import java.util.List; + +/** + * This exception will be caught by de.spring.webservices.endpoints.MyCustomExceptionResolver + * + */ +public class CustomBusinessException extends RuntimeException { + private final List arguments; + + public CustomBusinessException(List arguments) { + super(); + this.arguments = arguments; + } + + public CustomBusinessException(String message, List arguments) { + super(message); + + this.arguments = arguments; + } + + public CustomBusinessException(String message, Throwable cause, List arguments) { + super(message, cause); + + this.arguments = arguments; + } + + public List getArguments() { + return arguments; + } +} diff --git a/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/services/impl/CustomBindingExampleServiceImpl.java b/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/services/impl/CustomBindingExampleServiceImpl.java index de65baa..c5ce222 100644 --- a/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/services/impl/CustomBindingExampleServiceImpl.java +++ b/cxf/web-services-spring-cxf-server/src/main/java/de/spring/webservices/services/impl/CustomBindingExampleServiceImpl.java @@ -1,8 +1,14 @@ package de.spring.webservices.services.impl; +//import java.util.ArrayList; +//import java.util.List; + import org.springframework.stereotype.Service; + + //import de.spring.webservices.exceptions.BusinessException; +//import de.spring.webservices.exceptions.CustomBusinessException; import de.spring.webservices.auto.CustomBindingExampleRequest; import de.spring.webservices.auto.CustomBindingExampleResponse; import de.spring.webservices.auto.ParentEnumType; @@ -22,6 +28,13 @@ public class CustomBindingExampleServiceImpl implements // 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.MyCustomExceptionResolver + // see soap-ws.xml Spring configuration file. +// List 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()); diff --git a/cxf/web-services-spring-cxf-server/src/main/resources/spring-configuration/ws/soap-ws.xml b/cxf/web-services-spring-cxf-server/src/main/resources/spring-configuration/ws/soap-ws.xml index cd60455..27ccc48 100644 --- a/cxf/web-services-spring-cxf-server/src/main/resources/spring-configuration/ws/soap-ws.xml +++ b/cxf/web-services-spring-cxf-server/src/main/resources/spring-configuration/ws/soap-ws.xml @@ -218,4 +218,20 @@ + + + + + + + SERVER + + + + + + + -- 2.1.4