Metro JAX-WS

Webサービスを作るのもアノテーション使って楽ちんになってたのね。
でもサービスを公開する側(サーバ側)はAXIS2は組み込みの仕方がいまだにわからんので。
他にないかと調べてたらGlassfishがMetroていうプロダクトも作っててどうもこれが組み込み簡単ぽそう。

準備

環境はこんな感じ。
Eclipse 3.7 Indigo(ちょい前にDLしてたpleiades-e3.7-java-jre_20110924.zip)
JavaSE 7 update3
Ant1.8.3
Tomcat7(Pleiades同梱の)
Metroをダウンロード→Metro 2.2 download
あとJAVA_HOMEとANT_HOME、CATALINA_HOMEを環境変数に追加してPATHにも追加。

Metroのインスト

> ant -Dcatalina.home=%CATALINA_HOME% -f metro-on-tomcat.xml install

これでTomcatの共有ライブラリにJarがコピーされる。
次にJDK7の更新。
これはJDK7付属のJAX-WSが2.1のため(Metroは2.2のRI)

> mkdir %JAVA_HOME%\jre\lib\endorsed

作成したendorsedフォルダにmetro/lib/webservices-api.jarをコピー。

eclipseの設定

インストしたJDK7をインストール済みJREに追加。


Pleiadesで初めから入っているJREでもシステムライブラリに「webservices-api.jar」を一番上に追加でもいいかも?

サービスクラスの作成

Tomcatプロジェクトを作成しておもむろにサービスクラスを作成。
(プロジェクトのシステムライブラリは追加したJREのJDK7)

package sample.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public class HelloWorld {

    @WebMethod
    public String hello(@WebParam String param) {
        return param + " World";
    }
}

ただのPOJOに「@WebServiceアノテーションを付与。
publicなメソッドは「@WebMethod」を付与しなくてもいいぽい。

jaxws.xmlの作成

サービスエンドポイントを定義するsun-jaxwx.xmlをWEB-INF直下に作成。

<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>
    <endpoint
        name="hello"
        implementation="sample.service.HelloWorld"
        url-pattern="/service/HelloWorld.ws"/>
</endpoints>

web.xmlの作成(編集)

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>wsservlet</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>wsservlet</servlet-name>
        <url-pattern>*.ws</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
</web-app>

デプロイ&起動

Tomcat Launcherで起動して次のURLにアクセス。
http://localhost:8080/jax-wx/service/HelloWorld.ws
こんな画面が表示されれば成功。

クライアントの作成

WSDLが手に入ったので今度はクライアント側のスタブを作成。
これはWsImport Ant Taskを使って生成。

<?xml version="1.0" encoding="utf-8"?>
<project name="HelloWorld" basedir="." default="wsdl2java">
    <property name="metro.home" value="../metro2.2"/>

    <path id="metro.classpath">
        <fileset dir="${metro.home}/lib">
            <include name="*.jar"/>
        </fileset>
    </path>

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

    <target name="wsdl2java">
        <wsimport
            wsdl="http://localhost:8080/jax-ws/service/HelloWorld.ws?wsdl"
            sourcedestdir="src"
            destdir="classes"
            package="sample.client"
            xnocompile="yes">
        </wsimport>
    </target>
</project>

生成したスタブはもちろんJAX-WS2.2準拠になってるのでプロジェクトで使用しているJREにMetro2.2のwebservices-api.jarが無いとコンパイルエラーになる。
クライアント部分のソースはこちら。

public class Client {
    public static void main(String[] args) throws Exception {
        HelloWorldService ws = new HelloWorldService();
        HelloWorld proxy = ws.getHelloWorldPort();
        // サービス呼び出し
        System.out.println(proxy.hello("Hello"));
    }
}

おまけ:javaからWSDL生成

axisでjava2wsdlがあるんだしと調べたらすぐしたにあった。

<?xml version="1.0" encoding="utf-8"?>
<project name="HelloWorld" basedir="." default="java2wsdl">
    <property name="metro.home" value="../metro2.2"/>

    <path id="metro.classpath">
        <fileset dir="${metro.home}/lib">
            <include name="*.jar"/>
        </fileset>
    </path>

    <taskdef name="wsgen" classname="com.sun.tools.ws.ant.WsGen">
        <classpath refid="metro.classpath"/>
    </taskdef>

    <target name="java2wsdl" depends="init">
        <wsgen
            sei="sample.service.HelloWorld"
            sourcedestdir="src"
            destdir="classes"
            resourcedestdir="wsdl"
            genwsdl="true">
            <classpath path="WEB-INF/classes"/>
        </wsgen>
    </target>
</project>

wsgenタスクでWSDLだけ作って欲しいんだけど、スタブも作成されるのが…。


EclipseでAntを実行したときにエラーでてwsgenが止まる場合、外部ツール構成でランタイムを指定すればOK。


Ant Taskの詳細は以下。
Tools 3. wsimport Ant Task
Tools 5. wsgen Ant Task