在开发或生产模式下运行JAX-WS Web服务

时间:2017-11-24 10:04:00

标签: java-ee glassfish jax-ws wsimport

我有一个使用wsimport(在ANT任务中)生成的Web服务,我想要处理我发送无效XML请求时出现的javax.xml.bind.UnmarshalException异常。

为了抛出这个异常,我只是向服务器发送一个不平衡的标签,然后我回来了:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
 <S:Body>
      <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
         <faultcode>S:Server</faultcode>
         <faultstring>javax.xml.bind.UnmarshalException
 - with linked exception:
[com.ctc.wstx.exc.WstxParsingException: Unexpected close tag &lt;/m:BAR>; expected &lt;/m:BR>.
 at [row,col {unknown-source}]: [16,38]]</faultstring>
      </S:Fault>
   </S:Body>
</S:Envelope>

不幸的是,在我的代码中,我看不到捕获此异常并发送回标准消息的方法,而不是自动发送客户端可能无法解析的一些webservice-internal异常。

有没有办法告诉JAX-W在生产开发模式下运行?在生产模式下,它会允许我覆盖发送的消息以回复错误的请求吗?

或者至少实现某种钩子,当JAX-WS的代码发生异常时,它会调用我的方法......

我正在Glassfish 4.1.2上运行该服务。

用于构建wsdl的Web服务的我的ANT脚本如下所示:

<!DOCTYPE project>
<project name="WSDL to Java generator" default="wsimport">  
    <path id="wsimport.classpath">
        <fileset dir="../../EAR/EarContent/lib">
            <include name="commons-beanutils-*.jar"/>
            <include name="commons-lang-*.jar"/>
            <include name="commons-logging-*.jar"/>
        </fileset>

        <fileset dir="../../Common/ant-libs">
            <include name="*.jar"/>
        </fileset>
    </path>

    <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport" classpathref="wsimport.classpath"/>

    <target name="wsimport">
        <wsimport verbose="true" wsdl="../schemas/WebService.wsdl"  wsdlLocation="../schemas/WebService.wsdl" binding="./ws-build-bindings.xjb">
            <xjcarg line="-Xannotate"/>
            <xjcarg line="-Xinheritance"/>

            <arg line="-keep"/>
            <arg line="-d ../src"/>
            <arg line="-p org.company.name.message"/>

            <arg line="-Xnocompile"/>    
        </wsimport>
    </target>
</project>

生成的界面如下所示:

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.Holder;
/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.0
 * Generated source version: 2.2
 * 
 */
@WebService(name = "WebService", targetNamespace = "http://company.com/foo/WebService/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class
})
public interface WebService {

    @WebMethod(operationName = "PublishEvent", action = "PublishEvent")
    @WebResult(name = "ResponseMessage", targetNamespace = "http://foo.bar/schema/message", partName = "response")
    public ResponseMessageType publishEvent(
        @WebParam(name = "EventMessage", targetNamespace = "http://foo.bar/schema/message", partName = "event")
        EventMessageType event);

    @WebMethod(operationName = "Request", action = "Request")
    @WebResult(name = "ResponseMessage", targetNamespace = "http://foo.bar/schema/message", partName = "response")
    public ResponseMessageType request(
        @WebParam(name = "RequestMessage", targetNamespace = "http://foo.bar/schema/message", partName = "request")
        RequestMessageType request);

    @WebMethod(operationName = "Response", action = "Response")
    public void response(
        @WebParam(name = "ResponseMessage", targetNamespace = "http://foo.bar/schema/message", mode = WebParam.Mode.INOUT, partName = "response")
        Holder<ResponseMessageType> response);

}

生成的类Service

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;    
/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.0
 * Generated source version: 2.2
 * 
 */
@WebServiceClient(name = "WebService", targetNamespace = "http://company.com/foo/WebService/", wsdlLocation = "../schemas/WebService.wsdl")
public class WebService_Service
    extends Service
{

    private final static URL WebSERVICE_WSDL_LOCATION;
    private final static WebServiceException WebSERVICE_EXCEPTION;
    private final static QName WebSERVICE_QNAME = new QName("http://company.com/foo/WebService/", "WebService");

    static {
        WebSERVICE_WSDL_LOCATION = org.company.name.message.WebService_Service.class.getResource("../schemas/WebService.wsdl");
        WebServiceException e = null;
        if (WebSERVICE_WSDL_LOCATION == null) {
            e = new WebServiceException("Cannot find '../schemas/WebService.wsdl' wsdl. Place the resource correctly in the classpath.");
        }
        WebSERVICE_EXCEPTION = e;
    }

    public WebService_Service() {
        super(__getWsdlLocation(), WebSERVICE_QNAME);
    }

    public WebService_Service(WebServiceFeature... features) {
        super(__getWsdlLocation(), WebSERVICE_QNAME, features);
    }

    public WebService_Service(URL wsdlLocation) {
        super(wsdlLocation, WebSERVICE_QNAME);
    }

    public WebService_Service(URL wsdlLocation, WebServiceFeature... features) {
        super(wsdlLocation, WebSERVICE_QNAME, features);
    }

    public WebService_Service(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public WebService_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
        super(wsdlLocation, serviceName, features);
    }

    @WebEndpoint(name = "WebServiceSOAP")
    public WebService getWebServiceSOAP() {
        return super.getPort(new QName("http://company.com/foo/WebService/", "WebServiceSOAP"), WebService.class);
    }

    @WebEndpoint(name = "WebServiceSOAP")
    public WebService getWebServiceSOAP(WebServiceFeature... features) {
        return super.getPort(new QName("http://company.com/foo/WebService/", "WebServiceSOAP"), WebService.class, features);
    }

    private static URL __getWsdlLocation() {
        if (WebSERVICE_EXCEPTION!= null) {
            throw WebSERVICE_EXCEPTION;
        }
        return WebSERVICE_WSDL_LOCATION;
    }

}

这是我对界面的实现(省略了实际工作的代码),当发出无效请求时,我无法抓住它,因为我的方法不是称为:

import javax.jws.WebService;
import javax.xml.ws.Holder;

import org.company.name.message.ErrorType.ErrorLevelEnum;
import org.company.name.message.EventMessageType;
import org.company.name.message.HeaderType;
import org.company.name.message.WebService;
import org.company.name.message.RequestMessageType;
import org.company.name.message.ResponseMessageType;

@WebService(endpointInterface = "org.company.name.message.WebService")
public class Web implements WebService {
    @Override
    public ResponseMessageType publishEvent(EventMessageType event) {
        ResponseMessageBuilder responseBuilder = new ResponseMessageBuilder();
        try
        {
            // build response here

        }
        catch (WebException exception) {
            // error building response
        }
        catch (Exception ex) {
            // general error
        }

        return responseBuilder.build();
    }

    @Override
    public ResponseMessageType request(RequestMessageType request) {
        ResponseMessageBuilder responseBuilder = new ResponseMessageBuilder();

        try
        {
            // build response here

        }
        catch (WebException exception) {
            // error building response
        }
        catch (Exception ex) {
            // general error
        }

        return responseBuilder.build();
    }

    @Override
    public void response(Holder<ResponseMessageType> response) {
        // TODO Auto-generated method stub
    }
}

1 个答案:

答案 0 :(得分:0)

使用<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.journaldev.tablayoutappbar.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" app:tabGravity="fill" app:tabMode="fixed" android:layout_height="wrap_content"/> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sample_text"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout> https://docs.oracle.com/middleware/1213/wls/WSGET/jax-ws-soaphandlers.htm#WSGET3446)修复此问题。

处理程序拦截请求,尝试SOAPHandler它(通过JAXB)并且如果抛出异常,我自定义响应消息(即通过unmarshal完全替换它messageContext.setMessage(soapFaultMessage); 1}} handleMessage的方法并将其发回(通过从SOAPHandler方法返回false

此外,值得研究一下你可以抛出的handleMessage类(https://docs.oracle.com/javase/7/docs/api/javax/xml/ws/soap/SOAPFaultException.html),并根据自己的喜好定制肥皂故障响应信息。