CXF または JAX-WS で生成された Web サービス クライアントで WSDL の場所を指定する必要性を回避するにはどうすればよいでしょうか? 質問する

CXF または JAX-WS で生成された Web サービス クライアントで WSDL の場所を指定する必要性を回避するにはどうすればよいでしょうか? 質問する

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;
    }

私の質問は次のとおりです。

  1. すべてのクラスが CXF と JAXB によって生成された場合でも、WSDL の場所は本当に必要ですか?必要な場合は、その理由は何ですか?

  2. WSDL の場所が本当に必要ない場合、CXF が WSDL を生成しないようにし、完全に回避する適切でクリーンな方法は何ですか?

  3. このハッキングによって、どのような悪い副作用が生じる可能性があるのでしょうか? まだ何が起こるかテストできないので、誰かが事前に教えてくれると嬉しいです。

ベストアンサー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>

の値の前に を付けていることに注意してくださいwsdlLocationclasspath:これにより、プラグインは 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 以降でのみ機能することに注意してください。

おすすめ記事