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:
Weather
or WeatherSoap
to serve all the REST requests.
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With