Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use CXF client in thread safe way

I have created the client stub for below service using apache-cxf's wsdl2java command. http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL


Then I invoke the getWeatherInformation() method as below.

Weather weatherService = new Weather();
WeatherSoap weatherSoap = weatherService.getWeatherSoap();
ArrayOfWeatherDescription result = weatherSoap.getWeatherInformation();

I have read that cxf clients are thread safe. But I have a doubt whether it is safe to use the same WeatherSoap instance accross multiple threads? Or instead should/can I use an instance of Weather class, accross multiple threads? Thanks.

EDIT:


What I do is I have exposed a RESTful API to public and if somebody calls that rest service I call another SOAP service. Above code is used to call the SOAP service. What I want to know is should I execute all the above lines for each rest request or can I reuse an instance of Weather or WeatherSoap to serve all the REST requests.
like image 692
prageeth Avatar asked Mar 16 '15 14:03

prageeth


1 Answers

Yes CXF is thread safe, you can use single instance/singleton for Weather and WeatherSoap, you can think of cxf as similar to servlet engine which handles all the infrastructure for you such as transport, databinding for you. I had similar usecase, where I had a front end presentation layer and number of network servers, to interact between these I had a rest for presentation and SOAP which implements business logic as well as interacts with servers. Hence I implemented a soap client in rest layer. I had requirement were I needed split rest request and invoke parallel soap calls which had time delays 800ms. I performance tested the entire setup and did not run-up into any thread issues.

So coming into to client implementation

Pure Java

public class MySoapClient{

  private static WeatherSoap weatherSoap;

  private MySoapClient(){
  }

  public static WeatherSoap getClient(){

    if(weatherSoap==null){
        Weather weatherService = new Weather();
        weatherSoap= weatherService.getWeatherSoap();
    }
    return weatherSoap;
  }

}

And I would modify the Weather class to get SOAP url from properties file.

@WebServiceClient(name = "Weather", 
                  wsdlLocation = "classpath:weather.wsdl",
                  targetNamespace = "http://ws.cdyne.com/WeatherWS/") 
public class Weather extends Service {

    private static final Logger LOG = LoggerFactory.getLogger(Weather.class);
    public final static URL WSDL_LOCATION;
    public final static QName SERVICE = new QName("http://ws.cdyne.com/WeatherWS/", "Weather");
    public final static QName WeatherHttpPost = new QName("http://ws.cdyne.com/WeatherWS/", "WeatherHttpPost");
    public final static QName WeatherHttpGet = new QName("http://ws.cdyne.com/WeatherWS/", "WeatherHttpGet");
    public final static QName WeatherSoap12 = new QName("http://ws.cdyne.com/WeatherWS/", "WeatherSoap12");
    public final static QName WeatherSoap = new QName("http://ws.cdyne.com/WeatherWS/", "WeatherSoap");
    static {
        URL url = null;
        try {
            url = new URL(MyPropertiesUtil.getProperty("app.weather.url"));
        } catch (MalformedURLException e) {
            LOG.error(e.getMessage(), e);
        }
        if (url == null) {
            LOG.error("an issue with your url");
        }       
        WSDL_LOCATION = url;   
    }

    public Weather(URL wsdlLocation) {
        super(wsdlLocation, SERVICE);
    }

    public Weather(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public Weather() {
        super(WSDL_LOCATION, SERVICE);
    }


    //All the other interface methods

}

Using Spring

if you are using spring you can make things even simpler, you can eliminate Weather.java class by using configuration file as shown below and let cxf generate proxy for you.

<jaxws:client id="weatherSoap" serviceClass="com.cdyne.ws.weatherws.WeatherSoap" address="${app.weather.url}" />

And Business Class would look like below.

@Component
MyBusinessLogic{

  @Autowired
  private WeatherSoap weatherSoap;

  public ArrayOfWeatherDescription getOutput(){
    return weatherSoap.getWeatherInformation();
  }

}
like image 141
Karthik Prasad Avatar answered Sep 19 '22 13:09

Karthik Prasad