Apache CXFとSpringを備えたJava SOAPサーバー

画像 最近、 SOAPプロトコルについて説明し、さまざまな言語およびプラットフォームでサーバーを作成するプロセスについて説明するいくつかの記事が登場しました。 トピックを続けます。 この記事では、Apache CXFとSpring Frameworkを使用してJavaサーバーを作成する方法について説明します。 読者は、前述のプロトコルの一般的な理解と、antおよびmavenの操作を既に理解していると想定されます。 タスクをもう少し面白くするために、Webサービスを記述するWSDLスキームを指定して、初期条件を追加します。 だから...

ウィキペディアの記事からの画像。)



0.初期条件



設定したタスク:既製のWSDLスキームに基づいて、 SOAP 1.1仕様を満たすWebサービスを実装する必要があります。 「エンベロープ」を送信するためのプロトコルとして、HTTPを使用します。 したがって、タスクは2つのコンポーネントに分割できます。



最初のポイントは、次の発言をすることです。 特定のケースでは、必要な操作を手動で記述することもできますが、一般的なケースでは、インターフェイスを自動生成するツールを使用する方が便利です。



これは、元のWSDLスキームは次のようになります。

<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions name="CurrentTimeService" targetNamespace="http://artspb.me/cts" xmlns:tns="http://artspb.me/cts" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"> <wsdl:types> <xsd:schema targetNamespace="http://artspb.me/cts"> <xsd:element name="timeZoneId" nillable="true" type="xsd:string"/> <xsd:element name="currentTime" type="xsd:dateTime"/> </xsd:schema> </wsdl:types> <wsdl:message name="getCurrentTimeMsg"> <wsdl:part element="tns:timeZoneId" name="timeZoneId"/> </wsdl:message> <wsdl:message name="currentTimeMsg"> <wsdl:part element="tns:currentTime" name="currentTime"/> </wsdl:message> <wsdl:portType name="CurrentTimeService"> <wsdl:operation name="getCurrentTime"> <wsdl:input message="tns:getCurrentTimeMsg" name="getCurrentTime"/> <wsdl:output message="tns:currentTimeMsg" name="currentTime"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="CurrentTimeService_HttpBinding" type="tns:CurrentTimeService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getCurrentTime"> <soap:operation soapAction="http://artspb.me/cts" style="document"/> <wsdl:input name="getCurrentTime"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="currentTime"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="CurrentTimeService_HttpService"> <wsdl:port binding="tns:CurrentTimeService_HttpBinding" name="CurrentTimeService_HttpPort"> <soap:address location="http://localhost:8080/YetAnotherService/service/currentTimeService"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
      
      





このサービスの機能は非常にシンプルです。指定されたタイムゾーンの現在の時刻を返します。 ベルトが指定されていない場合、サービスは現在のサーバー時間を返します。



このプロセスでは、次のツールを使用します。



これらはすべてIntelliJ IDEAで使用すると非常に便利ですが、このツールはオプションです。



プロジェクト構造








プロジェクトの構造を定義します。 buildフォルダーに、antのスクリプトを保存します。 ObjectLibraryモジュールでは、ソース回路と、それによって生成されたクラスを保持します。 CurrentTimeServiceモジュールがメインモジュールになり、サービス実装を保持します。また、そこからwarファイルを収集します。



pomファイルでは、モジュールに必要な依存関係を示します。 多くの外部依存関係はありません:spring-web、log4j、cxf-rt-frontend-jaxws、cxf-rt-transports-http-これらはすべてhttp://repo1.maven.org/maven2で利用可能です。



1. WSDLスキームに基づくjava-interfaceの作成



WSDLスキームに基づいてjava-interfaceを自動的に生成するには、Apache CXFパッケージのwsdl2javaユーティリティを使用します。 元のant-scriptをわずかに変更して、Javaクラスが追加されるディレクトリを事前にクリーンアップします。 これは、将来、元の回路が変更される場合に役立ちます。 デフォルトでは、ディレクトリはクリアされないため、使用されなくなったクラスから「ガベージ」が表示される可能性があります。 この問題は、複雑な複合タイプを組み込んだ回路でよく見られます。



 <?xml version="1.0"?> <project name="BuildObject"> <property name="cxf.home" value="/home/art/tools/apache-cxf-2.5.2"/> <path id="cxf.classpath"> <fileset dir="${cxf.home}/lib"> <include name="*.jar"/> </fileset> </path> <target name="cxfWSDLToJava"> <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true"> <arg value="-verbose"/> <arg value="-d"/> <arg value="../ObjectLibrary/src/main/java"/> <arg value="../ObjectLibrary/src/main/resources/CurrentTimeService.wsdl"/> <classpath> <path refid="cxf.classpath"/> </classpath> </java> </target> <target name="regenerate.object.library"> <delete dir="../ObjectLibrary/src/main/java"/> <antcall target="cxfWSDLToJava"/> </target> </project>
      
      





このスクリプトをbuild / build.xmlファイルに配置します。 タスクregenerate.object.libraryを実行します。その結果、ObjectLibraryフォルダーで必要なインターフェイスを取得します。



 package me.artspb.cts; 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; /** * This class was generated by Apache CXF 2.5.2 * 2012-02-02T17:39:35.466+04:00 * Generated source version: 2.5.2 * */ @WebService(targetNamespace = "http://artspb.me/cts", name = "CurrentTimeService") @XmlSeeAlso({ObjectFactory.class}) @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface CurrentTimeService { @WebResult(name = "currentTime", targetNamespace = "http://artspb.me/cts", partName = "currentTime") @WebMethod(action = "http://artspb.me/cts") public javax.xml.datatype.XMLGregorianCalendar getCurrentTime( @WebParam(partName = "timeZoneId", name = "timeZoneId", targetNamespace = "http://artspb.me/cts") java.lang.String timeZoneId ); }
      
      







wsdl2javaユーティリティの助けを借りて、すぐに既製のサーバー(-serverスイッチ)とその実装(-implスイッチ)を取得できることに留意してください。 ただし、この記事のフレームワークでは、生成されたコードへの緊密なバインドを回避するために必要なインターフェイスを取得するためにのみ使用します。



2.結果のインターフェースに基づいてWebサービスを実装する



CurrentTimeServiceインターフェイスの実装を同じ名前のモジュールに配置します。 コードは簡単で、追加のコメントは不要です。



 package me.artspb.cts; import org.apache.log4j.Logger; import javax.jws.WebParam; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import java.util.GregorianCalendar; import java.util.TimeZone; public class CurrentTimeServiceImpl implements CurrentTimeService { private Logger logger = Logger.getLogger(CurrentTimeServiceImpl.class); public XMLGregorianCalendar getCurrentTime( @WebParam(partName = "timeZoneId", name = "timeZoneId", targetNamespace = "http://artspb.me/cts") String timeZoneId) { logger.debug("Operation getCurrentTime was requested."); XMLGregorianCalendar gregorianCalendar; try { gregorianCalendar = getXmlGregorianCalendar(timeZoneId); } catch (DatatypeConfigurationException e) { throw new RuntimeException(e); } logger.debug("Successful."); return gregorianCalendar; } private XMLGregorianCalendar getXmlGregorianCalendar(String id) throws DatatypeConfigurationException { TimeZone timeZone; if (!"".equals(id)) { logger.debug("TimeZoneId isn't null: " + id); timeZone = TimeZone.getTimeZone(id); } else { logger.debug("TimeZoneId is null. Will use default value."); timeZone = TimeZone.getDefault(); } GregorianCalendar gregorianCalendar = new GregorianCalendar(timeZone); return DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar); } }
      
      







次に、 に従って、serviceContext.xmlおよびweb.xmlファイルをリソースに追加します。 また、log4j.xmlを忘れないでください。 これらのファイルは、ソースコードと共にアーカイブ内にあります。記事へのリンクは、記事の最後に記載されています。 その後、サービスの実装は完了したとみなすことができ、アプリケーションを収集してそのパフォーマンスを確認することが残っています。



3.組み立てと検査



プロジェクトをビルドするには、mavenの「パッケージ」タスクを実行します。 結果のwarファイルをTomcatサーバーにデプロイします。 ポート8080で使用できると想定しています。











確認するには、soapUIプログラムを使用します。 サービスのWSDLスキームはhttp:// localhost:8080 / CurrentTimeService / service / currentTimeService?Wsdlで利用できます。これを使用して、新しいsoapUIプロジェクトを作成できます。



リクエストを送信します:

 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cts="http://artspb.me/cts"> <soapenv:Header/> <soapenv:Body> <cts:timeZoneId>PST</cts:timeZoneId> </soapenv:Body> </soapenv:Envelope>
      
      







答えが得られます。

 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <currentTime xmlns="http://artspb.me/cts">2012-02-02T08:48:24.402-08:00</currentTime> </soap:Body> </soap:Envelope>
      
      







結論の代わりに



タスクは達成されました:Webサービスはリクエストを正しく処理します。 また、生成された実装への「緊密な」バインドを回避することができました。これにより、コードがより柔軟になり、さらなる変更を行う労力を減らすことができます。



頑張って!



主なリンク:




All Articles