Assuming we are using Jaxb2Marshaller class for marshaling/marshaling the XML request/response.Lets we want to use a xsd file named validate.xsd for validating XML REST Request.First put the validate.xsd file in to src/main/resources directory in the project workspace.Now set the JAXB configuration in your rest-servlet.xml file like:
<bean id="jaxb2Marshaller"> <property name="schema" value="classpath:/validate.xsd" /> <property name="classesToBeBound"> <list> <value>com.devil.space.RPCRequest</value> <value>com.devil.space.RPCResponse</value> </list> </property> </bean>
RPCRequest and RPCResponse are the rest request and response java xml object respectively.So the full rest-servlet.xml file would be like:
<?xml version=1.0 ?> <beans xmlns=http://www.springframework.org/schema/beans xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:context=http://www.springframework.org/schema/context xmlns:mvc=http://www.springframework.org/schema/mvc xmlns:util=http://www.springframework.org/schema/util xmlns:p=http://www.springframework.org/schema/p xsi:schemaLocation=http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd></beans> <!-- @Controllers --> <context:component-scan base-package=com.devil.space.controller,com.devil.space.rest /> <bean class=org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping > <bean class=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter> <property name=messageConverters> <list> <ref bean=marshallingHttpMessageConverter > <bean class=org.springframework.http.converter.StringHttpMessageConverter > </list> </property> </bean> <bean id=marshallingHttpMessageConverter class=org.springframework.http.converter.xml.MarshallingHttpMessageConverter p:marshaller-ref=jaxb2Marshaller p:unmarshaller-ref=jaxb2Marshaller > <bean id=jaxb2Marshaller> <property name=schema value=classpath:/validate.xsd > <property name=classesToBeBound> <list> <value<com.devil.space.RPCRequest</value> <value<com.devil.space.RPCResponse</value> </list> </property> </bean> <bean id=viewResolver class=org.springframework.web.servlet.view.InternalResourceViewResolver> <property name=viewClass value=org.springframework.web.servlet.view.JstlView> </bean> </beans>
So if the xml file data is not as per xsd file validations,response message will be like :
“The request sent by the client was syntactically incorrect”
Thats it.You are done.!!
Now this message is kind of generic error message.If we want to know where exactly is the problem in our XML request,there are more things to be done:
1.Configuration in to rest-servlet.xml.
Add following configuration in to rest-servlet.xml:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver"> <property name="messageConverters"> <list> <ref bean="marshallingHttpMessageConverter" /> <bean class="org.springframework.http.converter.StringHttpMessageConverter" /> </list> </property> </bean>
2.Adding method for handling exception.
Lets us assume your controller class is :
@Controller @RequestMapping("/SaveXMLData") public class DownloadXMLDataEndPointController { @RequestMapping(value = "/SaveAndUpdateData", method = RequestMethod.POST) @ResponseBody public RPCResponse saveXMLRequestData( @RequestBody RPCRequest request) throws Exception { ----Logic for processing request----- RPCResponse response=new RPCResponse(); --construct response object---------- return response; } }
In the above controller class,add another method for handling exception:
@ExceptionHandler(HttpMessageNotReadableException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody RPCResponse handleXMLException(HttpMessageNotReadableException ex) { String error = "Invalid XML.Error is:-"; error = error + ex.getMessage(); String responseMessage = "FAILOVER"; RPCResponse response=new RPCResponse(); --construct response object---------- return response; }
So the complete Controller class would be :
@Controller @RequestMapping("/SaveXMLData") public class DownloadXMLDataEndPointController { @RequestMapping(value = "/SaveAndUpdateData", method = RequestMethod.POST) @ResponseBody public RPCResponse saveXMLRequestData( @RequestBody RPCRequest request) throws Exception { ----Logic for processing request----- RPCResponse response=new RPCResponse(); --construct response object---------- return response; } @ExceptionHandler(HttpMessageNotReadableException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) @ResponseBody RPCResponse handleXMLException(HttpMessageNotReadableException ex) { String error = "Invalid XML.Error is:-"; error = error + ex.getMessage(); String responseMessage = "FAILOVER"; RPCResponse response=new RPCResponse(); --construct response object---------- return response; } }
Now if we deploy the application again.And send a xml request.If there is any validation error as per our XSD file,A detail error message will be in response stating in which line in XML request is the error.
Now if there is more than one XSD files which are been used to validate more than one type of XML request,We can configure them in single XSD file.Lets there are three XSD files (ABCD.xsd,PQRS.xsd,XYZT.xsd)for validating three types of XML request..Our validate.xsd will be as
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:include schemaLocation="ABCD.xsd" /> <xs:include schemaLocation="PQRS.xsd" /> <xs:include schemaLocation="XYZT.xsd" /> </xs:schema>
That is it.Similarly we can configure more XSD files for validating different types of XML requests.
If still there is any issue that you encounter :mail me at– parry.ism@gmail.com
I tried your code but it’s not working for me. My xml is not getting validated . I have changed the xsd so that the validation fails but it is going thru fine and not hitting any exception
Here is the spring xml config
dataAccessFailure
resourceNotFound
resourceNotFound
resourceNotFound
org.acs.ecta.resource.Manuscript
org.acs.ecta.resource.ResponsePayload
and the controller is :
@Controller
public class MyController {
@Autowired
private MyService myService;
private ResponsePayload resPayload;
private static final Logger logger = LoggerFactory.getLogger(EctaController.class);
@RequestMapping(value=”/submitManuscript”,method=RequestMethod.POST)
public @ResponseBody ResponsePayload addManuscript( @RequestBody Manuscript xmlManuscript)throws Exception {
resPayload=myService.submitXMLManuscript(xmlManuscript);
return resPayload;
}
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
String handleXMLException(HttpMessageNotReadableException ex) {
String error = “Invalid XML Error is :”;
error = error + ex.getMessage();
String responseMessage = “FAILOVER”;
System.out.println(“XSD Error :”+responseMessage +”:”+error);
return error;
}
}
Please send the exception error (if any) and rest-servlet.xml file content.
Hello Parvinder,
Great post indeed. Can you also post the Spring 4 annotation based configuration for the same.
Many thanks,
Best Regards,
Chandra.
There is not much difference if we will use Spring 4 .Only change that need to do is to use @RestController instead of @Controller in the Controller class. By using @RestController in the controller class , @ResponseBody annotation is active by default and so there is no need to specify @ResponseBody in every request mapping methods in the controller class.
TҺis helps youngsters learn іn a enjoyable ɑnd easy method plus there are
sections too for teachers аnd oldsters where there ɑгe
tips about how Ƅᥱst to ɦelp kids աith classes and learning.