Mauro Molinari wrote:
Well, for reference to other people, maybe the best solution is to reopen that bug and either keep it open (if you plan to work on it) or close as rejected (if you don't).
I'll do the latter then.
Mauro Molinari wrote:
Anyway, in my case, we're seriously considering to migrate our infrastructure from Axis2 to Metro. This said, do you think that embedding XTS in this new scenario would be easier or not?
No, embedding it in Metro will ne harder for two reasons.
Firstly, the WS-T implementation (that's the implementation of the WS-AT and WS-BA protocols plus the completion protocols used by the client to terminate transactions/business activities) need to be able to receive an incoming message whose payload is a SOAP fault. This is required by the WS-T specifications and without it certain aspects of normal operation and crash recovery will not work.
If you check the service WSDL used by the JBoss implementation you can see that it includes these operations. For example, the WS-AT participant service (the service which runs in the same container as the transactional web service) uses the binding in file wsat-participant-binding.wsdl which contains the following lines of relevance:
<wsdl:import
namespace="http://docs.oasis-open.org/ws-tx/wsat/2006/06"
location="wsat.wsdl" />
<wsdl:binding name="Participant_SOAPBinding" type="wsat:ParticipantPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="PrepareOperation">
<soap:operation soapAction="http://docs.oasis-open.org/ws-tx/wsat/2006/06/Prepare" style="document"/>
<wsdl:input message="wsat:Prepare">
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
. . .
<wsdl:operation name="SoapFault">
<soap:operation soapAction="http://docs.oasis-open.org/ws-tx/wsat/2006/06/fault"/>
<wsdl:input message="wsat:SoapFault">
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
The imported wsdl contains the following lines of relevance:
<wsdl:types>
<xs:schema>
<xs:import
namespace="http://www.w3.org/2005/08/addressing"
schemaLocation="ws-addr.xsd" />
<xs:import
namespace="http://docs.oasis-open.org/ws-tx/wsat/2006/06"
schemaLocation="wsat.xsd" />
<xs:import namespace="http://schemas.xmlsoap.org/soap/envelope/"
schemaLocation="envelope.xsd"/>
</xs:schema>
</wsdl:types>
<!-- Messages -->
<wsdl:message name="Prepare">
<wsdl:part name="parameters" element="wsat:Prepare"/>
</wsdl:message>
. . .
<wsdl:message name="SoapFault">
<wsdl:part name="parameters" element="soapenv:Fault"/>
</wsdl:message>
. . .
<!-- Port Types -->
<wsdl:portType name="CoordinatorPortType">
<wsdl:operation name="PreparedOperation">
<wsdl:input message="wsat:Prepared"/>
</wsdl:operation>
. . .
<wsdl:operation name="SoapFault">
<wsdl:input message="wsat:SoapFault"/>
</wsdl:operation>
</wsdl:portType>
. . .
Now, one of the problems with using Metro's JaxWS implementation is that it will not deliver an incoming message with a SOAP fault as payload. It assumes that it must be an error response associated with some prior outgoing request and then gets very confused and drops the message. You can try to get the Metro implementors to recognize that this is a problem and fix it. I have tried and got no response.
Metro is not unique in this regard. The current CXF implementation does currently deliver SOAP faults as payload but previous versions have failed to handle this case. It has actually been fixed then broken a couple of times so far. Luckily, JBoss has CXF conributors who have been able to fix if for us when it recently stopped working again (thanks Jim Ma :-). JBossWS Native has managed to retain the ability to deliver faults as payload in all the releases I have tested on,
Secondly, the WS-C and WS-T implementations require that the client coordinator and web service be able to explciitly configure WSA headers on outgoing messages and be abel to collect and process incoming WSA headers. The original JaxWS-WSA JSR-261 draft specification defined an API which allowed JaxWS clients and service implementation beans to have this access to WSA message headers. However, Sun killed this specification, leaving no standard API for a WS-C/T implementor to rely on. Furthermore, they provided no implementation in Metro, standard or non-standard.
So, in order to embed the JBoss code in Metro you will have to provide your own client and server side handlers to mange serilaization and deserialization of the relevant SOAP headers. You will also need to provide code which allows the relevant information to be installed to/read from the JaxWS message context so that the client/server can read or write the Java data which populates these SOAP headers.
Another issue is where to locate this functionality so that the JBoss XTS code can find it. CXF provides all its JaxWS-WSA implementation in package org.apache.cxf.ws.addressing. JBoss/Native provides its implementaton in package javax.xml.ws.addressing. Also, CXF has only provided access to a cut-down version of the WSA RelatesTo header -- only 1 Relationship can be provided in this header. JBossWS/Native has provided a full implementation of the draft API allowing a list of Relationships to be provided. So, JBossWS exports an abstraction class called MAP (plus several related classes such as MAPBuilder) which hide the details of which underlying JaxWS-WSA implementation is being used. If ytou want to embed the JBoss XTS code in Metro then you will need to implement this abstraction library and redirect it to sit over your Metro JaxWS-WSA library.
Mauro Molinari wrote:
Correct me if I'm wrong, the steps necessary to set up the whole thing (XTS + bridge) is the following:
CLIENT SIDE
- configure the client side header handler: this should be easy, as with Metro we can use the standard JAX-WS handlers provided by XTS
- deploy the WS-AT service: this may be some work to "convert" the SAR provided by XTS to something deployable with Metro
- deploy the WS-C service if we plan to use local coordination: same as above
SERVER SIDE
- configure the service side header handler: this should be easy, as with Metro we can use the standard JAX-WS handlers provided by XTS
- deploy the WS-AT service: this may be some work to "convert" the SAR provided by XTS to something deployable with Metro
- deploy the WS-C service if we plan to use stand-alone coordination (this configuration seems the best for our purpose): same as above, although we also have to setup XTS client-side so that it uses the remote coordination service (is the use of system properties, like described in chapter 7, the only way to do that?)
- configura the bridge handler: again, this should be easy, because we should be able to use the one provided with the bridge
Modulo the problems outlined above yes that is what you need to do.
Mauro Molinari wrote:
Other questions I would have:
- in XTS documentation it is said that XTS implements version 1.0 and 1.1 of the various protocols of WS-T; however, in the bridge documentation it distinguishes between version 1.0 and 1.2, saying it works only for 1.2; is this an error? Is the bridge supposed to work with the 1.1 protocol version?
1.2 is a maintenance version of the 1.1 spec which clarified some of the references and terminology but did not redefine any of the behaviour of conformant 1.1 implementations. So, a 1.2 implementation is a 1.1 implementation.
Mauro Molinari wrote:
- given the fact that XTS does not support subordinate transactions in stand-alone coordination configuration, if we use local coordination how is subordinate transactions supposed to be implemented using the bridge? Should it use nested transactions on JTA side? Anyway, throughout JBossTS JTA documentation, it is often said that JTA does not support nested transactions, although there's a JBossTS configuration option to enable JTA nested transactions; it is not clear to me if, by enabling this option, nested transaction will actually work on JTA side or not
Hmm, some terminological disambiguation is required here. "stand-alone" is being used here in a different sense to the one you understand, I think. In the XTS docs a "stand-alone coordinator" is a coordinator running in a different container to the client. When you deploy the XTS sar you need the client libraries and the client participant service but you automatically get all the coordinator services too (you also get the paticipant services but we'll ignore that for now). If you don't do anything then your client will talk to the coordinator in its container when it tries to start a transaction. However, you can point the client at a coordinator running elsewhere. Thsi is usually done by setting System property org.jboss.jbosts.xts.coordinatorURL on the JVM command line. The latter configuration is referred to as "stand-alone coordination" because the coordinator is in a different JVM to the client.
Now, a similar thing is possible with your web service container but there is an important difference. In order to make the web service transactional you need to deploy the participant libraries and the participant end points. However, as with the client you automatically end up deploying the coordinator services in the web service's JVM. Now the web service does not normally initiate a conversation with a coordinator service using its own URL. The SOAP handlers configured on the client and server side ensure that the web service receives a transaction context whenever a web service request is made. This transaction context includes a URL which the WS-T participant code uses to enlist the web service as part of the transaction. The registration response contains another URL whcih identifes the WS-AT coordinator or WS-BA coordinator service. This is stashed away for use when prepare/commit/close etc messages come in.
So, the web service normally talks to whatever service it is told to negotiate with. It does not normally have to provide its own URL. However, there is one case where it does need to do so -- when it wants to interpose a subordinate coordinator between itself and the one provided in the web service request. This is not 'nesting'. It is indirect coordination via an intermediary. If you use the XTS subordinate handler then when a request comes in the WS-T code creates a hiddent participant in the incoming WS-AT/BA transaction and ties it to a local 'subordinate' WS-AT/BA transaction which it creates by talking to its local coordinator service. It then registers the web service in the local transaction. If another web service gets called inside the same remote transaction it is also registered it in the local transaction but it does not need an extra hidden participant.
If, say, this is a WS-AT transaction then the hidden participant responds to an incoming prepare by calling prepare on the local subordinate. This may require the subordinate transaction to make several local prepare calls to the local web services. If they all work the subordinate transaction returns prepared and the hidden participant returns prepared. If it then receives a commit request it commits the lcoal transaction which commits each local participant. SImilarly it can handle an abort by rolling back the local subordinate transacton.
The benefit of using a subordinate transaction is that it only requires one non-local prepare/prepared and one non-local commit/committed even when multiple local web services are enlisted. So, this is just a performance optimization fo ruse when the coordinatro and web servcie are a long distance apart on the intrenet, The line which you are confused by refers to the fact that the subordinate coordinator has to be created by the coordinator service in the same container as the web service. If you set org.jboss.jbosts.xts.coordinatorURL in the web service container to point to a remote coordinator then the hidden participant will never find it and the subordinate transaction will never complete correctly. So, you cannot use stand-alone coordination in combination with subordinate coordinator interposition.
Now, that is not an issue with WS-AT ==> JTA bridging because you are not creating a local WS-AT transaction inside the incoming remote WS-AT transaction. The JTA transaction which your WS-AT bridges to is created using the local JTA coordinator. But that is what happens whenever yo create a JTA transaction. The bridge code does create a hidden WS-AT participant to prepare/commit/rollback the JTA transaction and to return the results back to it. But your code does nto need to care about that.
Ok, I hope that clears things up for you and anyone else who has managed to read this far :-)
regards,
Andrew Dinn