title: Custom validation error messages using Jaxb2marshaller and spring-ws
body: <p>I have a running spring-ws project that can unmarshal requests using Jax2b, but when unmarshalling of integers/booleans fail I get an error message with little detail and often without the name of the invalid element. E.g.:</p>
  
  <pre><code>org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested     exception is javax.xml.bind.UnmarshalException
   - with linked exception:
  [org.xml.sax.SAXParseException; cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'.]
  </code></pre>
  
  <p>This also becomes the content of the SOAPFault response from my webservice.</p>
  
  <p>I am trying to change the message to include the element name. I'm using a ValidationEventHandler to change the message by throwing a RuntimeException from the event handler, but it only works i some cases.</p>
  
  <h3>ValidationEventHandler:</h3>
  
  <pre class="lang-java prettyprint-override"><code>@Component
  public class ValidationEventHandlerImpl implements ValidationEventHandler {
  
      @Override
      public boolean handleEvent(ValidationEvent event) {
  
          String message = event.getMessage();
          String linkedMessage = "";
          if(event.getLinkedException() != null)
              linkedMessage = event.getLinkedException().toString();
  
          boolean ignoreValidationEvent = true;            
          if(message.contains("NumberFormatException") || 
                  message.contains("is not a valid value") || 
                  linkedMessage.contains("NumberFormatException") || 
                  linkedMessage.contains("is not a valid value")){
              ignoreValidationEvent = false;
          }
  
          if(ignoreValidationEvent){
              return true;
          }else{
              String nodeName = "";
              if(event.getLocator() != null &amp;&amp; event.getLocator().getNode() != null)
                  nodeName = event.getLocator().getNode().getNodeName();
  
              //This is the important line
              throw new RuntimeException("Error parsing '" + nodeName + "': " + event.getMessage());
  
          }
      }
  
  }
  </code></pre>
  
  <h3>It successfully changes:</h3>
  
  <pre><code>JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException: Not a number: 32g321
   - with linked exception:
  [java.lang.NumberFormatException: Not a number: 32g321]
  </code></pre>
  
  <p><strong>to:</strong> RuntimeException message: "<em>java.lang.RuntimeException: Error parsing 'MyNodeName': Not a number: 32g321</em>"</p>
  
  <p>(Event Severity: ERROR)</p>
  
  <h3>But it does <strong>not</strong> work when I want it to change:</h3>
  
  <pre><code>JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException
   - with linked exception:
  [org.xml.sax.SAXParseException; cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'.]
  </code></pre>
  
  <p><strong>to:</strong> RuntimeException message: "<em>java.lang.RuntimeException: Error parsing 'MyNodeName': '' is not a valid value for 'integer'</em>". </p>
  
  <p>The RuntimeException is ignored and the SAXParseException is thrown instead and added to the SOAPFault reponse.</p>
  
  <p>(Event Severity: FATAL_ERROR)</p>
  
  <h3>Spring configuration for Jaxb2Marshalling:</h3>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;bean id="jaxb2MarshallerContact" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"&gt;
      &lt;property name="classesToBeBound"&gt;
          &lt;list&gt;
              &lt;value&gt;com.model.oxm.ContactRequest&lt;/value&gt;
              &lt;value&gt;com.model.oxm.ContactResponse&lt;/value&gt;
          &lt;/list&gt;
      &lt;/property&gt;
      &lt;property name="marshallerProperties"&gt;
          &lt;map&gt;
              &lt;entry&gt;
                  &lt;key&gt;
                      &lt;util:constant static-field="javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT" /&gt;
                  &lt;/key&gt;
                  &lt;value type="boolean"&gt;true&lt;/value&gt;
              &lt;/entry&gt;
              &lt;entry&gt;
                  &lt;key&gt;
                      &lt;util:constant static-field="javax.xml.bind.Marshaller.JAXB_FRAGMENT" /&gt;
                  &lt;/key&gt;
                  &lt;value type="boolean"&gt;true&lt;/value&gt;
              &lt;/entry&gt;
          &lt;/map&gt;
      &lt;/property&gt;
      &lt;property name="schema" ref="ContactServiceSchema" /&gt;
      &lt;property name="validationEventHandler" ref="validationEventHandlerImpl" /&gt;
  &lt;/bean&gt;
  
  &lt;bean id="ContactServiceSchema" class="org.springframework.core.io.ClassPathResource"&gt;
      &lt;constructor-arg value="WEB-INF/schemas/ContactService.xsd" /&gt;
  &lt;/bean&gt; 
  </code></pre>
  
  <h3>Endpoint:</h3>
  
  <pre class="lang-java prettyprint-override"><code>@Endpoint
  public class ContactEndpoint {
  
      private Logger logger = Logger.getLogger(ContactEndpoint.class);
  
      @Autowired
      private ContactService contactService;
  
      private static final String NAMESPACE_URI = "http://mydomain/schemas";
  
      @PayloadRoot(namespace = NAMESPACE_URI, localPart = "ContactRequest")     
      @ResponsePayload
      public ContactResponse handleContactRequest(@RequestPayload ContactRequest contactRequest) throws Exception {
      ...
  </code></pre>
  
  <ul>
  <li><p>How can I return a custom message instead of the SAXParseException message?</p></li>
  <li><p>Is there a better way of implementing this, e.g. using ValidationErrorHandler?</p></li>
  </ul>
  
  <p>Thanks!</p>