+++ /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.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<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) {
- SoapFaultDetail detail = fault.addFaultDetail();
- Result result = detail.getResult();
-
- Element element = new Element();
- element.setMessage(ex.getMessage());
-
- if (ex instanceof CustomBusinessException) {
- List<String> arguments = element.getMessageArgs();
- arguments.add("ARGUMENT 1");
- arguments.add("ARGUMENT 2");
- }
-
- ExampleFault customFault = new ExampleFault();
- customFault.setTechnicalError(getStackTrace(ex));
- List<Element> 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();
- }
-}
--- /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.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<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) {
+ SoapFaultDetail detail = fault.addFaultDetail();
+ Result result = detail.getResult();
+
+ Element element = new Element();
+ element.setMessage(ex.getMessage());
+
+ if (ex instanceof CustomBusinessException) {
+ List<String> arguments = element.getMessageArgs();
+ arguments.add("ARGUMENT 1");
+ arguments.add("ARGUMENT 2");
+ }
+
+ ExampleFault customFault = new ExampleFault();
+ customFault.setTechnicalError(getStackTrace(ex));
+ List<Element> 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();
+ }
+}
<sws:dynamic-wsdl id="example" portTypeName="Examples"
createSoap12Binding="true" createSoap11Binding="false"
locationUri="/spring-ws/example"
- targetNamespace="http://gumartinm.name/resource/wsdl/schemas">
+ targetNamespace="http://gumartinm.name/spring-ws/exampleService">
<sws:xsd location="classpath:schemas/examples.xsd"/>
</sws:dynamic-wsdl>
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schemas">
<list>
- <value>classpath:schemas/examples.xsd</value>
+ <!--
+ 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"/>
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.
+ 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
- <bean id="myCustomExceptionResolver" class="de.spring.webservices.endpoints.MyCustomExceptionResolver">
+ <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>