4 Replies Latest reply on Jul 28, 2008 12:11 PM by ruthbd

    Managing an "optionally" transactional web-service

      Good evening (or morning, in the UK). I am working on a web-service with the ws-tx to JTA bridge and this service is going to be "optionally" transactional. So, we have the coordination context pulled off the message (inbound) and then the inbound bridge runs, etc. - all good. On the way out, the bridge is stopped and the web services transaction is suspended via the ws-tx transaction manager.

      But, if the client doesn't provide a coordination context because they aren't consuming the service transactionally, then I want to essentially commit on my way out, instead of suspending, right? The reason I'm not just disabling everything is because this service consumes other services and those will be consumed transactionally, so even if the client isn't enlisting this service call in a transaction, anything that the service does should still be atomic.

      Any guidance or reprimanding is appreciated ;-)

      Thanks,
      Brice.

        • 1. Re: Managing an
          jhalliday

          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:

          Inbound:
          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.

          Outbound:
          1) modified bridge interceptor, either stop the bridge or commit the top level tx.
          2) modified XTS header context processor.

          • 2. Re: Managing an
            adinn

             


            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.

            • 3. Re: Managing an

              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.

              • 4. Re: Managing an

                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.