docs: public static void rcvXAPrepare(CommsByteBuffer request,
                                     Conversation conversation,
                                     int requestNumber,
                                     boolean allocatedFromBufferPool,
                                     boolean partOfExchange)
     {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(tc, "rcvXAPrepare",
                                             new Object[]
                                             {
                                                request,
                                                conversation,
                                                ""+requestNumber,
                                                ""+allocatedFromBufferPool,
                                                ""+partOfExchange
                                              });
  
        // PK61176 We need to clean up tran state in catch block if required. Scope vars appropriately.
        ConversationState convState = (ConversationState) conversation.getAttachment();
        ServerLinkLevelState linkState = (ServerLinkLevelState) conversation.getLinkLevelAttachment();
        SITransaction tran = null;
        int clientTransactionId = 0;
        XidProxy xid = null;
  
        final boolean optimizedTx = CommsUtils.requiresOptimizedTransaction(conversation);
  
        try
        {
           clientTransactionId = request.getInt();
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
           {
              SibTr.debug(tc, "XAResource Object ID", clientTransactionId);
           }
  
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Getting Xid");
           xid = (XidProxy) request.getXid();
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Completed:", xid);
  
           boolean endRequired = false;
           int endFlags = 0;
           if (optimizedTx)
           {
              endRequired = request.get() == 0x01;
              endFlags = request.getInt();
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              {
                 SibTr.debug(tc, "End Required:", ""+endRequired);
                 SibTr.debug(tc, "End Flags:", ""+endFlags);
              }
           }
  
           boolean requiresMSResource = false;
           if (conversation.getHandshakeProperties().getFapLevel() >= JFapChannelConstants.FAP_VERSION_5)
           {
              requiresMSResource = request.get() == 0x01;
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Requires MS Resource:", ""+requiresMSResource);
           }
  
           // Get the transaction out of the table
           if (endRequired) linkState.getTransactionTable().endOptimizedGlobalTransactionBranch(clientTransactionId, endFlags);
           tran = linkState.getTransactionTable().getResourceForGlobalTransactionBranch(clientTransactionId, xid);
  
           // If the UOW was never created (because we were running with the
           // optimization that gets an XAResource and enlists it as part of the
           // first piece of transacted work and this failed) then throw
           // an exception notifying the caller that the UOW has been rolled back.
           if (tran == IdToTransactionTable.INVALID_TRANSACTION)
           {
              Throwable throwable =
                 linkState.getTransactionTable().getExceptionForRollbackOnlyGlobalTransactionBranch(clientTransactionId, xid);
              String errorMsg =
                 nls.getFormattedMessage("TRANSACTION_MARKED_AS_ERROR_SICO2029",
                       new Object[]{ throwable },
                       null);
  
              XAException xa = new XAException(errorMsg);
              xa.initCause(throwable);
              xa.errorCode = XAException.XA_RBOTHER;
              throw xa;
           }
  
           // Get the actual transaction ...
           SIXAResource xaResource = getResourceFromTran(tran, convState, requiresMSResource);
  
           boolean isUnitOfWorkInError = false;
           if (tran != null)
           {
              isUnitOfWorkInError =
                 linkState.getTransactionTable().isGlobalTransactionBranchRollbackOnly(clientTransactionId, xid);
           }
  
           if (isUnitOfWorkInError)
           {
              // PK59276 Rollback the transaction, as after we throw a XA_RB* error the
              // transaction manager will not call us with xa_rollback.
              xaResource.rollback(xid);
  
              Throwable throwable = linkState.getTransactionTable().getExceptionForRollbackOnlyGlobalTransactionBranch(clientTransactionId, xid);
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "The transaction was marked as error due to",
                                                   throwable);
  
              // And respond with an error
              XAException xa = new XAException(
                 nls.getFormattedMessage("TRANSACTION_MARKED_AS_ERROR_SICO2029",
                                         new Object[]{ throwable },
                                         null)
              );
              xa.initCause(throwable);
              xa.errorCode = XAException.XA_RBOTHER;
  
              throw xa;
           }
  
           int rc = 0;
           try
           {
              // Now call the method on the XA resource
              rc = xaResource.prepare(xid);
           }
           finally
           {
              // Now mark the transaction as no longer in doubt. Ensure we always do this
              if (tran != null)
              {
                 // Remove transaction from table - as it is no longer in flight
                 linkState.getTransactionTable().removeGlobalTransactionBranch(clientTransactionId, xid);
              }
           }
  
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Prepare returned: " + rc);
  
           // PM23626 If we have enlisted in a read only transaction, for example when the only action within
           // the transaction is a synchronous receive that returned null, we also need to remove
           // the transaction from the dispatchable map - as we will not be called with commit/rollback.
           if (rc == XAException.XA_RDONLY)
           {
              linkState.getDispatchableMap().removeDispatchableForGlobalTransaction(clientTransactionId, xid);
           }
  
           CommsByteBuffer reply = poolManager.allocate();
           reply.putInt(rc);
  
           try
           {
              conversation.send(reply,
                                JFapChannelConstants.SEG_XAPREPARE_R,
                                requestNumber,
                                JFapChannelConstants.PRIORITY_MEDIUM,
                                true,
                                ThrottlingPolicy.BLOCK_THREAD,
                                null);
           }
           catch (SIException e)
           {
              FFDCFilter.processException(e,
                                          CLASS_NAME + ".rcvXAPrepare",
                                          CommsConstants.STATICCATXATRANSACTION_XAPREPARE_01);
  
              SibTr.error(tc, "COMMUNICATION_ERROR_SICO2027", e);
           }
        }
        catch (XAException e)
        {
           FFDCFilter.processException(e, CLASS_NAME + ".rcvXAPrepare", CommsConstants.STATICCATXATRANSACTION_XAPREPARE_02);
           
           // PK61176 If the XAException is a XA_RBXXXX then this will be the last time we will get called.
           // Remove transaction from table - as it is no longer in flight
           if (tran != null &&
               e.errorCode >= XAException.XA_RBBASE && e.errorCode <= XAException.XA_RBEND)
           {
             try
             {
               linkState.getTransactionTable().removeGlobalTransactionBranch(clientTransactionId, xid);
             }
             catch (SIErrorException sie)
             {
               // No FFDC Code Needed
               // We could potentially throw this exception because we have already called removeGlobalTransactionBranch in
               //  the finally block of the xaResource.prepare call. As other calls outside of that try-finally block can
               //  throw XAExceptions then we have no guarantee that we even called prepare so we still need this call here in
               //  the catch. We can't add a finally block to this call as we only want to remove the global tran in the case were
               //  we called prepare. The safest fix is just to catch this exception and move on.
               if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Caught SIErrorException when calling remoteGlobalTransactionBranch: " + sie);
             }
             
             linkState.getDispatchableMap().removeDispatchableForGlobalTransaction(clientTransactionId, xid);
           }
  
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "XAException - RC: " + e.errorCode, e);
  
           StaticCATHelper.sendExceptionToClient(e,
                                                 CommsConstants.STATICCATXATRANSACTION_XAPREPARE_02,
                                                 conversation, requestNumber);
        }
  
        request.release(allocatedFromBufferPool);
  
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "rcvXAPrepare");
     }