CXFからwsdl2Javaを使用して(wsimportに似たものを生成する)Webサービスクライアントを生成すると、mavenを介して、私のサービスは次のようなコードで始まります。
@WebServiceClient(name = "StatusManagement",
wsdlLocation = "c:/some_absolute_path_to_a_wsdl_file.wsdl",
targetNamespace = "http://tempuri.org/")
public class StatusManagement extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
static {
URL url = null;
try {
url = new URL("c:/some_absolute_path_to_a_wsdl_file.wsdl");
} catch (MalformedURLException e) {
System.err.println("Can not initialize the default wsdl from c:/some_absolute_path_to_a_wsdl_file.wsdl");
// e.printStackTrace();
}
WSDL_LOCATION = url;
}
ハードコードされた絶対パスは本当にひどいものです。生成されたクラスは、私以外のコンピューターでは機能しません。
最初のアイデアは、WSDLファイル(およびインポートするすべてのもの、他のWSDL、XSD)をjarファイルのどこかに置き、クラスパスにすることです。しかし、私たちはこれを避けたいです。そのすべてがWSDLおよびXSDに基づいたCXFおよびJAXBによって生成されたため、実行時にWSDLを知る必要はありません。
WsdlLocation属性は、WSDLの場所をオーバーライドすることを目的としています(少なくともこれはどこかで読んだものです)。デフォルト値は ""です。 Mavenを使用しているため、CXFの構成内に<wsdlLocation></wsdlLocation>
を含めて、ソースジェネレーターにwsdlLocationを空白のままにしようと試みました。ただし、これはXMLタグが空なので、XMLタグを無視するだけです。 <wsdlLocation>" + "</wsdlLocation>
を使用して、ひどく恥ずべきハックを行いました。
これにより、他の場所も変更されます。
@WebServiceClient(name = "StatusManagement",
wsdlLocation = "" + "",
targetNamespace = "http://tempuri.org/")
public class StatusManagement extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://tempuri.org/", "StatusManagement");
public final static QName WSHttpBindingIStatus = new QName("http://tempuri.org/", "WSHttpBinding_IStatus");
static {
URL url = null;
try {
url = new URL("" + "");
} catch (MalformedURLException e) {
System.err.println("Can not initialize the default wsdl from " + "");
// e.printStackTrace();
}
WSDL_LOCATION = url;
}
だから、私の質問は:
すべてのクラスがCXFおよびJAXBによって生成された場合でも、本当にWSDLの場所が必要ですか?はいの場合、なぜですか?
WSDLの場所が本当に必要ない場合、CXFがそれを生成せず、完全に回避しないようにする適切でクリーンな方法は何ですか?
このハックで得られる悪影響は何ですか?まだ何が起こるかを確認するためにそれをテストすることはできませんので、誰かが事前に言うことができれば、それは素晴らしいでしょう。
今日、ついにこの質問に対する正しい答えを見つけました。
<plugin>
<groupId>org.Apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${project.basedir}/src/main/resources/wsdl/FooService.wsdl</wsdl>
<wsdlLocation>classpath:wsdl/FooService.wsdl</wsdlLocation>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2Java</goal>
</goals>
</execution>
</executions>
</plugin>
wsdlLocation
の値の先頭にclasspath:
が付いていることに注意してください。これは、wsdlが絶対パスではなくクラスパス上にあることをプラグインに伝えます。次に、次のようなコードが生成されます。
@WebServiceClient(name = "FooService",
wsdlLocation = "classpath:wsdl/FooService.wsdl",
targetNamespace = "http://org/example/foo")
public class Foo_Service extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://org/example/foo", "Foo");
public final static QName FooSOAPOverHTTP = new QName("http://org/example/foo", "Foo_SOAPOverHTTP");
static {
URL url = Foo_Service.class.getClassLoader().getResource("wsdl/FooService.wsdl");
if (url == null) {
Java.util.logging.Logger.getLogger(Foo_Service.class.getName())
.log(Java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "classpath:wsdl/FooService.wsdl");
}
WSDL_LOCATION = url;
}
これは、バージョン2.4.1以降のcxf-codegen-pluginでのみ機能することに注意してください。
を使用しております
wsdlLocation = "WEB-INF/wsdl/WSDL.wsdl"
つまり、クラスパスに関連するパスを使用します。
マーシャリング/アンマーシャリング中のメッセージの検証には、実行時にWSDLが必要になると思います。
org.jvnet.jax-ws-commons:jaxws-maven-plugin
を使用して、ビルド時にWSDLからクライアントを生成する場合:
src/main/resources
のどこかに配置しますwsdlLocation
の前にclasspath:
を付けるwsdlLocation
の前に/
を付けてください例:
/src/main/resources/foo/bar.wsdl
に保存されますjaxws-maven-plugin
および<wsdlDirectory>${basedir}/src/main/resources/foo</wsdlDirectory>
を使用して<wsdlLocation>/foo/bar.wsdl</wsdlLocation>
を構成する1)場合によっては、はい。 WSDLにポリシーなど、実行時の動作を指示するものが含まれている場合、実行時にWSDLが必要になる場合があります。ポリシー関連のものなどのアーティファクトは生成されません。また、いくつかのあいまいなRPC /リテラルの場合、必要なすべての名前空間が生成されたコードで出力されるわけではありません(仕様ごと)。したがって、それらにはwsdlが必要になります。ただし、あいまいなケース。
2)何かがうまくいくと思った。 CXFのバージョンそれはバグのように聞こえます。そこに空の文字列(スペースのみ)を試すことができます。それが機能するかどうかはわかりません。つまり、コードでは、WSDL URLを取得してnullを渡すコンストラクターを使用できます。 wsdlは使用されません。
3)上記の制限のみ。
Wsdl2javaの使用を回避できる可能性はありますか?すぐにCXFフロントエンドAPIを使用して、SOAP Webサービスを呼び出すことができます。唯一の問題は、クライアント側でSEIとVOを作成する必要があることです。サンプルコードを次に示します。
package com.aranin.weblog4j.client;
import com.aranin.weblog4j.services.BookShelfService;
import com.aranin.weblog4j.vo.BookVO;
import org.Apache.cxf.jaxws.JaxWsProxyFactoryBean;
public class DemoClient {
public static void main(String[] args){
String serviceUrl = "http://localhost:8080/weblog4jdemo/bookshelfservice";
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(BookShelfService.class);
factory.setAddress(serviceUrl);
BookShelfService bookService = (BookShelfService) factory.create();
//insert book
BookVO bookVO = new BookVO();
bookVO.setAuthor("Issac Asimov");
bookVO.setBookName("Foundation and Earth");
String result = bookService.insertBook(bookVO);
System.out.println("result : " + result);
bookVO = new BookVO();
bookVO.setAuthor("Issac Asimov");
bookVO.setBookName("Foundation and Empire");
result = bookService.insertBook(bookVO);
System.out.println("result : " + result);
bookVO = new BookVO();
bookVO.setAuthor("Arthur C Clarke");
bookVO.setBookName("Rama Revealed");
result = bookService.insertBook(bookVO);
System.out.println("result : " + result);
//retrieve book
bookVO = bookService.getBook("Foundation and Earth");
System.out.println("book name : " + bookVO.getBookName());
System.out.println("book author : " + bookVO.getAuthor());
}
}
ここで完全なチュートリアルを見ることができます http://weblog4j.com/2012/05/01/developing-soap-web-service-using-Apache-cxf/
生成できました
static {
WSDL_LOCATION = null;
}
wsdlurlにnullを持つようにpomファイルを構成することにより:
<plugin>
<groupId>org.Apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${basedir}/target/generated/src/main/Java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/service.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-wsdlLocation</extraarg>
<wsdlurl />
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2Java</goal>
</goals>
</execution>
</executions>
</plugin>
CXF 3.1.7用の更新
私の場合、WSDLファイルをsrc/main/resources
に配置し、このパスをEclipseのSroucesに追加しました(プロジェクト->ビルドパス->ビルドパスの構成...->ソース[タブ]->フォルダーの追加)。
pom
ファイルがどのように見えるかを以下に示します。ご覧のとおり、wsdlLocation
オプションは必要ありません。
<plugin>
<groupId>org.Apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>classpath:wsdl/FOO_SERVICE.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2Java</goal>
</goals>
</execution>
</executions>
</plugin>
そして、これが生成されたサービスです。ご覧のとおり、URLは絶対ファイルパスからではなく、ClassLoaderから取得されます
@WebServiceClient(name = "EventService",
wsdlLocation = "classpath:wsdl/FOO_SERVICE.wsdl",
targetNamespace = "http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/")
public class EventService extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/", "EventService");
public final static QName EventPort = new QName("http://www.sas.com/xml/schema/sas-svcs/rtdm-1.1/wsdl/", "EventPort");
static {
URL url = EventService.class.getClassLoader().getResource("wsdl/FOO_SERVICE.wsdl");
if (url == null) {
Java.util.logging.Logger.getLogger(EventService.class.getName())
.log(Java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "classpath:wsdl/FOO_SERVICE.wsdl");
}
WSDL_LOCATION = url;
}
真剣に、トップの答えは私のために働いていません。 cxf.version 2.4.1および3.0.10を試しました。毎回wsdlLocationで絶対パスを生成します。
私の解決策は、wsdl2Java
でApache-cxf-3.0.10\bin\
コマンドを-wsdlLocation classpath:wsdl/QueryService.wsdl
と共に使用することです。
詳細:
wsdl2Java -encoding utf-8 -p com.jeiao.boss.testQueryService -impl -wsdlLocation classpath:wsdl/testQueryService.wsdl http://127.0.0.1:9999/platf/testQueryService?wsdl