I'm using a controller that accepts POST requests with XML payload and uses JAXB with schema validation enabled to unmarshal. I use several schemata, my marshaller configuration is:
A demo controller is:Code:<beans:bean id="xmlMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <beans:property name="contextPath" value="demo.og.com.model"/> <beans:property name="schemas"> <beans:list> <beans:value>classpath:schemas/common-0.1.xsd</beans:value> <beans:value>classpath:schemas/payment-0.1.xsd</beans:value> <beans:value>classpath:schemas/contract-0.1.xsd</beans:value> </beans:list> </beans:property> </beans:bean>
In this case, CostItem is a class generated by xjc and it corresponds to an the costItem element described in common-1.0.xsd:Code:@RequestMapping(value="/cost", method=RequestMethod.POST ) public String echoCost( @RequestBody CostItem ci, Model model ) { logger.debug( "Cost: " + ci.getCost().getCostTotal() ); model.addAttribute( ci ); return "costView"; }
Then I use a similar method to handle an ArrayOfContracts object, which is described in contract-0.1.xsd (bear with me):Code:<xs:complexType name="cost"> <xs:sequence> <xs:element name="costBeforeVat" type="xs:float" /> <xs:element name="vatPercentage" type="xs:int" /> <xs:element name="costTotal" type="xs:float" /> <xs:element name="currency" type="xs:string" /> </xs:sequence> </xs:complexType> <xs:element name="costItem"> <xs:complexType> <xs:sequence> <xs:element name="cost" type="tns:cost"/> </xs:sequence> </xs:complexType> </xs:element>
Notice that cost in each ContractItem references the common-1.0 namespace.Code:<xs:complexType name="contractItem"> <xs:sequence> <xs:element name="since" type="xs:date" /> <xs:element name="until" type="xs:date" /> <xs:element name="cost" type="common:cost" /> <xs:element name="cpvCodes" type="tns:arrayOfCpvCodes" minOccurs="0" /> <xs:element name="description" type="xs:string" /> </xs:sequence> <xs:attribute name="id" type="xs:string" use="optional" /> </xs:complexType> <xs:complexType name="arrayOfContractItems"> <xs:sequence> <xs:element name="item" type="tns:contractItem" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> <xs:complexType name="contract"> <xs:sequence> <xs:element name="contractNumber" type="xs:string" /> <xs:element name="primaryParties" type="tns:arrayOfContractParties" /> <xs:element name="secondaryParties" type="tns:arrayOfContractParties" /> <xs:element name="contractItems" type="tns:arrayOfContractItems" /> <xs:element name="contractDate" type="xs:date" /> <xs:element name="complementsContract" type="xs:string" minOccurs="0" /> <xs:element name="replacesContract" type="xs:string" minOccurs="0" /> <xs:element name="isDeleted" type="xs:boolean" default="false" minOccurs="0"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="optional" /> </xs:complexType> <xs:element name="arrayOfContracts"> <xs:complexType> <xs:sequence> <xs:element name="contract" type="tns:contract" minOccurs="0" maxOccurs="unbounded" /> </xs:sequence> </xs:complexType> </xs:element>
Everything works fine, until i try to post an invalid document, i.e. one without a contractDate. As expected, I get an exception:
After this point, whenever I send a valid document, I keep getting the same MarshalException exception, the framework seems to ignore the new payload. Redeploying the app fixes the issue. I don't have this problem when I unmarshal the simpler CostItem element, sending an invalid request throws the exception just for that request, not for every subsequent one.Code:DEBUG: org.springframework.web.servlet.DispatcherServlet - Could not complete request org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException - with linked exception: [org.xml.sax.SAXParseException: cvc-complex-type.2.4.b: The content of element 'contract' is not complete. One of '{"http://demo.og.com/schema/contract-0.1":contractDate}' is expected.]
Any suggestions?


Reply With Quote
