users@jax-ws.java.net

Re: JAX-WS 2.1 backward compatibility (was "turning off WS-Policy (and/or WSIT)")

From: Mark Hansen <marklists_at_javector.com>
Date: Fri, 23 Mar 2007 02:04:13 -0400

Joe and I agreed that this should be posted to the community. Joe's
comments are in-line.

Mark Hansen wrote:
> Hi Joe,
>
> Thanks for the nice explanation. I am not running the appclient. I
> am running Java SE 5, as follows:
>
> java version "1.5.0_10"
> Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
> Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode)
>
> So, <glassfish-install>/lib/appserv-rt.jar is not on the classpath.
> I understand the various workarounds you describe - thanks for all the
> detail.
FWIW. The reference to the missing class is from a message handler in
webservices-rt.jar.
There is nothing specific in the generated JAX-WS client code for
transactions.
That code can be used to access JAXB 2.0 or JAXB 2.1 version of web service.

>
> My opinion on this, for what it is worth, is that its a *bad* idea to
> generate WS-AT policy assertions *by default* for @STATELESS Web
> services. WS-AT policy support is a great idea, but it should be
> *optional* for a bunch of reasons:
> * It introduces a sort of non-backward compatibilty from JAX-WS 2.1
> to JAX-WS 2.0. That is particulary bad since Java EE 5 services can
> use either version of JAX-WS. By having this WS-AT behavior as the
> default, you can get very different WSDLs and runtime client
> behaviors by deploying an @STATELESS on 2 different containers that
> are both Java EE 5 certified. See my previous mail on this thread
> about that.
> * As a general architectural principle, all the WS-* specs should be
> turned off by default for WSDL generation. Nobody has much real-world
> experience with these specs, and its a safe bet that most people will
> want to keep their WSDL as simple as possible until they gain
> experience working with the WS-*.
Thanks for your valuable feedback. Your point is taken that this should
be configurable. Backwards compatibility suggests that it be off by default.

Current architecture makes it quite easy to implement this.
transactional support is not built into JAX-WS at all, it is plugged in
via handler semantics and extensions.

>
> * Its a mistake to tightly couple the container behavior (e.g., the
> transactional nature of a bean) to its WSDL. Think of the WSDL as a
> JSF or interface definition wrapper around the bean.. It shouldn't by
> *default* contain *all* the information about the underlying
> implementation. JAX-WS should not be trying to reimplement Java
> container semantics in the SOAP/XML world. There may be good reasons
> to have a non-transactional WSDL representation that is implemented by
> an underlying bean that is transacted.
I do have to disagree with you on this point. If you would like a
transaction client to control whether persistent updates occur or not to all
the web service invocations that it makes, the WSDL does need to export
what methods allow for transactions and which ones do not.

Note that a WSDL is similar to an EJB remote interface in this case.

So by allowing for transaction policy assertions on a wsdl:operation, it
allows the client to know which web service invocations can be
controlled by a client transaction.

Example:

@Resource
UserTranasction ut;

ut.begin();
    webSvc1port.removeFromInventory(partNo, quantity);
    webSvc2.addToOrder(orderNo, partNo, quantity);
ut.commit() // or ut.rollback();

A contract is required between the client and service on whether it is
acceptable to flow a transaction from
the client to the service operation. A client would not have the
ability to aggregate web service invocations
into one atomic transaction without knowing whether service supports
flowing in a transactional context with the
request. The two operations above must support flowing
the client transactional context to the web service invocations to
enable atomic transaction of these two services.
This becomes especially important when the web services are on two
different systems that typically do not
allow for distributed two phase commit.

Lastly, the WSIT transaction code is performing the following for SOAP
messages (injecting transaction context as a SOAP header on outgoing
client messages and detecting transaction context on incoming SOAP
request to service). This work is more analagous
to what portable interceptors are used for injecting and detecting
transaction context over IIOP transport (CORBA standards)
The EJB container is still doing the same transactional work for a web
services as it performs for IIOP flowed transactions.
This work is done by handlers which are easily removed.

-joe












> JAX-RPC stumbled in part because it tied "RPC" semantics too tightly
> to the WSDL/SOAP. Shortly after JAX-RPC came out, people realized
> that in the WSDL/SOAP world, it is more useful to work with doc/lit
> services and think in terms of message passing. I am worried that
> JAX-WS 2.1 is now repeating that kind of mistake with the new WS-*
> specifications. JAX-WS should not tightly couple things like
> transaction semantics or reliable messaging (with MDB) to the WSDL
> representation that are generated by default. For example, while it
> would be a nice option for a MDB to be able to auto-generate WSDL with
> the proper WS-Reliability assertions, that should not be required or
> even the default behavior.
> JAX-WS is on the right track. Its a big improvement over JAX-RPC. It
> would be great if we could keep it simple, not tie it too tightly to
> the underlying Java, and give developers/deployers lots of options -
> with the default behavior always being the simpliest possible WSDL
> that sensibly maps to the underlying Java class.
>
> -- Mark
>
>
> Hi Joe,
>
> Joseph Fialli wrote:
>
>> Mark Hansen wrote:
>>
>>> I'm deploying a @WebService / @Stateless. The WSDL generated in GF
>>> V2 B39 (built with JAX-WS 2.1) contains a bunch of WS-Policy markup
>>> (see below).
>>> When I generate a service/port from this WSDL using this code:
>>>
>>> String hostVal = System.getProperty("glassfish.host");
>>> String portVal = System.getProperty("glassfish.deploy.port");
>>> URL wsdlURL =
>>> new
>>> URL("http://"+hostVal+":"+portVal+"/HelloService/Hello?wsdl");
>>> printWSDL(wsdlURL);
>>> QName serviceQName = new QName("http://samples/", "HelloService");
>>> QName portQName = new QName("http://samples/", "HelloPort");
>>> Service service = Service.create(wsdlURL, serviceQName);
>>> Hello port = (Hello) service.getPort(portQName, Hello.class);
>>> String result = port.sayHello("Java Programmer");
>>>
>>> (Hello.class is the SEI generated from the Hello class below by wsgen)
>>>
>>> then, I get this error:
>>>
>>> java.lang.NoClassDefFoundError"
>>> message="com/sun/enterprise/transaction/TransactionImport">java.lang.NoClassDefFoundError:
>>> com/sun/enterprise/transaction/TransactionImport
>>>
>>> Why am I getting this error? And how can I turn off the WS-Policy
>>> markups in the WSDL?
>>
>> Mark,
>>
>> First off, I would like to state that the example above should just
>> work.
>>
>> There possibly is a configuration issue (such as classpath) or
>> something we can do better in packaging WSIT in glassfish.
>>
>> The missing class is defined in <glassfish-install>/lib/appserv-rt.jar.
>> You could assist our evaluation of this issue if you could confirm the
>> following information.
>>
>> Are you running a standalone client?
>> <glassfish-install>/bin/appclient specifies appserv-rt.jar so I assume
>> the class is not defined for that reason. If you are running an
>> application client, it could be you are getting the wrong version of
>> appserv-rt.jar. TransactionImport is not defined in AS 9.0
>> but it has been defined in AS 9.1 since June 27th.
>> http://fisheye5.cenqua.com/browse/glassfish/appserv-core/src/java/com/sun/enterprise/transaction/TransactionImport.ja
>>
>>
>> Lastly, could you confirm what JDK version and platform that you
>> encountered this problem.
>> If you have a stack trace when the TransactionImport class was not
>> found, it would be helpful
>> but this is not necessary if you don't have it.
>>
>> *****************************
>>
>> WORKAROUND suggestions:
>>
>> If you do not want to introduce appserv-rt.jar to the classpath for
>> the possible standalone client, you may want to use a Java EE
>> concept that does not default to enabling transactions.
>>
>> The easiest workaround would be to remove @javax.ejb.Stateless.
>> (Since transactions are enabled by default on a Stateless EJB.)
>> I noted in your other mail that you also discovered you could use
>> TransactionAttribute(NEVER). Addtionally, you could
>> use TransactionManagement(BEAN). No WS-AT policy assertions
>> will be generated for these EJBs.
>>
>> While Web Service transaction semantics are only implemented in web
>> and EJB tier in Glassfish v2; however, you should be able to call an
>> EJB method with
>> TransactionAttribute of REQUIRED.
>>
>> **********
>>
>> Explanation on why generated wsdl of a Container Managed Transaction
>> (CMT) EJB was generating a wsdl with ws-atomic transaction policy
>> assertions in it.
>>
>> By default, a stateless EJB has the following Transaction Attributes.
>>
>> TransactionManaged(CONTAINER)
>> TransactionAttributeType(REQUIRED)
>>
>> To ease mapping existing transacted Java EJB to a transactd web
>> service, the above
>> attributes are getting mapped to semantically equivalent ws-atomic
>> transaction policy assertions. This is intended to be a feature.
>> I understand your frustration that this feature is not currently
>> working properly
>> in your environment.
>> As the workaround pointed out, if transaction support is not required,
>> it might be best to just use a servlet or BEAN managed transaction.
>>
>> -Joe Fialli
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>> -- Mark
>>
>>
>