JAX-WS RI不强制执行XSD限制

时间:2011-10-13 12:52:57

标签: validation xsd jax-ws restriction

我目前正在使用JAX-WS参考实现(版本2.1.7)开发一些Web服务。它们是基于契约的,也就是说,WSDL和XSD文件不是由wsgen生成的。

这允许我自由使用XSD限制来加强对通过SOAP消息传递给我的服务的值的验证。以下是此类“受限制”XSD元素的两个示例:

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

我将@SchemaValidation注释添加到我的服务类中以强制执行模式验证。但是,JAX-WS不会按预期强制执行验证规则。行为如下:

  • 正确报告缺少必需元素(例如,缺少maxResults)。
  • 也会正确报告无效值(例如,整数字段中的字符数据)。
  • 间隔限制违规(例如,maxResults&gt; 1000或maxResults&lt; 1)在没有报告的情况下通过验证过程,并被注入到我的JAXB生成的Java结构中。即使是xsd:positiveInteger类型,即使负值也被视为有效!
  • 不报告字符串长度约束违规(例如,lastName长度超过25个字符)。

换句话说,<xsd:element>标记中出现的限制被正确实施,但在基于JAX-WS的上下文中使用时,JAXB似乎完全忽略了<xsd:restriction>个元素。

我编写了一个测试类,使用裸JAXB(无JAX-WS)来检查我的XSD限制。因此,所有限制都得到了正确执行。

这让我觉得JAX-WS在使用JAXB时可能存在错误...除非我做错了什么,当然......

我错过了一些基本的东西吗?!?

提前感谢您的帮助,

杰夫

2 个答案:

答案 0 :(得分:2)

我终于找到了什么错误......

为了让我的Web服务在JUnit上下文中工作,即通过Endpoint.publish()发布,我必须从wsdlLocation注释中删除@WebService属性。如果不这样做,则传递给wsdlLocation = "WEB-INF/wsdl/SearchIndividualsV1_0.wsdl"注释的@WebService会与传递给Endpoint.publish()方法{1}}的网址值冲突。

在阅读Glen Mazza的博客(http://www.jroller.com/gmazza/entry/soap_xml_schema_validation),附加说明部分后,我放回了http://127.0.0.1:9000/rpe-ws/SearchIndividuals属性,现在所有限制都已正确执行。

换句话说,删除wsdlLocation注释中的wsdlLocation并不会阻止服务本身工作,但会阻止@WebService元素中声明的限制被正确实施。但是,<xsd:restrictions>元素中声明的限制仍然可以正确执行。

因此,我回到必须解决<xsd:element>兼容性问题以使我的单元测试正常工作,但这比生产环境中的非工作验证更不重要...

以防万一...在非Web上下文中运行Web服务时,任何人都知道这个WSDL位置不兼容吗?

谢谢,

杰夫

答案 1 :(得分:0)

哦,兄弟!...

为了覆盖我的JUnit测试的wsdlLocation,我创建了仅覆盖@WebService注释的Web服务实现的派生。结果,我遇到了今天早上我终于解决的同样问题(参见我上面的第一个答案)。

经过大量测试后,我发现存在一个@WebService - 带注释的类,扩展了我的Web服务实现,阻止了XSD验证正确处理<xsd:restriction>标记。

为了说明这种奇怪的行为,我们假设我有以下类:

@WebService(...)
public interface JeffWebService {...}

@WebService(..., wsdlLocation = "path/myWsdl.wsdl", ...)
public class JeffWebServiceImpl implements JeffWebService {...}

其中path/myWsdl.wsdl正确定位WSDL。然后XSD验证工作正常,即我上面第一个答案的内容完全有效。

我现在在基于JUnit的Endpoint.publish()调用中添加以下类:

@WebService(..., wsdlLocation = "alternatePath/myWsdl.wsdl", ...)
public class TestWebServiceImpl extends JeffWebServiceImpl {}

除了@WebService注释之外什么都不会覆盖。然后,在完全指定<xsd:restriction>属性之前,XSD验证会像以前一样排除wsdlLocation标记,尽管事实上我仍在我的非JUnit代码中使用JeffWebServiceImpl实现!如果我在TestWebServiceImpl中注释掉注释,那么除了单元测试之外,一切都能正常工作。

换句话说,只要有一些类在类路径中扩展我的Web服务实现,最具体的类的@WebService注释会覆盖所有其他类,而不管我在常规Web中使用的实际类应用背景。很奇怪,不是吗?!?

底线:我现在将禁用基于端点的单元测试。如果我(或任何阅读此线程的人)找到一种干净的,非虚假的方式来集成生产和JUnit配置,我会考虑将它们放回我的JUnit测试套件中。

我希望这个帖子可以帮助遇到同样问题的人解决问题的速度比我做得快......

杰夫