Results 1 to 2 of 2

Thread: Problem with JAXB and @RequestBody

  1. #1
    Join Date
    Sep 2010
    Posts
    12

    Unhappy Problem with JAXB and @RequestBody

    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:

    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>
    A demo controller is:

    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";
    }
    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:
    <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>
    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="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>
    Notice that cost in each ContractItem references the common-1.0 namespace.

    Everything works fine, until i try to post an invalid document, i.e. one without a contractDate. As expected, I get an exception:

    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.]
    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.

    Any suggestions?

  2. #2
    Join Date
    Sep 2010
    Posts
    12

    Default

    Ok this had nothing to do with namespaces, validation just doesn't work in unmarshalling so an invalid document was stored and then the marshaller (where validation does work) was breaking.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •