1 package de.spring.webservices.endpoints;
3 import java.io.PrintWriter;
4 import java.io.StringWriter;
5 import java.util.LinkedHashMap;
8 import java.util.Properties;
10 import javax.xml.transform.Result;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14 import org.springframework.oxm.Marshaller;
15 import org.springframework.util.CollectionUtils;
16 import org.springframework.ws.soap.SoapFault;
17 import org.springframework.ws.soap.SoapFaultDetail;
18 import org.springframework.ws.soap.server.endpoint.AbstractSoapFaultDefinitionExceptionResolver;
19 import org.springframework.ws.soap.server.endpoint.SoapFaultDefinition;
20 import org.springframework.ws.soap.server.endpoint.SoapFaultDefinitionEditor;
22 import de.spring.webservices.auto.Element;
23 import de.spring.webservices.auto.ExampleFault;
24 import de.spring.webservices.exceptions.CustomBusinessException;
26 public class MyCustomMappingExceptionResolver extends AbstractSoapFaultDefinitionExceptionResolver {
27 private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomMappingExceptionResolver.class);
29 private Marshaller marshaller;
31 private Map<String, String> exceptionMappings = new LinkedHashMap<>();
34 * Set the mappings between exception class names and SOAP Faults. The exception class name can be a substring, with
35 * no wildcard support at present.
37 * <p>The values of the given properties object should use the format described in
38 * {@code SoapFaultDefinitionEditor}.
40 * <p>Follows the same matching algorithm as {@code SimpleMappingExceptionResolver}.
42 * @param mappings exception patterns (can also be fully qualified class names) as keys, fault definition texts as
44 * @see SoapFaultDefinitionEditor
46 public void setExceptionMappings(Properties mappings) {
47 for (Map.Entry<Object, Object> entry : mappings.entrySet()) {
48 if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
49 exceptionMappings.put((String)entry.getKey(), (String)entry.getValue());
55 protected SoapFaultDefinition getFaultDefinition(Object endpoint, Exception ex) {
56 if (!CollectionUtils.isEmpty(exceptionMappings)) {
57 String definitionText = null;
58 int deepest = Integer.MAX_VALUE;
59 for (String exceptionMapping : exceptionMappings.keySet()) {
60 int depth = getDepth(exceptionMapping, ex);
61 if (depth >= 0 && depth < deepest) {
63 definitionText = exceptionMappings.get(exceptionMapping);
66 if (definitionText != null) {
67 SoapFaultDefinitionEditor editor = new SoapFaultDefinitionEditor();
68 editor.setAsText(definitionText);
69 return (SoapFaultDefinition) editor.getValue();
76 * Return the depth to the superclass matching. {@code 0} means ex matches exactly. Returns {@code -1} if
77 * there's no match. Otherwise, returns depth. Lowest depth wins.
79 * <p>Follows the same algorithm as RollbackRuleAttribute, and SimpleMappingExceptionResolver
81 protected int getDepth(String exceptionMapping, Exception ex) {
82 return getDepth(exceptionMapping, ex.getClass(), 0);
85 @SuppressWarnings("unchecked")
86 private int getDepth(String exceptionMapping, Class<? extends Exception> exceptionClass, int depth) {
87 if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
90 if (exceptionClass.equals(Throwable.class)) {
93 return getDepth(exceptionMapping, (Class<? extends Exception>) exceptionClass.getSuperclass(), depth + 1);
96 protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
97 ExampleFault customFault = new ExampleFault();
98 customFault.setTechnicalError(getStackTrace(ex));
100 Element element = buildElement(ex);
101 List<Element> elements = customFault.getElements();
102 elements.add(element);
104 SoapFaultDetail detail = fault.addFaultDetail();
105 Result result = detail.getResult();
107 marshaller.marshal(customFault, result);
108 } catch (Exception marshallEx) {
109 LOGGER.error("MyCustomMappingExceptionResolver: marshaller error", marshallEx);
113 public void setMarshaller(Marshaller marshaller) {
114 this.marshaller = marshaller;
117 private Element buildElement(Exception ex) {
118 Element element = new Element();
119 element.setMessage(ex.getMessage());
121 if (ex instanceof CustomBusinessException) {
122 CustomBusinessException customEx = (CustomBusinessException) ex;
123 List<String> messageArgs = element.getMessageArgs();
124 List<String> argumentsEx = customEx.getArguments();
126 for (String argumentEx: argumentsEx) {
127 messageArgs.add(argumentEx);
134 private String getStackTrace(Throwable throwable) {
135 final StringWriter sw = new StringWriter();
136 final PrintWriter pw = new PrintWriter(sw, true);
137 throwable.printStackTrace(pw);
138 return sw.getBuffer().toString();