【问题标题】:JAX-WS - Map Exceptions to faultsJAX-WS - 将异常映射到故障
【发布时间】:2011-01-05 02:04:48
【问题描述】:

我正在使用 JAX WS 来公开 WebService。该服务的某些操作可能会产生异常。不是内部服务器异常,而是依赖于操作调用的输入参数的异常。

如果我指定我的操作会引发自定义异常,如下所示:

@WebService
@SOAPBinding(style = Style.RPC, use = Use.LITERAL)
public class MyServiceEndpointImpl implements MyServiceEndpoint {

    @WebMethod
    public void throwsException throws InvalidInputException;
}

在运行应用程序时,我最终得到以下堆栈跟踪:

 com.sun.xml.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class com.mypackage.ws.services.jaxws.InvalidInputExceptionBean is not found. Have you run APT to generate them?
    at com.sun.xml.ws.model.RuntimeModeler.getClass(RuntimeModeler.java:285)
    at com.sun.xml.ws.model.RuntimeModeler.processExceptions(RuntimeModeler.java:1006)
    at com.sun.xml.ws.model.RuntimeModeler.processRpcMethod(RuntimeModeler.java:969)
    at com.sun.xml.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:546)
    at com.sun.xml.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:370)
    at com.sun.xml.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:256)
    at com.sun.xml.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:322)
    at com.sun.xml.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:188)
    at com.sun.xml.ws.api.server.WSEndpoint.create(WSEndpoint.java:467)
    at org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:333)
    at org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:45)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:121)

@XmlRootEntity 添加到InvalidInputException 并不能解决问题。

如果这不是通过 Web 服务报告故障的推荐方法,那么还有更好的方法吗?我的异常是否应该从RuntimeException 继承并依赖传输来处理错误(即,所有内容最终都将包装在 SOAPException 中)?我希望有像 Spring-WS'SoapFaultAnnotationExceptionResolver 这样的东西。 JAX-WS 是否有类似的东西可用?

【问题讨论】:

  • 也许我应该注意到它报告为丢失的类 com.mypackage.ws.services.jaxws.InvalidInputExceptionBean 确实不存在。但我认为这是很自然的,它应该像异常状态一样生成。

标签: java web-services jax-ws


【解决方案1】:

您是否尝试使用@WebFault 注释您的异常?另外,你实现getFaultInfo()了吗?

编辑:我意识到我的回答可能不够详细。正如this thread 中提醒的那样(例如):

JAX-WS 2.0 规范要求 用注释的异常 @WebFault 必须有两个构造函数 以及一种方法【获取故障信息的getter】:

WrapperException(String message, FaultBean faultInfo)
WrapperException(String message, FaultBean faultInfo, Throwable cause)
FaultBean getFaultInfo()

WrapperException 被替换为 异常的名称,以及 FaultBean 被类替换 实现故障 bean 的名称。 故障 bean 是一个 Java bean,它 包含故障信息 并由 Web 服务客户端使用 了解故障原因。

这在 JAX-WS 规范的第 2.5 节故障中有详细说明。你的例外符合这个吗?可以发一下代码吗?


OP 是对的。根据规范 2.1,第 3.7 节服务特定异常,不需要使用 @WebFault 注释,JAX-WS 可以为与第 2.5 节中描述的模式不匹配的异常动态生成包装器 bean(只需为您希望出现在故障中的信息)。对于与第 2.5 节中描述的模式匹配的异常(即具有getFaultInfo 方法和@WebFault 注释的异常),当将异常映射到 XML 模式时,FaultBean 被用作 JAXB 的输入。

所以上面建议的解决方案(匹配第 2.5 节中描述的模式)只是一种解决方法。包装器 bean 的生成应该只适用于其他异常。而且我不知道为什么这里会失败。

【讨论】:

  • 我没有。我现在试过了,但我得到了同样的错误。但是我还需要指定@WebFault 的属性名称、targetNameSpace 和faultBean 吗?
  • 感谢您的提示,我会调查的。不,我没有实现您指定的构造函数。我读过(误读?)规范的那一部分,因为 JAX WS 实现会自动生成带有这些构造函数的异常包装器本身。我开始认为我在做一些倒退的事情......
  • 事实证明,符合您上面编写的异常样式意味着 JAX-WS 将不会为异常创建包装 bean,否则它应该这样做。所以这对我来说是一种解决方法。但是,根据规范中的“3.7 Service Specific Exception”,它应该适用于所有没有注释的异常。
  • @Pascal Thivent - 每次我寻找答案时,我都会找到你。也许我应该辞职,你可以做我的工作吗? :)
  • @PascalThivent :似乎即使在 JAX-WS 2.0 中,getFaultInfo 也是可选的。在第 3.7 节的末尾,可以找到与规范版本 2.1 中相同的示例映射。但它似乎并未得到广泛支持。
【解决方案2】:

对上述答案的补充。我最终将此作为我的 InvalidInputException 实现:

@WebFault(faultBean = "com.mypackage.ws.exception.FaultBean")
public class InvalidInputException extends Exception {

    private static final long serialVersionUID = 1L;

    private FaultBean faultBean;

    public InvalidInputException() {
        super();
    }

    public InvalidInputException(String message, FaultBean faultBean, Throwable cause) {
        super(message, cause);
        this.faultBean = faultBean;
    }

    public InvalidInputException(String message, FaultBean faultBean) {
        super(message);
        this.faultBean = faultBean;
    }

    public FaultBean getFaultInfo() {
        return faultBean;
    }
}

FaultBean 只是一个简单的 POJO,目前根本没有数据。现在,根据 JAX-WS 规范(请参阅 3.7 服务特定异常),它符合使用 @WebFault 注释的异常的要求,因此它不会为其创建包装器 bean,这可能是失败的原因。

这是一个不错的解决方法,但它不能解释问题中的错误。

【讨论】:

  • 为此+1,它拯救了我的一天:)。但这仅适用于已检查的异常,不适用于未检查的异常。任何线索...
  • @waxwing 我已经实现了一个示例,但是如果没有定义 targetNamespace 元素,我的示例就无法工作?
  • @rits 同样发生在我身上,我在 Websphere 8.5.5 上尝试过这个,它有 Axis 2 作为 JAX-WS 的服务提供者,它不能与 RuntimeException 一起工作,但它确实工作与 Websphere Liberty Profile 相同,因为它改用 Apache CXF。实际上很遗憾,因为现在我的客户需要捕获/声明异常。
猜你喜欢
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
相关资源
最近更新 更多