JAx-ws WebServiceに関する問題(一)

12346 ワード

1.JDK 6持参のJAX-WS+Jboss 4を使用する.2.3 WebServiceを開発してWebServiceのエラーを報告しますか?java.lang.ClassNotFoundException: com.sun.xml.ws.transport.http.servlet.WSServletContextListener
 
JDK自体はサーブレットベースのコードを持たず、持参したjax-wsはWServeretとWServeretContextListenerの2つのクラスを持たず、j 2 eeのjarパッケージにしかありません
 
ソリューション:
a.コードのEndpointを使用する.publish()リリース(軽量級HTTP Server);
       
Endpoint.publish("http://localhost:8080/HelloService", new HelloSEI());

欠点は、コードのリリースごとに面倒で、修正も面倒で、IPとポートごとに1つしかリリースできないことです.
 
b.Springが持参したSimpleJaxWsServiceExporterを使用してリリースする(軽量級HTTP Server);
       
<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
    <property name="baseAddress" value="http://localhost:8080/"/>
</bean>

<bean id="accountServiceEndpoint" class="example.AccountServiceEndpoint">
    ...
</bean>

欠点は、IPとポートごとに1つしかパブリッシュできないことです.
 
c.jaxws-springを使用する.JArが提供するWSSpringService方式パブリケーション(サーブレットパブリケーション):
これは2つの追加jarパッケージを使用する必要があります.
        jaxws-spring-1.8.jar
        xbean-spring-v2-2.8.jar
構成:
        web.xml
<web-app>
  <!-- this is for Spring -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- these are for JAX-WS -->
  <servlet>
    <servlet-name>jaxws-servlet</servlet-name>
    <servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>jaxws-servlet</servlet-name>
    <url-pattern>/add</url-pattern>
  </servlet-mapping>
  ... if you deploy more services,
  you might need more <servlet-mapping>s ...
</web-app>

    
    applicationContext.xml
    
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ws="http://jax-ws.java.net/spring/core"
  xmlns:wss="http://jax-ws.java.net/spring/servlet"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://jax-ws.java.net/spring/core
    http://jax-ws.java.net/spring/core.xsd
    http://jax-ws.java.net/spring/servlet
    http://jax-ws.java.net/spring/servlet.xsd">

  <wss:binding url="/add" service="#addService" />
  <wss:binding url="/sub">
    <wss:service><!-- nested bean is of course fine -->
      <ws:service bean="#myService" />
    </wss:service>
  </wss:binding>

  <!-- this bean implements web service methods -->
  <bean id="myService" class="foo.MyService" />

  <!-- simplest definition only needs the class name -->
  <ws:service id="addService" impl="foo.MyAddService" handlers="#myHandler"/>

  <bean id="myHandler" class="foo.MyHandler" />

</beans>

 
2.Client側が同じようにjboss webコンテナに配置する場合、クライアントはjavaを呼び出す.lang.ClassCastException: com.sun.xml.ws.client.WSServiceDelegate cannot be cast to javax.xml.ws.spi.ServiceDelegate21
 
これは、JBOSSが独自のjax-ws apiを実装しているため、jbosswsと呼ばれています.apiクラスの競合を引き起こします.
ソリューション:
JDK全体のJAX-WS実装に関するクラスをJBOSSをロードするJAX-WS API実装クラスに置き換えるという考え方である.
 
方法はjboss/lib/endorsed/ディレクトリの下にあります.
                  jboss-jaxrpc.jar
                  jboss-jaxws.jar
                  jboss-jaxws-ext.jar
                  jboss-saaj.jar
                  xercesImpl.jar
%JAVAにコピーHOME%/jre/endorsed/ディレクトリの下にあります.(JDKのendorsedメカニズムを使用していますので、関連資料を参照してください)
JDKのendorsedディレクトリはSystem.getProperty(「java.endorsed.dirs」)を取得します.WebコンテナでどのJDKを使うかは、そのJDKの下で修正する必要があります.
 
3.パブリッシュされたwsdlの中でimportがwsdlとxsdファイルを持っている場合、クライアントは毎回Addressingにアクセスします.ローカルwarパッケージの中のxsdとwsdlとパブリッシュされたサービスをバインドするにはどうすればいいですか?
説明:これはWSのメカニズムによるもので、JAX-WSは公式に解決策を提供しています.
ソリューション:jax-ws-catalogを追加する方法で、ローカルのxsdとwsdlをバインドします.
 
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer=" system"> 
    < system systemId=" http://foo.org/hello?wsdl" uri="HelloService.wsdl"/> 
</catalog>

 
Jax-ws-catalog.xmlの配置位置:
Øwsimportコマンドラインまたはantタスク
-catalogオプションパラメータを使用してcatalog fileを指定します.例:
-catalog jax-ws-catalog.xml
 
ØWebServiceクライアントランタイム環境
Classpathの下のこのディレクトリ:META-INF/jax-ws-catalog.xml
(.jarパッケージのMETA-INF/jax-ws-catalog.xmlも)
 
Ø軽量レベルのHTTPサーバ(j 2 se)に基づくendpointリリース
つまりインタフェースを呼び出すことでpublish()で、HttpServerを指定します.
Springの軽量レベルのパブリケーション支援クラスでパブリッシュされたものを含む:
org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter
org.springframework.remoting.jaxws.SimpleHttpServerJaxWsServiceExporter
Classpathの下のこのディレクトリ:META-INF/jax-ws-catalog.xml
 
Øサーブレットベースendpoint
WEB-INF/jax-ws-catalog.xml
 
ØJSR 109規格に基づくEJBモジュールのリリース
META-INF/jax-ws-catalog.xml
【備考】
筆者はCXFをwebserviceとして実現する際にjax-ws-catalogを指定する.xmlは解析をうまくロードできます.ただし、JDKが持つjax-wsまたはMetro jax-ws RIを使用する場合は、JBOSSをパブリッシュコンテナとして使用する、jax-ws-catalogを常に正しく実行することはできない.xmlに記述するimport wsdl/xsdschema参照の置換は、jndiによってjax-ws-catalogにアクセスすることがさらにデバッグされた.xmlですが、ローカルwsdl/xsdを使用する効果はありません.
 
4.endpointを使用して、1つのservcenameの下に複数のportnameがあるWebServiceをパブリッシュする方法
how to publish multi port webservice with same serviceName?
解釈:一般的にJAX-WS RI上の例やSpringの2つのhttp Stand alone publishパブリケーションアシストクラス(前述:Springの軽量レベルパブリケーションアシストクラス)を見ても、この方面の資料は見られません.マルチポート使用が比較的少ないためです.
ソリューション:Springが提供するhttp endpoint pubishクラスの拡張:AbstractJaxWsServiceExporter.
@WebService注記を持つSpring beanに初期化されたendpointパブリケーションクラスを自動的に解析し、構成されたbasepathに基づいてパブリッシュし、アドレスをパブリッシュします.http://hostname:port/basepath/serviceName/portName
 
コード:
import java.net.InetSocketAddress;
import java.util.List;


import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import javax.xml.ws.WebServiceProvider;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.jaxws.AbstractJaxWsServiceExporter;


import com.sun.net.httpserver.Authenticator;
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;


public class PortableHttpServerJaxWsServiceExporter extends
    AbstractJaxWsServiceExporter
{
    private static final Logger LOG = LoggerFactory.getLogger(PortableHttpServerJaxWsServiceExporter.class);
    
    public PortableHttpServerJaxWsServiceExporter()
    {
        port = 8080;
        backlog = -1;
        shutdownDelay = 0;
        basePath = "/";
        localServer = false;
    }


    public void setServer(HttpServer server)
    {
        this.server = server;
    }


    public void setPort(int port)
    {
        this.port = port;
    }


    public void setHostname(String hostname)
    {
        this.hostname = hostname;
    }


    public void setBacklog(int backlog)
    {
        this.backlog = backlog;
    }


    public void setShutdownDelay(int shutdownDelay)
    {
        this.shutdownDelay = shutdownDelay;
    }


    public void setBasePath(String basePath)
    {
        this.basePath = basePath;
    }


    public void setFilters(List<Filter> filters)
    {
        this.filters = filters;
    }


    public void setAuthenticator(Authenticator authenticator)
    {
        this.authenticator = authenticator;
    }


    @Override
    public void afterPropertiesSet() throws Exception
    {
        if (server == null)
        {
            InetSocketAddress address = (hostname == null ? new InetSocketAddress(
                port)
                : new InetSocketAddress(hostname, port));
            server = HttpServer.create(address, backlog);
            if (logger.isInfoEnabled())
                logger.info((new StringBuilder(
                    "Starting HttpServer at address ")).append(address)
                    .toString());
            server.start();
            localServer = true;
            
            LOG.info("Start http server successful. hostname: {}, port: {}", hostname, port);
        }
        super.afterPropertiesSet();
    }


    @Override
    protected void publishEndpoint(Endpoint endpoint, WebService annotation)
    {
        endpoint.publish(buildHttpContext(endpoint, annotation.serviceName(),
            annotation.portName()));
    }


    @Override
    protected void publishEndpoint(Endpoint endpoint,
        WebServiceProvider annotation)
    {
        endpoint.publish(buildHttpContext(endpoint, annotation.serviceName(),
            annotation.portName()));
    }


    protected HttpContext buildHttpContext(Endpoint endpoint,
        String serviceName, String portName)
    {
        String fullPath = calculateEndpointPath(endpoint, serviceName, portName);
        HttpContext httpContext = server.createContext(fullPath);
        if (filters != null)
            httpContext.getFilters().addAll(filters);
        if (authenticator != null)
            httpContext.setAuthenticator(authenticator);
        
        LOG.info("Listen http context at full path : {}.", httpContext.getPath());
        
        return httpContext;
    }


    protected String calculateEndpointPath(Endpoint endpoint,
        String serviceName, String portName)
    {
        if (null == portName)
        {
            return (new StringBuilder(String.valueOf(basePath))).append(
                serviceName).toString();
        }
        return (new StringBuilder(String.valueOf(basePath)))
            .append(serviceName).append("/").append(portName).toString();
    }


    @Override
    public void destroy()
    {
        super.destroy();
        if (localServer)
        {
            logger.info("Stopping HttpServer");
            server.stop(shutdownDelay);
        }
    }


    protected final Log logger = LogFactory.getLog(getClass());


    private HttpServer server;


    private int port;


    private String hostname;


    private int backlog;


    private int shutdownDelay;


    private String basePath;


    private List<Filter> filters;


    private Authenticator authenticator;


    private boolean localServer;
}

 
配布方法:
<bean class="com.huawei.ossj.ws.publisher.PortableHttpServerJaxWsServiceExporter">
        <property name="basePath" value="/" />
        <property name="port" value="19900" />
    </bean>