Reputation: 1010
I am currently developing a few Web services using the JAX-WS reference implementation (version 2.1.7). They are contract-based, that is, the WSDL and XSD files are not generated by wsgen.
This allows me to freely use XSD restrictions to strengthen validation of values passed to my services through SOAP messages. Here are two examples of such "restricted" XSD elements:
<xsd:element name="maxResults" minOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="1000"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="lastName" minOccurs="0">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:minLength value="1"/>
<xsd:maxLength value="25"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
I added the @SchemaValidation
annotation to my service classes to enforce schema validation. However, JAX-WS does not enforce validation rules as expected. The behaviour is as follows:
maxResults
).maxResults
> 1000 or maxResults
< 1) pass through the validation process without being reported and are injected into my JAXB-generated Java structures. Even negative values are considered valid despite the xsd:positiveInteger
type!lastName
length over 25 characters) are not reported either.In other words, restrictions that appear in <xsd:element>
tags are correctly enforced but <xsd:restriction>
elements seem to be totally ignored by JAXB when used in a JAX-WS-based context.
I wrote a test class to check my XSD restrictions using bare JAXB (no JAX-WS). As a result, all restrictions are correctly enforced.
This gives me the feeling that there might be a bug in the usage of JAXB by JAX-WS... unless there is something I am doing incorrectly, of course...
Am I missing something fundamental here?!?
Thanks in advance for any help,
Jeff
Upvotes: 5
Views: 8267
Reputation: 1010
Oh brother!...
In order to override the wsdlLocation
for my JUnit tests, I created derivations of my Web service implementations that override only the @WebService
annotation. As a result, I ran into the same problem I finally solved this morning (ref. my first answer above).
After doing plenty of tests, I figured out that it's the presence of a @WebService
-annotated class extending my Web service implementation that prevents XSD validation from properly handling <xsd:restriction>
tags.
To illustrate this bizarre behaviour, let's suppose I have the following classes:
@WebService(...)
public interface JeffWebService {...}
@WebService(..., wsdlLocation = "path/myWsdl.wsdl", ...)
public class JeffWebServiceImpl implements JeffWebService {...}
where path/myWsdl.wsdl
correctly locates the WSDL. Then XSD validation works properly, i.e. the content of my first answer above is totally valid.
I now add the following class that I use in my JUnit-based Endpoint.publish()
calls:
@WebService(..., wsdlLocation = "alternatePath/myWsdl.wsdl", ...)
public class TestWebServiceImpl extends JeffWebServiceImpl {}
that overrides nothing but the @WebService
annotation. Then XSD validation excludes <xsd:restriction>
tags as it used to do before specifying the wsdlLocation
attribute at all, despite the fact that I still use the JeffWebServiceImpl
implementation in my non-JUnit code! If I comment out the annotation in TestWebServiceImpl
, then everything works properly again, except for unit tests, of course.
In other words, as soon as there is some class extending my Web service implementation in the classpath, the @WebService
annotation of the most specific class overrides all others, regardless of the actual class I use in a regular Web application context. Weird, isn't it?!?
Bottom line: I will disable Endpoint-based unit tests for now. If I (or anyone reading this thread) find a clean, non-bogus way to integrate both production and JUnit configurations, I will consider putting them back in my JUnit test suite.
I hope this thread will help anyone running into the same problem solve it faster than I did...
Jeff
Upvotes: 1
Reputation: 1010
I finally found what's wrong...
In order to get my Web services to work in a JUnit context, i.e. published through Endpoint.publish()
, I had to remove the wsdlLocation
attribute from my @WebService
annotations. If I don't, the wsdlLocation = "WEB-INF/wsdl/SearchIndividualsV1_0.wsdl"
passed to the @WebService
annotation clashes with the URL value passed to the Endpoint.publish()
method, http://127.0.0.1:9000/rpe-ws/SearchIndividuals
.
After reading Glen Mazza's Weblog (http://www.jroller.com/gmazza/entry/soap_xml_schema_validation), Additional Notes section, I put back the wsdlLocation
attribute and all restrictions are now properly enforced.
In other words, removing the wsdlLocation
in a @WebService
annotation does not prevent the service itself from working, but prevents restrictions declared in <xsd:restrictions>
elements from being properly enforced. Restrictions declared in <xsd:element>
elements, however, are still correctly enforced.
I am therefore getting back to having to solve that wsdlLocation
compatibility problem to make my unit tests work properly, but this is way less critical than non-working validations in a production context...
Just in case... Anyone has an idea about this WSDL location incompatibility when running a Web service in a non-Web context?
Thanks,
Jeff
Upvotes: 3