Maven 経由で CXF から wsdl2java を使用して Web サービス クライアントを生成すると (wsimport に似たものを生成します)、サービスは次のようなコードで開始されます。
@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 を使用しているため、<wsdlLocation></wsdlLocation>
CXF の構成内に含めて、ソース ジェネレーターが wsdlLocation を空白のままにするように強制しようとしました。ただし、これは 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 が WSDL を生成しないようにし、完全に回避する適切でクリーンな方法は何ですか?
このハッキングによって、どのような悪い副作用が生じる可能性があるのでしょうか? まだ何が起こるかテストできないので、誰かが事前に教えてくれると嬉しいです。
ベストアンサー1
今日、ようやくこの質問に対する正しい答えが分かりました。
<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;
}
これは、cxf-codegen-plugin のバージョン 2.4.1 以降でのみ機能することに注意してください。