Announcement Announcement Module
Collapse
No announcement yet.
Problem with JAXB and @RequestBody Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

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

    Comment

    Working...
    X