CXF ws client, dynamic endpoint and loading WSDL from the classpath

来源:互联网 发布:为什么雷姆受欢迎 知乎 编辑:程序博客网 时间:2024/04/19 18:56

CXF ws client, dynamic endpoint and loading WSDL from the classpath

When you allow CXF to create the client code for a webservice (based on the WSDL), this creates code like the following.

@WebServiceClient( name = "IdentityService", targetNamespace = "http://www.prolixproject.org/is",                   wsdlLocation = "file:/home/joachim/apps/java/ca/pxclient/src/main/wsdl/IdentityService.wsdl" )public class IdentityService_Service    extends Service{    public final static URL WSDL_LOCATION;    public final static QName SERVICE = new QName( "http://www.prolixproject.org/is", "IdentityService" );    public final static QName IdentityServiceImplPort =        new QName( "http://www.prolixproject.org/is", "IdentityServiceImplPort" );    static    {        URL url = null;        try        {            url = new URL( "file:/home/joachim/apps/java/ca/pxclient/src/main/wsdl/IdentityService.wsdl" );        }        catch ( MalformedURLException e )        {            System.err.println(                "Can not initialize the default wsdl from file:/home/joachim/apps/java/ca/pxclient/src/main/wsdl/IdentityService.wsdl" );            // e.printStackTrace();        }        WSDL_LOCATION = url;    }    public IdentityService_Service( URL wsdlLocation )    {        super( wsdlLocation, SERVICE );    }    public IdentityService_Service( URL wsdlLocation, QName serviceName )    {        super( wsdlLocation, serviceName );    }    public IdentityService_Service()    {        super( WSDL_LOCATION, SERVICE );    }    /** @return returns IdentityService */    @WebEndpoint( name = "IdentityServiceImplPort" )    public IdentityService getIdentityServiceImplPort()    {        return super.getPort( IdentityServiceImplPort, IdentityService.class );    }    /**     * @param features A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the features parameter will have their default values.     * @return returns IdentityService     */    @WebEndpoint( name = "IdentityServiceImplPort" )    public IdentityService getIdentityServiceImplPort( WebServiceFeature... features )    {        return super.getPort( IdentityServiceImplPort, IdentityService.class, features );    }}

This code represents two challenges.

  • The WSDL is loaded from the filesystem. While the location may be fine during development. It will likely fail once deployed.
  • The service endpoint is fixed. Depending on the deployment, this should be configurable (typically it will be different for testing and production).

The first problem seems weird. As the WSDL was needed to create the classes to access the service, why is it still needed at runtime? Apparently, this can be used for handling additional information which is allowed to change, typically extra header information like authentication.

As not all services provide the WSDL online, and you don’t want the WSDL to be searched on the file system (as this would require putting it in a specific location and assuring the location is also known in the application), the classpath sounds like the normal place to put this. If only “classpath:” URL’s would be supported. There is a solution using the classloader to supply the URL though (see code).

The next problem is that the WSDL defined the service endpoint location, but deployment may require this to be different in some cases. This is fixed by allowing the endpoint location to be overridden by a system property.

The client code (with some cleanup) then looks like this.

@WebServiceClient( name = "IdentityService", targetNamespace = "http://www.prolixproject.org/is",                   wsdlLocation = "file:/home/joachim/apps/java/ca/pxclient/src/main/wsdl/IdentityService.wsdl" )public class ProlixSso    extends Service{    public final static URL WSDL_LOCATION;    public final static QName SERVICE = new QName( "http://www.prolixproject.org/is", "IdentityService" );    public final static QName IDENTITY_SERVICE_IMPL_PORT =        new QName( "http://www.prolixproject.org/is", "IdentityServiceImplPort" );    static    {        ClassLoader cl = Thread.currentThread().getContextClassLoader();        if ( null == cl ) cl = ProlixSso.class.getClassLoader();        WSDL_LOCATION = cl.getResource( "be/progs/ca/pxclient/wsdl/IdentityService.wsdl" );    }    public ProlixSso()    {        super( WSDL_LOCATION, SERVICE );    }    /** @return returns IdentityService */    @WebEndpoint( name = "IdentityServiceImplPort" )    public IdentityService getIdentityServiceImplPort()    {        IdentityService proxy = super.getPort( IDENTITY_SERVICE_IMPL_PORT, IdentityService.class );        ( (BindingProvider) proxy ).getRequestContext().put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, getUrl() );        return proxy;    }    /**     * @param features A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the features parameter will have their default values.     * @return returns IdentityService     */    @WebEndpoint( name = "IdentityServiceImplPort" )    public IdentityService getIdentityServiceImplPort( WebServiceFeature... features )    {        IdentityService proxy = super.getPort( IDENTITY_SERVICE_IMPL_PORT, IdentityService.class, features );        ( (BindingProvider) proxy ).getRequestContext().put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, getUrl() );        return proxy;    }    private static String getUrl()    {        String res = System.getProperty( "ca.prolix.identityservice.url" );        if ( null == res ) res = "http://testportal.prolix-dev.de/prolixservices/jbi/IdentityService/";        return res;    }}
原创粉丝点击