Web Services 如何自定义JAX-WS RuntimeException响应?

e5njpo68  于 2023-11-22  发布在  其他
关注(0)|答案(2)|浏览(209)

我试图自定义在到达WebMethod之前抛出的RuntimeException的错误响应,例如无效的xml主体或JAX-WS服务的错误方法名称。我试图使用@HandlerChain的处理程序,但响应在处理程序处理之前发送。
这里有一个例子。假设我在我的ws中有一个copyTool方法,但客户端发送了下面的请求。我希望能够自定义响应,以便我可以更改faultString或返回一些自定义faultCode。

输入

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:cor="http://acme.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <cor:copyTool>
       <toolNumber>some Text instead of Integer</toolNumber>
      </cor:copyTool>
   </soapenv:Body>
</soapenv:Envelope>

字符串

输出

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns0:Fault xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2003/05/soap-envelope">
         <faultcode>ns0:Server</faultcode>
         <faultstring>Exception Description: The object [some Text instead of Integer], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[toolNumber-->toolNumber/text()]] with descriptor [XMLDescriptor(com.acme --> [DatabaseTable(ns0:copyTool)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "some Text instead of Integer"</faultstring>
      </ns0:Fault>
   </S:Body>
</S:Envelope>

kg7wmglp

kg7wmglp1#

我认为你可以尝试使用ExceptionMapper,如下所示:

@Provider
public class WebApplicationExceptionMapper implements ExceptionMapper<Exception>{

    @Override
    public Response toResponse(Exception exception) {
        Response.Status responseStatus = THE_STATUS_YOU_WANT_BASED_ON_THE_EXCEPTION;
        return Response.status(responseStatus).entity(THE_ERROR_ENTITY_YOU_WANT_BASED_ON_THE_EXCEPTION).build();
    }

}

字符串

hmae6n7t

hmae6n7t2#

我可以通过@HandlerChainRuntimeException自定义故障消息。我猜你做错了什么。

一步一步的过程中,我做了什么,使它的工作:

我创建了一个示例项目来演示。

项目结构(Maven项目):

x1c 0d1x的数据

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>customize-fault-jaxws</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.3.7</version>
        </dependency>
    </dependencies>

</project>

字符串

PublishLotteryService:

package org.example.endpoint;

import org.example.webservice.LotteryServiceImpl;

import javax.xml.ws.Endpoint;

public class PublishLotteryService {

    public static void main(String[] args) {
        Endpoint.publish("http://localhost:8080/webservice/lottery", new LotteryServiceImpl());
    }

}

LotteryService(一种WebService接口):

package org.example.webservice;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;

@WebService
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL)
public interface LotteryService {

    @WebMethod(operationName = "SendYourNameAndWinLottery")
    String sendYourNameAndWinLottery(String nameOfThePerson);

}

LotteryServiceImpl(一种WebService实现):

package org.example.webservice;

import javax.jws.HandlerChain;
import javax.jws.WebService;

@WebService(endpointInterface = "org.example.webservice.LotteryService")
@HandlerChain(file = "custom-fault-message.xml")
public class LotteryServiceImpl implements LotteryService {

    @Override
    public String sendYourNameAndWinLottery(String nameOfThePerson) {
        return "Hi, " + nameOfThePerson + ". You are one of the lucky winners. You won a $1000 USD.";
    }
}

注意:您必须通过创建一个具有任意名称的处理程序链.xml文件并将该**. xml**文件设置/引用到@HandlerChain中,来告诉您的WebService使用@HandlerChain
custom-fault-message.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains 
     xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <javaee:handler-chain>
    <javaee:handler>
      <javaee:handler-class>org.example.handler.CustomizeFaultMessageHandler</javaee:handler-class>
    </javaee:handler>
  </javaee:handler-chain>
</javaee:handler-chains>

自定义错误消息提示:

package org.example.handler;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;

public class CustomizeFaultMessageHandler implements SOAPHandler<SOAPMessageContext> {

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        try {
            SOAPBody body = context.getMessage().getSOAPPart().getEnvelope().getBody();
            SOAPFault soapFault = body.getFault();
            soapFault.setFaultCode("random-code");
            soapFault.setFaultString("place your custom error message here.");
        } catch (SOAPException e) {
            System.out.println(e.getMessage());
        }
        return true;
    }

    @Override
    public void close(MessageContext context) {
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

}

需要注意的一些重要事项:

你必须在handleMessage(SOAPMessageContext context)中从false设置return true;。否则,它不会进入handleFault(SOAPMessageContext context)来处理Fault相关的事情。
现在,你可以看到这样的代码:

SOAPBody body = context.getMessage().getSOAPPart().getEnvelope().getBody();
SOAPFault soapFault = body.getFault();
soapFault.setFaultCode("random-code");
soapFault.setFaultString("place your custom error message here.");


我只是获取默认的Fault,并在这里使用我的自定义Fault CodeFault Message覆盖它。现在,当前的SOAPMessageContext使用包含我的自定义值的Fault进行更新。这就是您需要做的所有事情。

输出(成功案例):
输入XML请求负载:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <SendYourNameAndWinLottery xmlns="http://webservice.example.org/">
            <arg0 xmlns="">Anish</arg0>
        </SendYourNameAndWinLottery>
    </Body>
</Envelope>

输出XML响应:

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:SendYourNameAndWinLotteryResponse xmlns:ns2="http://webservice.example.org/">
            <return>Hi, Anish. You are one of the lucky winners. You won a $1000 USD.</return>
        </ns2:SendYourNameAndWinLotteryResponse>
    </S:Body>
</S:Envelope>


输出(失败,自定义错误消息):

我已经将soap主体名称SendYourNameAndWinLottery篡改为错误的名称SendYourNameAndWin以进行测试。

XML请求负载不正确:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <SendYourNameAndWin xmlns="http://webservice.example.org/">
            <arg0 xmlns="">Anish</arg0>
        </SendYourNameAndWin>
    </Body>
</Envelope>

输出XML响应:

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <S:Body>
        <S:Fault xmlns="" xmlns:ns3="http://www.w3.org/2003/05/soap-envelope">
            <faultcode xmlns="">random-code</faultcode>
            <faultstring>place your custom error message here.</faultstring>
        </S:Fault>
    </S:Body>
</S:Envelope>


相关问题