Skip to main content

JAX WS clients

8 replies [Last post]
Anonymous

Hi ,

Is there a way in terms of best practices to use web service clients ?

Should services need to be cache ?

Is the port thread safe ?

Creating a service is an expensive operation ?

What about creating a port ?

Also when a client is generated is better to copy the WSDL definition
locally no ?

When a security policy is applied there are caching mechanism for policy
files ? or custom ones need to be done ?

Sorry for so many questions . but i saw a lot of WEB apps where on each
call a new service and new port is created (this impels reading
wsdls,policy file etc and for me it looks not so optimum)

Thanks !

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
al130959
Offline
Joined: 2005-09-28
Points: 0

Hi Cristian,

Am 02.07.2012 13:53, schrieb Cristian Chiovari:
> Is there a way in terms of best practices to use web service clients ?
> Should services need to be cache ?
> Is the port thread safe ?
> Creating a service is an expensive operation ?
> What about creating a port ?
Yes, creating a Service object by far is the most expensive operation,
but the good news is that Service objects are thread-safe and can
therefore easily be cached and reused.

The spec does not mandate Port and Dispatch objects to be thread-safe
(as they may e.g. contain call-specific parameters via the
BindingProvider's request/response contexts). They are more
light-weight, but from my personal point of view still worth being
cached in some way:

What you can do here as a best practice is either (unfortunately, by
hand) create and manage a pool of Port/Dispatch instances and assign
them to your worker threads as needed, or - maybe as a more simplistic
variant - use a static ThreadLocal to store a dedicated Port/Dispatch
instance for each of your web app's web service client worker threads.
The additional memory requirements for doing so typically are tolerable.

> Also when a client is generated is better to copy the WSDL definition
> locally no ?
Mark has already provided a pretty comprehensive reply to this question :-)

> When a security policy is applied there are caching mechanism for
> policy files ? or custom ones need to be done ?
I am afraid I think the correct reply here is that this depends from
your particular JAX-WS implementation. While AFAIK, Metro does not offer
any way to dynamically adjust your policy based on a Port or Dispatch
object, I think that the WLS JAX-WS implementation (which basically is a
variant of Metro with some WLS-specific features) allows to dynamically
adjust your policy via the BindingProvider object (see above).

I think the best thing here is to simply cache properly configured Port
or Dispatch objects that use the appropriate security policy - this
should then work across any implementation.

> Sorry for so many questions . but i saw a lot of WEB apps where on
> each call a new service and new port is created (this impels reading
> wsdls,policy file etc and for me it looks not so optimum)
Fully agreed - I've also seen lots of them and always try to teach my
customers the above basics... ;-)

> Thanks !
You're welcome...

HTH & best regards,

Andreas

Cristian Chiovari

Thanks a lot Andreas and Mark for the answers.

So caching of Service or Ports is a good practice indeed.

Once caching is used then it is solved even the problem of reading (locally) the wsdls and policies.

But what about SOAP over JMS WS ? Same principles apply ?

I recently read about how to properly use JMS connections . https://community.jboss.org/wiki/ShouldICacheJMSConnectionsAndJMSSessions

When regular WS clients are used over HTTP a JEE container would not be able to somehow cache all this like it is done for JMS ? (maybe not now but in the next specs ? somehow ?

(at least JBOSS does that for JMS ,and i am in the process of studying if Weblogic has this via JCA for JMS)

Cheers .

On 02 Jul 2012, at 18:25, Andreas Loew wrote:

> Hi Cristian,
>
> Am 02.07.2012 13:53, schrieb Cristian Chiovari:
>> Is there a way in terms of best practices to use web service clients ?
>> Should services need to be cache ?
>> Is the port thread safe ?
>> Creating a service is an expensive operation ?
>> What about creating a port ?
> Yes, creating a Service object by far is the most expensive operation, but the good news is that Service objects are thread-safe and can therefore easily be cached and reused.
>
> The spec does not mandate Port and Dispatch objects to be thread-safe (as they may e.g. contain call-specific parameters via the BindingProvider's request/response contexts). They are more light-weight, but from my personal point of view still worth being cached in some way:
>
> What you can do here as a best practice is either (unfortunately, by hand) create and manage a pool of Port/Dispatch instances and assign them to your worker threads as needed, or - maybe as a more simplistic variant - use a static ThreadLocal to store a dedicated Port/Dispatch instance for each of your web app's web service client worker threads. The additional memory requirements for doing so typically are tolerable.
>
>> Also when a client is generated is better to copy the WSDL definition locally no ?
> Mark has already provided a pretty comprehensive reply to this question :-)
>
>> When a security policy is applied there are caching mechanism for policy files ? or custom ones need to be done ?
> I am afraid I think the correct reply here is that this depends from your particular JAX-WS implementation. While AFAIK, Metro does not offer any way to dynamically adjust your policy based on a Port or Dispatch object, I think that the WLS JAX-WS implementation (which basically is a variant of Metro with some WLS-specific features) allows to dynamically adjust your policy via the BindingProvider object (see above).
>
> I think the best thing here is to simply cache properly configured Port or Dispatch objects that use the appropriate security policy - this should then work across any implementation.
>
>> Sorry for so many questions . but i saw a lot of WEB apps where on each call a new service and new port is created (this impels reading wsdls,policy file etc and for me it looks not so optimum)
> Fully agreed - I've also seen lots of them and always try to teach my customers the above basics... ;-)
>
>> Thanks !
> You're welcome...
>
> HTH & best regards,
>
> Andreas
>

mcs130
Offline
Joined: 2006-01-26
Points: 0

I can offer one opinion with regard to the question of packaging of
WSDL/XSDs *locally*.

*Yes* - it is much better/efficient to have your build process (be it Ant
or Maven) produce a JAR file where the */META-INF/wsdl *folder of that JAR
contains the WSDL/XSD files. Both tools that are often used to produce
client-side artifacts (*wsimport *for JAX-RS RI/Metro and *wsdl2Java *for
CXF) provide options that allow you to specify the *wsdlLocation
*property/attribute.

By "localizing" the WSDL/XSD files within the JAR, you are packaging the
Java artifacts with the WSDL/XSD files from which they were generated...
and you are saving a wire call to get a WSDL which is dynamically served
from the deployed/running endpoint. If anything in that WSDL changed,
subsequent to the time you generated your artifacts, you will have problems
anyway and localization spares you that mess.

If you look at the generated code using such a practice, you will see a
Service proxy class created that looks like this:

package com.acme.book.webservices;

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;

/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.5-b01
* Generated source version: 2.1
*
*/
@WebServiceClient(name = "BookOrderManagerService", targetNamespace = "
http://webservices.book.acme.com/", wsdlLocation =
"/META-INF/wsdl/BookOrderManagerService.wsdl")
*public class BookOrderManagerService_Service
extends Service*
{

private final static URL BOOKORDERMANAGERSERVICE_WSDL_LOCATION;
private final static WebServiceException
BOOKORDERMANAGERSERVICE_EXCEPTION;
private final static QName BOOKORDERMANAGERSERVICE_QNAME = new QName("
http://webservices.book.acme.com/", "BookOrderManagerService");

static {
*BOOKORDERMANAGERSERVICE_WSDL_LOCATION =
com.acme.book.webservices.BookOrderManagerService_Service.class.getResource("/META-INF/wsdl/BookOrderManagerService.wsdl");
*
WebServiceException e = null;
if (BOOKORDERMANAGERSERVICE_WSDL_LOCATION == null) {
e = new WebServiceException("Cannot find
'/META-INF/wsdl/BookOrderManagerService.wsdl' wsdl. Place the resource
correctly in the classpath.");
}
BOOKORDERMANAGERSERVICE_EXCEPTION = e;
}

public BookOrderManagerService_Service() {
super(__getWsdlLocation(), BOOKORDERMANAGERSERVICE_QNAME);
}

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

/**
*
* @return
* returns BookOrderManagerService
*/
@WebEndpoint(name = "BookOrderManagerServicePort")
public BookOrderManagerService getBookOrderManagerServicePort() {
return super.getPort(new QName("http://webservices.book.acme.com/",
"BookOrderManagerServicePort"), BookOrderManagerService.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 BookOrderManagerService
*/
@WebEndpoint(name = "BookOrderManagerServicePort")
public BookOrderManagerService
getBookOrderManagerServicePort(WebServiceFeature... features) {
return super.getPort(new QName("http://webservices.book.acme.com/",
"BookOrderManagerServicePort"), BookOrderManagerService.class, features);
}

private static URL __getWsdlLocation() {
if (BOOKORDERMANAGERSERVICE_EXCEPTION!= null) {
throw BOOKORDERMANAGERSERVICE_EXCEPTION;
}
return BOOKORDERMANAGERSERVICE_WSDL_LOCATION;
}

}

When you run your client code, you will see that during the instantiation
of the proxy object, it will NOT call over the wire and will, in fact, read
this from the JAR file itself. Notice in the code above how the URL is set
using a class.getResource() method and a generated helper method called
__getWsdlLocation(). This particular code was generated with *wsimport *tool
but you will see very similar code if you use CXF and use its *wsdl2Java *
tool.

We have done this as a standard practice for a long time and it has worked
well.

Hope that helps - at least for that question.

On Mon, Jul 2, 2012 at 7:53 AM, Cristian Chiovari <
> wrote:

> Hi ,
>
> Is there a way in terms of best practices to use web service clients ?
>
> Should services need to be cache ?
>
> Is the port thread safe ?
>
> Creating a service is an expensive operation ?
>
> What about creating a port ?
>
> Also when a client is generated is better to copy the WSDL definition
> locally no ?
>
> When a security policy is applied there are caching mechanism for policy
> files ? or custom ones need to be done ?
>
> Sorry for so many questions . but i saw a lot of WEB apps where on each
> call a new service and new port is created (this impels reading
> wsdls,policy file etc and for me it looks not so optimum)
>
> Thanks !
>

Cristian Chiovari

Indeed this approach is the one I tried to impose at my workplace as well.
But still i was not satisfied with this improvement.
I mean it can be better because even if i have this wsdl's locally in the jar bundled, on each call if the services are not cached
there is a read from the filesystem and that adds some delay (even if small) but when you have thousands of simultaneous calls it might matter.

But as Andreas suggested caching the services , even ports ,solves this problem as well…

Still wonder if there might be a mechanism to reuse the wsdls that are read already once … via a static reference or so ? (maybe is like that already)

On 02 Jul 2012, at 17:18, Mark Streit wrote:

> I can offer one opinion with regard to the question of packaging of WSDL/XSDs locally.
>
> Yes - it is much better/efficient to have your build process (be it Ant or Maven) produce a JAR file where the /META-INF/wsdl folder of that JAR contains the WSDL/XSD files. Both tools that are often used to produce client-side artifacts (wsimport for JAX-RS RI/Metro and wsdl2Java for CXF) provide options that allow you to specify the wsdlLocation property/attribute.
>
> By "localizing" the WSDL/XSD files within the JAR, you are packaging the Java artifacts with the WSDL/XSD files from which they were generated... and you are saving a wire call to get a WSDL which is dynamically served from the deployed/running endpoint. If anything in that WSDL changed, subsequent to the time you generated your artifacts, you will have problems anyway and localization spares you that mess.
>
> If you look at the generated code using such a practice, you will see a Service proxy class created that looks like this:
>
> package com.acme.book.webservices;
>
> import java.net.URL;
> import javax.xml.namespace.QName;
> import javax.xml.ws.Service;
> import javax.xml.ws.WebEndpoint;
> import javax.xml.ws.WebServiceClient;
> import javax.xml.ws.WebServiceException;
> import javax.xml.ws.WebServiceFeature;
>
>
> /**
> * This class was generated by the JAX-WS RI.
> * JAX-WS RI 2.2.5-b01
> * Generated source version: 2.1
> *
> */
> @WebServiceClient(name = "BookOrderManagerService", targetNamespace = "http://webservices.book.acme.com/", wsdlLocation = "/META-INF/wsdl/BookOrderManagerService.wsdl")
> public class BookOrderManagerService_Service
> extends Service
> {
>
> private final static URL BOOKORDERMANAGERSERVICE_WSDL_LOCATION;
> private final static WebServiceException BOOKORDERMANAGERSERVICE_EXCEPTION;
> private final static QName BOOKORDERMANAGERSERVICE_QNAME = new QName("http://webservices.book.acme.com/", "BookOrderManagerService");
>
> static {
> BOOKORDERMANAGERSERVICE_WSDL_LOCATION = com.acme.book.webservices.BookOrderManagerService_Service.class.getResource("/META-INF/wsdl/BookOrderManagerService.wsdl");
> WebServiceException e = null;
> if (BOOKORDERMANAGERSERVICE_WSDL_LOCATION == null) {
> e = new WebServiceException("Cannot find '/META-INF/wsdl/BookOrderManagerService.wsdl' wsdl. Place the resource correctly in the classpath.");
> }
> BOOKORDERMANAGERSERVICE_EXCEPTION = e;
> }
>
> public BookOrderManagerService_Service() {
> super(__getWsdlLocation(), BOOKORDERMANAGERSERVICE_QNAME);
> }
>
> public BookOrderManagerService_Service(URL wsdlLocation, QName serviceName) {
> super(wsdlLocation, serviceName);
> }
>
> /**
> *
> * @return
> * returns BookOrderManagerService
> */
> @WebEndpoint(name = "BookOrderManagerServicePort")
> public BookOrderManagerService getBookOrderManagerServicePort() {
> return super.getPort(new QName("http://webservices.book.acme.com/", "BookOrderManagerServicePort"), BookOrderManagerService.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 BookOrderManagerService
> */
> @WebEndpoint(name = "BookOrderManagerServicePort")
> public BookOrderManagerService getBookOrderManagerServicePort(WebServiceFeature... features) {
> return super.getPort(new QName("http://webservices.book.acme.com/", "BookOrderManagerServicePort"), BookOrderManagerService.class, features);
> }
>
> private static URL __getWsdlLocation() {
> if (BOOKORDERMANAGERSERVICE_EXCEPTION!= null) {
> throw BOOKORDERMANAGERSERVICE_EXCEPTION;
> }
> return BOOKORDERMANAGERSERVICE_WSDL_LOCATION;
> }
>
> }
>
> When you run your client code, you will see that during the instantiation of the proxy object, it will NOT call over the wire and will, in fact, read this from the JAR file itself. Notice in the code above how the URL is set using a class.getResource() method and a generated helper method called __getWsdlLocation(). This particular code was generated with wsimport tool but you will see very similar code if you use CXF and use its wsdl2Java tool.
>
> We have done this as a standard practice for a long time and it has worked well.
>
> Hope that helps - at least for that question.
>
>
> On Mon, Jul 2, 2012 at 7:53 AM, Cristian Chiovari wrote:
> Hi ,
>
> Is there a way in terms of best practices to use web service clients ?
>
> Should services need to be cache ?
>
> Is the port thread safe ?
>
> Creating a service is an expensive operation ?
>
> What about creating a port ?
>
> Also when a client is generated is better to copy the WSDL definition locally no ?
>
> When a security policy is applied there are caching mechanism for policy files ? or custom ones need to be done ?
>
> Sorry for so many questions . but i saw a lot of WEB apps where on each call a new service and new port is created (this impels reading wsdls,policy file etc and for me it looks not so optimum)
>
> Thanks !
>
>
>

al130959
Offline
Joined: 2005-09-28
Points: 0

Hi Cristian,

Am 02.07.2012 21:17, schrieb Cristian Chiovari:
> Indeed this approach is the one I tried to impose at my workplace as well.
> But still i was not satisfied with this improvement.
> I mean it can be better because even if i have this wsdl's locally in
> the jar bundled, on each call if the services are not cached
> there is a read from the filesystem and that adds some delay (even if
> small) but when you have thousands of simultaneous calls it might matter.
>
> But as Andreas suggested caching the services , even ports ,solves
> this problem as well…
>
> Still wonder if there might be a mechanism to reuse the wsdls that are
> read already once … via a static reference or so ? (maybe is like that
> already)
This is exactly what happens if you start caching the Service instance:
The WSDL is parsed and cached in order to build up the Service instance,
so caching it avoids any further need to re-read the WSDL.

By additionally either pooling or caching Port/Dispatch objects as
ThreadLocals, you basically do the same for any "variable" configuration
that can be changed dynamically, specifically for a particular
request/response cycle (i.e./such as everything reachable through the
BindingProvider).

HTH & BR,

Andreas

> On 02 Jul 2012, at 17:18, Mark Streit wrote:
>
>> I can offer one opinion with regard to the question of packaging of
>> WSDL/XSDs /locally/.
>>
>> *Yes* - it is much better/efficient to have your build process (be it
>> Ant or Maven) produce a JAR file where the */META-INF/wsdl *folder of
>> that JAR contains the WSDL/XSD files. Both tools that are often used
>> to produce client-side artifacts (/wsimport /for JAX-RS RI/Metro and
>> /wsdl2Java /for CXF) provide options that allow you to specify the
>> /wsdlLocation /property/attribute.
>>
>> By "localizing" the WSDL/XSD files within the JAR, you are packaging
>> the Java artifacts with the WSDL/XSD files from which they were
>> generated... and you are saving a wire call to get a WSDL which is
>> dynamically served from the deployed/running endpoint. If anything in
>> that WSDL changed, subsequent to the time you generated your
>> artifacts, you will have problems anyway and localization spares you
>> that mess.
>>
>> If you look at the generated code using such a practice, you will see
>> a Service proxy class created that looks like this:
>>
>> package com.acme.book.webservices;
>>
>> import java.net.URL;
>> import javax.xml.namespace.QName;
>> import javax.xml.ws.Service;
>> import javax.xml.ws.WebEndpoint;
>> import javax.xml.ws.WebServiceClient;
>> import javax.xml.ws.WebServiceException;
>> import javax.xml.ws.WebServiceFeature;
>>
>>
>> /**
>> * This class was generated by the JAX-WS RI.
>> * JAX-WS RI 2.2.5-b01
>> * Generated source version: 2.1
>> *
>> */
>> @WebServiceClient(name = "BookOrderManagerService", targetNamespace =
>> "http://webservices.book.acme.com/", wsdlLocation =
>> "/META-INF/wsdl/BookOrderManagerService.wsdl")
>> *public class BookOrderManagerService_Service
>> extends Service*
>> {
>>
>> private final static URL BOOKORDERMANAGERSERVICE_WSDL_LOCATION;
>> private final static WebServiceException
>> BOOKORDERMANAGERSERVICE_EXCEPTION;
>> private final static QName BOOKORDERMANAGERSERVICE_QNAME = new
>> QName("http://webservices.book.acme.com/", "BookOrderManagerService");
>>
>> static {
>> *BOOKORDERMANAGERSERVICE_WSDL_LOCATION =
>> com.acme.book.webservices.BookOrderManagerService_Service.class.getResource("/META-INF/wsdl/BookOrderManagerService.wsdl");*
>> WebServiceException e = null;
>> if (BOOKORDERMANAGERSERVICE_WSDL_LOCATION == null) {
>> e = new WebServiceException("Cannot find
>> '/META-INF/wsdl/BookOrderManagerService.wsdl' wsdl. Place the
>> resource correctly in the classpath.");
>> }
>> BOOKORDERMANAGERSERVICE_EXCEPTION = e;
>> }
>>
>> public BookOrderManagerService_Service() {
>> super(__getWsdlLocation(), BOOKORDERMANAGERSERVICE_QNAME);
>> }
>>
>> public BookOrderManagerService_Service(URL wsdlLocation, QName
>> serviceName) {
>> super(wsdlLocation, serviceName);
>> }
>>
>> /**
>> *
>> * @return
>> * returns BookOrderManagerService
>> */
>> @WebEndpoint(name = "BookOrderManagerServicePort")
>> public BookOrderManagerService getBookOrderManagerServicePort() {
>> return super.getPort(new QName("http://webservices.book.acme.com/",
>> "BookOrderManagerServicePort"), BookOrderManagerService.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 BookOrderManagerService
>> */
>> @WebEndpoint(name = "BookOrderManagerServicePort")
>> public BookOrderManagerService
>> getBookOrderManagerServicePort(WebServiceFeature... features) {
>> return super.getPort(new QName("http://webservices.book.acme.com/",
>> "BookOrderManagerServicePort"), BookOrderManagerService.class, features);
>> }
>>
>> private static URL __getWsdlLocation() {
>> if (BOOKORDERMANAGERSERVICE_EXCEPTION!= null) {
>> throw BOOKORDERMANAGERSERVICE_EXCEPTION;
>> }
>> return BOOKORDERMANAGERSERVICE_WSDL_LOCATION;
>> }
>>
>> }
>>
>> When you run your client code, you will see that during the
>> instantiation of the proxy object, it will NOT call over the wire and
>> will, in fact, read this from the JAR file itself. Notice in the code
>> above how the URL is set using a class.getResource() method and a
>> generated helper method called __getWsdlLocation(). This particular
>> code was generated with /wsimport /tool but you will see very similar
>> code if you use CXF and use its /wsdl2Java /tool.
>>
>> We have done this as a standard practice for a long time and it has
>> worked well.
>>
>> Hope that helps - at least for that question.
>>
>>
>> On Mon, Jul 2, 2012 at 7:53 AM, Cristian Chiovari
>> > wrote:
>>
>> Hi ,
>>
>> Is there a way in terms of best practices to use web service
>> clients ?
>>
>> Should services need to be cache ?
>>
>> Is the port thread safe ?
>>
>> Creating a service is an expensive operation ?
>>
>> What about creating a port ?
>>
>> Also when a client is generated is better to copy the WSDL
>> definition locally no ?
>>
>> When a security policy is applied there are caching mechanism for
>> policy files ? or custom ones need to be done ?
>>
>> Sorry for so many questions . but i saw a lot of WEB apps where
>> on each call a new service and new port is created (this impels
>> reading wsdls,policy file etc and for me it looks not so optimum)
>>
>> Thanks !
>>
>>
>>
>>

mcs130
Offline
Joined: 2006-01-26
Points: 0

A couple of points:

1) As Andreas states, caching the instances after they are created (in our
case the developer wrote a "Factory" class that holds a Map of these) will
make a significant improvement. The key to Map was the service interface
name. This cache component was part of a "utility" JAR file that gets
used *with *the actual JAR of generated client artifacts produced using
wsimport (or wsdl2Java in the case of CXF).
2) I assume when you say read from the "filesystem", you do mean read from
the relative location /META-INF/wsdl of the JAR file, right? We have heard
of instances where if the generation is not done correctly or an older
version of the tooling is used - instead of the read event occurring from a
JAR - you would see it in the logs as "jar: ......", you get it reading
from some relative filesystem path on which the generation was done which
will NOT work.

HTH

On Tue, Jul 3, 2012 at 5:16 AM, Andreas Loew wrote:

> Hi Cristian,
>
> Am 02.07.2012 21:17, schrieb Cristian Chiovari:
>
> Indeed this approach is the one I tried to impose at my workplace as well.
>> But still i was not satisfied with this improvement.
>> I mean it can be better because even if i have this wsdl's locally in the
>> jar bundled, on each call if the services are not cached
>> there is a read from the filesystem and that adds some delay (even if
>> small) but when you have thousands of simultaneous calls it might matter.
>>
>> But as Andreas suggested caching the services , even ports ,solves this
>> problem as well…
>>
>> Still wonder if there might be a mechanism to reuse the wsdls that are
>> read already once … via a static reference or so ? (maybe is like that
>> already)
>>
> This is exactly what happens if you start caching the Service instance:
> The WSDL is parsed and cached in order to build up the Service instance, so
> caching it avoids any further need to re-read the WSDL.
>
> By additionally either pooling or caching Port/Dispatch objects as
> ThreadLocals, you basically do the same for any "variable" configuration
> that can be changed dynamically, specifically for a particular
> request/response cycle (i.e./such as everything reachable through the
> BindingProvider).
>
> HTH & BR,
>
> Andreas
>
> On 02 Jul 2012, at 17:18, Mark Streit wrote:
>>
>> I can offer one opinion with regard to the question of packaging of
>>> WSDL/XSDs /locally/.
>>>
>>> *Yes* - it is much better/efficient to have your build process (be it
>>> Ant or Maven) produce a JAR file where the */META-INF/wsdl *folder of that
>>> JAR contains the WSDL/XSD files. Both tools that are often used to produce
>>> client-side artifacts (/wsimport /for JAX-RS RI/Metro and /wsdl2Java /for
>>> CXF) provide options that allow you to specify the /wsdlLocation
>>> /property/attribute.
>>>
>>>
>>> By "localizing" the WSDL/XSD files within the JAR, you are packaging the
>>> Java artifacts with the WSDL/XSD files from which they were generated...
>>> and you are saving a wire call to get a WSDL which is dynamically served
>>> from the deployed/running endpoint. If anything in that WSDL changed,
>>> subsequent to the time you generated your artifacts, you will have problems
>>> anyway and localization spares you that mess.
>>>
>>> If you look at the generated code using such a practice, you will see a
>>> Service proxy class created that looks like this:
>>>
>>> package com.acme.book.webservices;
>>>
>>> import java.net.URL;
>>> import javax.xml.namespace.QName;
>>> import javax.xml.ws.Service;
>>> import javax.xml.ws.WebEndpoint;
>>> import javax.xml.ws.WebServiceClient;
>>> import javax.xml.ws.**WebServiceException;
>>> import javax.xml.ws.**WebServiceFeature;
>>>
>>>
>>> /**
>>> * This class was generated by the JAX-WS RI.
>>> * JAX-WS RI 2.2.5-b01
>>> * Generated source version: 2.1
>>> *
>>> */
>>> @WebServiceClient(name = "BookOrderManagerService", targetNamespace = "
>>> http://webservices.book.acme.**com/ ",
>>> wsdlLocation = "/META-INF/wsdl/**BookOrderManagerService.wsdl")
>>> *public class BookOrderManagerService_**Service
>>> extends Service*
>>>
>>> {
>>>
>>> private final static URL BOOKORDERMANAGERSERVICE_WSDL_**LOCATION;
>>> private final static WebServiceException BOOKORDERMANAGERSERVICE_**
>>> EXCEPTION;
>>> private final static QName BOOKORDERMANAGERSERVICE_QNAME = new QName("
>>> http://webservices.**book.acme.com/ ",
>>> "BookOrderManagerService");
>>>
>>> static {
>>> *BOOKORDERMANAGERSERVICE_WSDL_**LOCATION = com.acme.book.webservices.**
>>> BookOrderManagerService_**Service.class.getResource("/**META-INF/wsdl/**
>>> BookOrderManagerService.wsdl")**;*
>>>
>>> WebServiceException e = null;
>>> if (BOOKORDERMANAGERSERVICE_WSDL_**LOCATION == null) {
>>> e = new WebServiceException("Cannot find '/META-INF/wsdl/**BookOrderManagerService.wsdl'
>>> wsdl. Place the resource correctly in the classpath.");
>>> }
>>> BOOKORDERMANAGERSERVICE_**EXCEPTION = e;
>>> }
>>>
>>> public BookOrderManagerService_**Service() {
>>> super(__getWsdlLocation(), BOOKORDERMANAGERSERVICE_QNAME)**;
>>> }
>>>
>>> public BookOrderManagerService_**Service(URL wsdlLocation, QName
>>> serviceName) {
>>> super(wsdlLocation, serviceName);
>>> }
>>>
>>> /**
>>> *
>>> * @return
>>> * returns BookOrderManagerService
>>> */
>>> @WebEndpoint(name = "BookOrderManagerServicePort")
>>> public BookOrderManagerService getBookOrderManagerServicePort**() {
>>> return super.getPort(new QName("http://webservices.**book.acme.com/",
>>> "BookOrderManagerServicePort")**, BookOrderManagerService.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 BookOrderManagerService
>>> */
>>> @WebEndpoint(name = "BookOrderManagerServicePort")
>>> public BookOrderManagerService getBookOrderManagerServicePort**(WebServiceFeature...
>>> features) {
>>> return super.getPort(new QName("http://webservices.**book.acme.com/",
>>> "BookOrderManagerServicePort")**, BookOrderManagerService.class,
>>> features);
>>> }
>>>
>>> private static URL __getWsdlLocation() {
>>> if (BOOKORDERMANAGERSERVICE_**EXCEPTION!= null) {
>>> throw BOOKORDERMANAGERSERVICE_**EXCEPTION;
>>> }
>>> return BOOKORDERMANAGERSERVICE_WSDL_**LOCATION;
>>> }
>>>
>>> }
>>>
>>> When you run your client code, you will see that during the
>>> instantiation of the proxy object, it will NOT call over the wire and will,
>>> in fact, read this from the JAR file itself. Notice in the code above how
>>> the URL is set using a class.getResource() method and a generated helper
>>> method called __getWsdlLocation(). This particular code was generated with
>>> /wsimport /tool but you will see very similar code if you use CXF and use
>>> its /wsdl2Java /tool.
>>>
>>>
>>> We have done this as a standard practice for a long time and it has
>>> worked well.
>>>
>>> Hope that helps - at least for that question.
>>>
>>>
>>> On Mon, Jul 2, 2012 at 7:53 AM, Cristian Chiovari <
>>> cristian.chiovari@gmail.com >>
>>> wrote:
>>>
>>> Hi ,
>>>
>>> Is there a way in terms of best practices to use web service
>>> clients ?
>>>
>>> Should services need to be cache ?
>>>
>>> Is the port thread safe ?
>>>
>>> Creating a service is an expensive operation ?
>>>
>>> What about creating a port ?
>>>
>>> Also when a client is generated is better to copy the WSDL
>>> definition locally no ?
>>>
>>> When a security policy is applied there are caching mechanism for
>>> policy files ? or custom ones need to be done ?
>>>
>>> Sorry for so many questions . but i saw a lot of WEB apps where
>>> on each call a new service and new port is created (this impels
>>> reading wsdls,policy file etc and for me it looks not so optimum)
>>>
>>> Thanks !
>>>
>>>
>>>
>>>
>>> --
>>> Mark
>>>
>>

Cristian Chiovari

On Tue, Jul 3, 2012 at 1:51 PM, Mark Streit wrote:

> A couple of points:
>
> 1) As Andreas states, caching the instances after they are created (in our
> case the developer wrote a "Factory" class that holds a Map of these) will
> make a significant improvement. The key to Map was the service interface
> name. This cache component was part of a "utility" JAR file that gets
> used *with *the actual JAR of generated client artifacts produced using
> wsimport (or wsdl2Java in the case of CXF).
>

Indeed a simple and very efficient method.
What i have used in the past was done based on
http://commons.apache.org/pool/ .So when the web app started the pool was
initialized with a pre configured number of instance services. (Ports were
created each time ....but as i understood they might be cached as well)

Just thinking that another solution is to use a dynamic pool for ports that
can be increase when needed and decreased when there is no load

> 2) I assume when you say read from the "filesystem", you do mean read from
> the relative location /META-INF/wsdl of the JAR file, right? We have heard
> of instances where if the generation is not done correctly or an older
> version of the tooling is used - instead of the read event occurring from a
> JAR - you would see it in the logs as "jar: ......", you get it reading
> from some relative filesystem path on which the generation was done which
> will NOT work.
>
> Yes..reading from JAR...but indeed caching solves this.

However in a JEE environment the above custom caching solution cannot be
done by the container ?

@Resource ?
WebserviceClientPort port ?
WebserviceClientService service ?

Started to read recently how JMS connection are used in a JEE environment
and there are done some optimizations.

Regards

> HTH
>
>
> On Tue, Jul 3, 2012 at 5:16 AM, Andreas Loew wrote:
>
>> Hi Cristian,
>>
>> Am 02.07.2012 21:17, schrieb Cristian Chiovari:
>>
>> Indeed this approach is the one I tried to impose at my workplace as
>>> well.
>>> But still i was not satisfied with this improvement.
>>> I mean it can be better because even if i have this wsdl's locally in
>>> the jar bundled, on each call if the services are not cached
>>> there is a read from the filesystem and that adds some delay (even if
>>> small) but when you have thousands of simultaneous calls it might matter.
>>>
>>> But as Andreas suggested caching the services , even ports ,solves this
>>> problem as well…
>>>
>>> Still wonder if there might be a mechanism to reuse the wsdls that are
>>> read already once … via a static reference or so ? (maybe is like that
>>> already)
>>>
>> This is exactly what happens if you start caching the Service instance:
>> The WSDL is parsed and cached in order to build up the Service instance, so
>> caching it avoids any further need to re-read the WSDL.
>>
>> By additionally either pooling or caching Port/Dispatch objects as
>> ThreadLocals, you basically do the same for any "variable" configuration
>> that can be changed dynamically, specifically for a particular
>> request/response cycle (i.e./such as everything reachable through the
>> BindingProvider).
>>
>> HTH & BR,
>>
>> Andreas
>>
>> On 02 Jul 2012, at 17:18, Mark Streit wrote:
>>>
>>> I can offer one opinion with regard to the question of packaging of
>>>> WSDL/XSDs /locally/.
>>>>
>>>> *Yes* - it is much better/efficient to have your build process (be it
>>>> Ant or Maven) produce a JAR file where the */META-INF/wsdl *folder of that
>>>> JAR contains the WSDL/XSD files. Both tools that are often used to produce
>>>> client-side artifacts (/wsimport /for JAX-RS RI/Metro and /wsdl2Java /for
>>>> CXF) provide options that allow you to specify the /wsdlLocation
>>>> /property/attribute.
>>>>
>>>>
>>>> By "localizing" the WSDL/XSD files within the JAR, you are packaging
>>>> the Java artifacts with the WSDL/XSD files from which they were
>>>> generated... and you are saving a wire call to get a WSDL which is
>>>> dynamically served from the deployed/running endpoint. If anything in that
>>>> WSDL changed, subsequent to the time you generated your artifacts, you will
>>>> have problems anyway and localization spares you that mess.
>>>>
>>>> If you look at the generated code using such a practice, you will see a
>>>> Service proxy class created that looks like this:
>>>>
>>>> package com.acme.book.webservices;
>>>>
>>>> import java.net.URL;
>>>> import javax.xml.namespace.QName;
>>>> import javax.xml.ws.Service;
>>>> import javax.xml.ws.WebEndpoint;
>>>> import javax.xml.ws.WebServiceClient;
>>>> import javax.xml.ws.**WebServiceException;
>>>> import javax.xml.ws.**WebServiceFeature;
>>>>
>>>>
>>>> /**
>>>> * This class was generated by the JAX-WS RI.
>>>> * JAX-WS RI 2.2.5-b01
>>>> * Generated source version: 2.1
>>>> *
>>>> */
>>>> @WebServiceClient(name = "BookOrderManagerService", targetNamespace = "
>>>> http://webservices.book.acme.**com/ ",
>>>> wsdlLocation = "/META-INF/wsdl/**BookOrderManagerService.wsdl")
>>>> *public class BookOrderManagerService_**Service
>>>> extends Service*
>>>>
>>>> {
>>>>
>>>> private final static URL BOOKORDERMANAGERSERVICE_WSDL_**LOCATION;
>>>> private final static WebServiceException BOOKORDERMANAGERSERVICE_**
>>>> EXCEPTION;
>>>> private final static QName BOOKORDERMANAGERSERVICE_QNAME = new QName("
>>>> http://webservices.**book.acme.com/ ",
>>>> "BookOrderManagerService");
>>>>
>>>> static {
>>>> *BOOKORDERMANAGERSERVICE_WSDL_**LOCATION = com.acme.book.webservices.**
>>>> BookOrderManagerService_**Service.class.getResource("/**META-INF/wsdl/*
>>>> *BookOrderManagerService.wsdl")**;*
>>>>
>>>> WebServiceException e = null;
>>>> if (BOOKORDERMANAGERSERVICE_WSDL_**LOCATION == null) {
>>>> e = new WebServiceException("Cannot find '/META-INF/wsdl/**BookOrderManagerService.wsdl'
>>>> wsdl. Place the resource correctly in the classpath.");
>>>> }
>>>> BOOKORDERMANAGERSERVICE_**EXCEPTION = e;
>>>> }
>>>>
>>>> public BookOrderManagerService_**Service() {
>>>> super(__getWsdlLocation(), BOOKORDERMANAGERSERVICE_QNAME)**;
>>>> }
>>>>
>>>> public BookOrderManagerService_**Service(URL wsdlLocation, QName
>>>> serviceName) {
>>>> super(wsdlLocation, serviceName);
>>>> }
>>>>
>>>> /**
>>>> *
>>>> * @return
>>>> * returns BookOrderManagerService
>>>> */
>>>> @WebEndpoint(name = "BookOrderManagerServicePort")
>>>> public BookOrderManagerService getBookOrderManagerServicePort**() {
>>>> return super.getPort(new QName("http://webservices.**book.acme.com/",
>>>> "BookOrderManagerServicePort")**, BookOrderManagerService.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 BookOrderManagerService
>>>> */
>>>> @WebEndpoint(name = "BookOrderManagerServicePort")
>>>> public BookOrderManagerService getBookOrderManagerServicePort**(WebServiceFeature...
>>>> features) {
>>>> return super.getPort(new QName("http://webservices.**book.acme.com/",
>>>> "BookOrderManagerServicePort")**, BookOrderManagerService.class,
>>>> features);
>>>> }
>>>>
>>>> private static URL __getWsdlLocation() {
>>>> if (BOOKORDERMANAGERSERVICE_**EXCEPTION!= null) {
>>>> throw BOOKORDERMANAGERSERVICE_**EXCEPTION;
>>>> }
>>>> return BOOKORDERMANAGERSERVICE_WSDL_**LOCATION;
>>>> }
>>>>
>>>> }
>>>>
>>>> When you run your client code, you will see that during the
>>>> instantiation of the proxy object, it will NOT call over the wire and will,
>>>> in fact, read this from the JAR file itself. Notice in the code above how
>>>> the URL is set using a class.getResource() method and a generated helper
>>>> method called __getWsdlLocation(). This particular code was generated with
>>>> /wsimport /tool but you will see very similar code if you use CXF and use
>>>> its /wsdl2Java /tool.
>>>>
>>>>
>>>> We have done this as a standard practice for a long time and it has
>>>> worked well.
>>>>
>>>> Hope that helps - at least for that question.
>>>>
>>>>
>>>> On Mon, Jul 2, 2012 at 7:53 AM, Cristian Chiovari <
>>>> cristian.chiovari@gmail.com >>
>>>> wrote:
>>>>
>>>> Hi ,
>>>>
>>>> Is there a way in terms of best practices to use web service
>>>> clients ?
>>>>
>>>> Should services need to be cache ?
>>>>
>>>> Is the port thread safe ?
>>>>
>>>> Creating a service is an expensive operation ?
>>>>
>>>> What about creating a port ?
>>>>
>>>> Also when a client is generated is better to copy the WSDL
>>>> definition locally no ?
>>>>
>>>> When a security policy is applied there are caching mechanism for
>>>> policy files ? or custom ones need to be done ?
>>>>
>>>> Sorry for so many questions . but i saw a lot of WEB apps where
>>>> on each call a new service and new port is created (this impels
>>>> reading wsdls,policy file etc and for me it looks not so optimum)
>>>>
>>>> Thanks !
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Mark
>>>>
>>>

al130959
Offline
Joined: 2005-09-28
Points: 0

Hi Cristian,

Am 03.07.2012 14:22, schrieb Cristian Chiovari:
> What i have used in the past was done based on
> http://commons.apache.org/pool/ .So when the web app started the pool
> was initialized with a pre configured number of instance services.
> (Ports were created each time ....but as i understood they might be
> cached as well)
This is NOT AT ALL needed! You can create just one single static Service
instance per WSDL: Any single Service object is fully thread-safe and
can be shared by as many concurrent threads as you like. So "caching" a
Service basically means making it a static property of your client
class, nothing more. Therefore, this single object also needs to be
initialized only once from the WSDL.

> Just thinking that another solution is to use a dynamic pool for ports
> that can be increase when needed and decreased when there is no load
A dynamic pool of Port/Dispatch objects would be an "ideal" solution,
but as stated before, particularly in an environment where your WS
client is running from within a Java EE container and you therefore have
no direct control about the number of worker threads from your
WorkManager (i.e. either your HTTP session pool, EJB pool, or maybe even
both depending on the call scenarios), I'd rather recommend the
ThreadLocal solution: It is very simple as far as the codebase is
concerned, and - from my experience - still tolerable regarding the
amount of memory used (again, the Service instance is the big object,
not the Port).

This means use a lazily initialized static ThreadLocal to cache a
dedicated Port object to be used from the current worker thread. Running
the app for a while, successively all the threads from your
WorkManager's thread pool (HTTP session pool, EJB pool) will have their
thread's dedicated Port object created and cached, and these will then
be reused once the same worker thread is reassigned by the container
WorkManager to execute another WS client request of the same sort...

Did I make myself clear enough now? Unfortunately, I don't have any code
sample at hand which is simple enough to post it here...

HTH & BR,

Andreas