title: Validating against a Schema with JAXB
body: <p>I've been looking for solutions to this problem for far too long considering how easy it sounds so I've come for some help.</p>
  
  <p>I have an XML Schema which I have used with xjc to create my JAXB binding.  This works fine when the XML is well formed.  Unfortunately it also doesn't complain when the XML is not well formed.  I cannot figure out how to do proper full validation against the schema when I try to unmarshall an XML file.</p>
  
  <p>I have managed to use a ValidationEventCollector to handle events, which works for XML parsing errors such as mismatched tags but doesn't raise any events when there is a tag that is required but is completely absent.</p>
  
  <p>From what I have seen validation can be done againsta  schema, but you must know the path to the schema in order to pass it into the setSchema() method.  The problem I have is that the path to the schema is stored in the XML header and I can't knwo at run time where the schema is going to be.  Which is why it's stored in the XML file:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;DDSSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="/a/big/long/path/to/a/schema/file/DDSSettings.xsd"&gt;
  &lt;Field1&gt;1&lt;/Field1&gt;
  &lt;Field2&gt;-1&lt;/Field2&gt;
  </code></pre>
  
  <p>...etc</p>
  
  <p>Every example I see uses setValidating(true), which is now deprecated, so throws an exception.</p>
  
  <p>This is the Java code I have so far, which seems to only do XML validation, not schema validation:</p>
  
  <pre><code>try {
      JAXBContext jc = new JAXBContext() {
          private final JAXBContext jaxbContext = JAXBContext.newInstance("blah");
  
          @Override
          public Unmarshaller createUnmarshaller() throws JAXBException {
              Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
              ValidationEventCollector vec = new ValidationEventCollector() {
                  @Override
                  public boolean handleEvent(ValidationEvent event) throws RuntimeException {
                      ValidationEventLocator vel = event.getLocator();
                      if (event.getSeverity() == event.ERROR || event.getSeverity() == event.FATAL_ERROR) {
                          String error = "XML Validation Exception:  " + event.getMessage() + " at row: " + vel.getLineNumber() + " column: " + vel.getColumnNumber();
                          System.out.println(error);
                      }
                      m_unmarshallingOk = false;
                      return false;
                  }
              };
              unmarshaller.setEventHandler(vec);
  
              return unmarshaller;
          }
  
          @Override
          public Marshaller createMarshaller() throws JAXBException {
              throw new UnsupportedOperationException("Not supported yet.");
          }
  
          @Override
          @SuppressWarnings("deprecation")
          public Validator createValidator() throws JAXBException {
              throw new UnsupportedOperationException("Not supported yet.");
          }
      };
  
      Unmarshaller unmarshaller = jc.createUnmarshaller();
      m_ddsSettings = (com.ultra.DDSSettings)unmarshaller.unmarshal(new File(xmlfileName));
  } catch (UnmarshalException ex) {
      Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
      Level.SEVERE,
      null, ex);
  } catch (JAXBException ex) {
      Logger.getLogger(UniversalDomainParticipant.class.getName()).log(
      Level.SEVERE,
      null, ex);
  }
  </code></pre>
  
  <p>So what is the proper way to do this validation?  I was expecting there to be a validate() method on the JAXB generated classes, but I guess that would be too simple for Java.</p>