Enabling SOAP request validation in JBOSS 5.0 using JAX-WS

By default, JBoss JAX-WS Web services doesn’t validate SOAP requests for a valid xml or schema. This is by default in order to prevent performance overhead.
This may turn into a problem when developing the web service, since a required attribute in the schema may not be present in the request and the request will arrive to our service with no further notice. In many cases, this behavior is not a problem, you just need to consider in your web service that a null value may come for a required attribute.

So, Why validate?

  • Enforce schema
  • Sometimes it is good to enforce the schema validation when the request must comply with the schema, for example, when an attribute is required, or when the request must contain a list with exactly 2 elements but no more. Basically, when the request needs to comply with the xsd of the element. Validation in these cases is an aid for development, since the developer wouldn’t need to verify if the request has the required attributes.

  • Prevent default behavior
  • There are cases when the client can mispell a tag of the request, for example if the request has an attribute to filter the modification of a DB using a <filter> tag. If the client mispells the request and sends a <filters> tag instead of <filter> when no validation is enabled, the server will think that the client doesn’t need any filter (JBoss will set the filter variable to null), thus altering the behavior of the processing, updating all the rows in the DB without filtering, probably leading to disaster.

Validation in JBoss

In JBoss there is a simple way to enforce validation for the Web Service SOAP requests using the @SchemaValidation annotation. At the beginning, the use of the annotation seemed to be trivial, but after some unsuccessful attempts I found out that an extra effort was needed to get it going. This tutorial explains the simple steps needed to enable schema validation for JBoss and JAX-WS.

We start with a simple web service IMyWebService and the implementing class MyWebService, which has only one WebMethod getResponse, which receives one parameter param1. You can download the full project from here. It’s an eclipse Java project.
The parameter param1 is of class Param1 which has 2 fields:

private String param1Str;
private Integer param1Int;

After deploying the test project, using Soap UI to call the web service, we first import the wsdl from: http://localhost:8080/WSTest/WebService?wsdl
Calling the web service with the following message:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:type="http://test/com/wsTest/ws/type">
	<soapenv:Header/>
	<soapenv:Body>
		<type:param1>
			<param1Int>10</param1Int>
			<param1Str>TestString</param1Str>
		</type:param1>
	</soapenv:Body>
</soapenv:Envelope>

We can see the following log in the server console (we are just printing out the input values):

19:17:24,824 INFO  [STDOUT] 10
19:17:24,824 INFO  [STDOUT] TestString

So far so good, but until now we didn’t add any requirements on the fields. Let’s make the param1Str attribute required by adding the following annotation in the Param1 class:

@XmlElement(required=true)
public String getParam1Str() {
	return param1Str;
}

After redeploying WSTest and running the test case again we’d expect the server to reject the message due to validation errors, but this isn’t the case. As discussed earlier, JBoss disables SOAP request validation by default.
In order to enable validation, we need to do the following steps:

  1. Create a schema file with the declared elements from the wsdl
  2. Enable @SchemaValidation pointing to the schema file

Let’s discuss these points

Create a schema file with the declared elements from the wsdl

First, we need to create a schema file containing the elements we are going to use in the web service request. This may seem a time consuming task, but following these steps it should become really easy.
Create an xsd file, for example: schema.xsd using the following skeleton

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
	targetNamespace="<same_as_target_namespace_in_wsdl>"
	xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="<same_as_target_namespace_in_wsdl>">
	<!-- elements -->
	<xs:element name="param1" nillable="true" type="ns1:param1"/>
	...
	<!-- types -->
	<xs:complexType name="param1">
		...
	</xs:complexType>
	...
</xs:schema>

1. Replace the values of with the namespace used for the definitions of the wsdl. To find this, you will need to point your browser to the published wsdl ( http://localhost:8080/WSTest/WebService?wsdl ), navigate through the imported wsdl until you find the type definitions. Use the targetNamespace of the elements defined. In this case: http://test/com/wsTest/ws/type

2. Copy the <element> tags into the schema file.
3. Copy the <complexType> tags into the schema file.
After this, the schema.xsd should look like this (containing the elements of param1 and result1, complexType for param1 and result1):

<xs:schema elementFormDefault="qualified" version="1.0"
	targetNamespace="http://test/com/wsTest/ws/type" xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:ns1="http://test/com/wsTest/ws/type">
	<!-- elements -->
	<xs:element name="param1" nillable="true" type="ns1:param1" />
	<xs:element name="result1" nillable="true" type="ns1:result1" />
	<!-- types -->
	<xs:complexType name="param1">
		<xs:sequence>
			<xs:element minOccurs="0" name="param1Int" type="xs:int" />
			<xs:element name="param1Str" type="xs:string" />
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="result1">
		<xs:sequence />
	</xs:complexType>
</xs:schema>

After creating the file, we need to put it in an accessible place for the application, for example META-INF/xsd/schema.xsd

Enable @SchemaValidation

We need to tell JBoss that it needs to validate the incoming requests for the web service we are publishing. In order to do this, we’ll simply add the following annotation in the implementing class of the web service, pointing to the schema file in the schemaLocation attribute.

@WebService(endpointInterface = "com.wsTest.ws.IMyWebService", serviceName = "MyWebService", name = "MyWebService", portName = "MyWebServicePort")
@SchemaValidation(enabled = true ,schemaLocation="META-INF/xsd/schema.xsd")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class MyWebService implements IMyWebService {

After deploying and running the application, JBoss will start logging messages saying that it is validating the request/responses

16:41:33,608 INFO  [SOAPBodyElementDoc] Validating: XML_VALID
16:41:33,623 INFO  [STDOUT] 10
16:41:33,623 INFO  [STDOUT] TestString
16:41:33,623 INFO  [SOAPBodyElementDoc] Validating: XML_VALID

Removing the param1Str from the Soap UI request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:type="http://test/com/wsTest/ws/type">
	<soapenv:Header/>
	<soapenv:Body>
		<type:param1>
			<param1Int>10</param1Int>
		</type:param1>
	</soapenv:Body>
</soapenv:Envelope>

Issuing this request will lead to a validation error in JBoss:

16:48:11,052 INFO  [SOAPBodyElementDoc] Validating: XML_VALID
16:48:11,052 ERROR [StrictlyValidErrorHandler] org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'param1Int'. One of '{"http://test/com/wsTest/ws/type":param1Int, "http://test/com/wsTest/ws/type":param1Str}' is expected.
16:48:11,068 ERROR [SOAPFaultHelperJAXWS] SOAP request exception
org.jboss.ws.WSException: org.xml.sax.SAXException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'param1Int'. One of '{"http://test/com/wsTest/ws/type":param1Int, "http://test/com/wsTest/ws/type":param1Str}' is expected.
	at org.jboss.ws.WSException.rethrow(WSException.java:68)
	at org.jboss.ws.core.soap.SOAPBodyElementDoc.validatePayload(SOAPBodyElementDoc.java:130)
	at org.jboss.ws.core.soap.SOAPBodyElementDoc.transitionTo(SOAPBodyElementDoc.java:82)
	at org.jboss.ws.core.soap.SOAPContentElement.getObjectValue(SOAPContentElement.java:172)

And the corresponding error response in Soap UI:

e xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
   <env:Header/>
   <env:Body>
      <env:Fault>
         <faultcode>env:Server</faultcode>
         <faultstring>org.xml.sax.SAXException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'param1Int'. One of '{"http://test/com/wsTest/ws/type":param1Int, "http://test/com/wsTest/ws/type":param1Str}' is expected.</faultstring>
      </env:Fault>
   </env:Body>
</env:Envelope>

From this point, validating more complex requests shouldn’t be a difficult task. You can download the resulting source code from here. Open it as an Eclipse project or use the source code from your favorite IDE.

I hope this post makes your life easier enabling soap request validation for JBoss. Please let me know if this is your case or if you have any comments or difficulties.

Advertisements

25 responses to “Enabling SOAP request validation in JBOSS 5.0 using JAX-WS

      • Thanks very much for replying. I tried this but it didn’t work. I am using EJB3 stateless bean and using jax-ws annotations (@WebService etc) to within a Jar (my app is not a web application). I am using Jboss 7.1.0.Final and I used CXF maven plugin to generate Java types from wsdl. Any reason it wouldn’t work in a Jar?

      • That’s strange, it should also work this way… I wonder if this changed in that version of JBoss. Can you develop a simple test app if this is the case? You can send it to me, and I’ll test it in JBoss 5.1, and see what’s happening…

      • how to write custom error handler in jboss by extracting wsdl schemas and validation against it

  1. Hi iam trying to transfer file using web services jaxws via stub bt it can’t make object of stub so kindly pls help me to sortout that prblm.

  2. Interesting, looks like the same mechanics from @SchemaValidation,s jaxws-ri. But in the latter I havent found how to send a custom Fault to the client instead of the default. Is it possible with JBOSS ?

      • thanks for the answer. My question was precisely in fact how to throw a custom @WebFault annoted exception in one of the org.xml.sax.ErrorHandler method you can attach to the @SchemaValidation. I havent seen any sort of example of how to do it. For ex: how do I hint the WS stack to propagate my custom Fault:

        class MyHandler implments ErrorHandler{
        void error(SAXParseException exception) {
        MyCustomFault fault = new MyCustomFault();
        //propagate it to the WS stack, how ?
        }

  3. Yeah I ve already tried wrapping the fault in a SAXException. The problem is the WS stack (at least with the ri, havent tried with JBoss) doesnt fetch the cause to see this is a WebFault so the client recieves a default Fault (not the custom) from the default error mapping.

      • Yep tried too, the problem is because you get a ‘low level in the stack’ xml schema validation error, you dont get to the Java WebMethod in the WS pipeline so you dont have any chance to do what is suggested in the blog (throwing a clean custom WebFault for instance).
        Guess the spec didnt cover that particular use case, so we are stuck with the default handling 😦
        thanks though if you have other ideas 🙂

  4. Hi There,
    I am using JAX-WS RI 2.1.6 and as per ur post added the @org.jboss.ws.annotation.SchemaValidation annotation to enable schema validation. But JAX-WS framework is only validating simple XML errors(non matching end tag etc). It isnt validating the request xml as per my schema i.e. if a mandatory element is missing, it is not catching it.

    Any idea what could be the problem ?

    if you still have your project, can you please share it?

    • Hi, in JBoss you must add the schemaLocation attribute to enable schema validation. In RI you should try com.sun.xml.ws.developer.SchemaValidation annotation.

  5. Thanks for the very well written how to. I was excited to grab the source and try it out myself but it appears that it was removed or is no longer visible. Could you maybe re-post that link to the complete src. Thanks

  6. I’m trying but it doesn’t work. I’m using JBoss 5.1.0GA with default instance.
    When I start the server, after deploying, Jboss doesn’t log messages about validating the request/responses. When I try to change the request in soapUi, sending a wrong request, the validation doesn’t work, because it’s not enabled. Do you think it could be a Jboss version problem? What instance of Jboss do you start?

      • Hi Pinuz, thanks for you comment. Please try downloading the source of the completed project, I just tried it and it works in jboss 5.1 EAP, it should also work on AS.
        The annotation is: org.jboss.ws.annotation.SchemaValidation

      • No, ok, I downloaded the source, but it’s without libs. Can you tell me please which jar contains SchemaValidation? The jar and the version, please. Thank you

      • I’m using eclipse with maven, I need to know the jboss jar with the SchemaValidation class

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s