Hmm, so you want the same WS endpoint to support calls either with or without a transaction context on? Kind of like EJB's REQUIRED semantics I guess.
The bridge should not be used unless there is a ws-at tx context on the inbound call. It creates a JTA transaction that is designed to be driven by some external entity, which in such case does not exist. Instead you need to use the bridge if there is a context, or start a new top level JTA transaction if there is not.
It's made more complex by an assumption in the XTS header context processors, that they will be registered only on endpoints that are always transactional. i.e. it's expected a transaction context will be present. Usually you would expose your service via two different endpoints, one transactional and one not, with the interceptors only on the former.
I don't have the header context processor code to hand, but I think you may need to tweak it to ensure that it fails silent if there is no inbound context for it to process.
So the flow then is:
1) modified XTS header context processor, which will set a ws-at context on the thread if the headers exist on the inbound call, or do nothing if they don't.
2) Modified bridge interceptor, that will start a bridged JTA tx if there is a ws-at context on the thread, or a new top level JTA tx if there is not.
1) modified bridge interceptor, either stop the bridge or commit the top level tx.
2) modified XTS header context processor.
It's made more complex by an assumption in the XTS header context processors, that they will be registered only on endpoints that are always transactional. i.e. it's expected a transaction context will be present.
Don't think this is so looking at the XTS trunk JaxWS code. The inbound server header processor only attempts to resume a transaction if it finds a header identifying a WSCOOR coordination context. The outbound one only tries to suspend a transaction if there is a transaction manager or business activity manager current in the thread context. This is true for the 1.0 and 1.1 code.
So, the service endpoint can check for an incoming TX and if found create a dependent JTA TX, if not create a top-level JTA TX. As long as it commits or rolls back on the way out the header processing should work fine.
Yeah, I think I was looking at the inbound/outbound header processing first, and in fact I need to focus on where the bridge is started/stopped, especially stopping, so I can commit instead of suspending the top-level Tx.
OK, what I'm doing now (seems to be working) is if I don't detect a WSCOOR coordination context, then I ask the UserTransactionFactory for a new UserTransaction and begin() it. Then, the InboundBridge handler runs next and bridges to this "local" UserTransaction. On the way out, the InboundBridge handler stop()s the bridge, and the out header processor detects that no remote coordination existed for this call and commit()s the UserTransaction.
Seems to be working. This scenario should allow for remote coordination (interposition) as well as allowing this service to make additional service calls where it becomes the coordinating client, and be fairly seamless to its original client.