4

我目前正在使用 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> 1000 或maxResults< 1)通过验证过程而不被报告,并被注入到我的 JAXB 生成的 Java 结构中。尽管有类型,即使是负值也被认为是有效的xsd:positiveInteger
  • 字符串长度约束违规(例如,lastName长度超过 25 个字符)也不会报告。

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

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

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

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

提前感谢您的帮助,

杰夫

4

2 回答 2

2

我终于找到了问题所在...

为了让我的 Web 服务在 JUnit 上下文中工作,即通过 发布,我必须从我的注释Endpoint.publish()中删除该wsdlLocation属性。@WebService如果我不这样做,wsdlLocation = "WEB-INF/wsdl/SearchIndividualsV1_0.wsdl"传递给注释的值与传递给方法@WebService的 URL 值冲突, .Endpoint.publish()http://127.0.0.1:9000/rpe-ws/SearchIndividuals

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

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

因此,我不得不重新解决该wsdlLocation兼容性问题以使我的单元测试正常工作,但这比生产环境中的非工作验证更不重要......

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

谢谢,

杰夫

于 2011-10-14T13:22:37.283 回答
0

哦兄弟!...

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

在进行了大量测试之后,我发现是存在一个@WebService-annotated 类扩展了我的 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 验证完全排除<xsd:restriction>了在指定属性之前所做的标记wsdlLocation,尽管事实上我仍然JeffWebServiceImpl在我的非 JUnit 代码中使用该实现!如果我注释掉 中的注释TestWebServiceImpl,那么一切都会再次正常运行,当然,单元测试除外。

换句话说,只要在类路径中有某个类扩展了我的 Web 服务实现,@WebService最具体的类的注释就会覆盖所有其他类,而不管我在常规 Web 应用程序上下文中使用的实际类是什么。很奇怪不是吗?!?

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

我希望这个帖子能帮助遇到同样问题的人比我更快地解决它......

杰夫

于 2011-10-14T18:02:08.740 回答