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);
欠点は、コードのリリースごとに面倒で、修正も面倒で、IPとポートごとに1つしかリリースできないことです.
b.Springが持参したSimpleJaxWsServiceExporterを使用してリリースする(軽量級HTTP Server);
欠点は、IPとポートごとに1つしかパブリッシュできないことです.
c.jaxws-springを使用する.JArが提供するWSSpringService方式パブリケーション(サーブレットパブリケーション):
これは2つの追加jarパッケージを使用する必要があります.
jaxws-spring-1.8.jar
xbean-spring-v2-2.8.jar
構成:
web.xml
applicationContext.xml
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をバインドします.
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
コード:
配布方法:
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>