Skip to content

Commit

Permalink
Merge pull request wildfly#13539 from ochaloup/WFLY-13283-rollback-ac…
Browse files Browse the repository at this point in the history
…tive-txn-inbound-rts-bridge-new

[WFLY-13283] suspending WFTC transaction on response of REST-AT bridge
  • Loading branch information
bstansberry committed Dec 16, 2020
2 parents a7d0340 + 46f8ecb commit 05c17d5
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,45 @@
package org.wildfly.extension.rts.jaxrs;

import java.io.IOException;
import javax.annotation.Priority;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
import org.wildfly.extension.rts.logging.RTSLogger;
import org.wildfly.transaction.client.ContextTransactionManager;
import org.wildfly.transaction.client.LocalTransactionContext;


/**
* Filter which is expected to be called after {@link InboundBridgeFilter} is processed.<br>
* Inbound bridge manages transactions on Narayana side and this filter causes the transaction
* from Narayana being imported by Wildfly transaction client.
* <p>
* Request and response filter which is expected to be called
* for the request side after the {@link org.jboss.narayana.rest.bridge.inbound.InboundBridgeFilter} is processed
* while on the response side before the {@link org.jboss.narayana.rest.bridge.inbound.InboundBridgeFilter} is processed.
* </p>
* <p>
* Purpose of this filter is an integration of WFTC with Narayana REST-AT Inbound Bridge.
* Inbound Bridge uses Narayana transactions while WFLY utilizes WFTC transactions (wrapping the underlaying Narayana) ones.
* For that on request side the Inbound bridge first creates the Narayana transaction and then the request
* filter makes the WFTC to wrap and to know about this transaction.
* On the response side the WFTC needs to suspend its wrapping transaction and then Narayana suspend its own
* transaction (which was already suspended by WFTC callback and thus is ignored on the Narayana side).
* </p>
* <p>
* The {@link org.jboss.narayana.rest.bridge.inbound.InboundBridgeFilter} defines its {@link Priority}
* as <code>{@code Priorities#USER}-100</code>. This WildFly filter has to be processed after the Narayana
* one and it needs to define higher priority.
* </p>
*
* @author Ondrej Chaloupka <ochaloup@redhat.com>
*/
@Provider
public class ImportWildflyClientGlobalTransactionFilter implements ContainerRequestFilter {
@Priority(Priorities.USER - 80)
public class ImportWildflyClientGlobalTransactionFilter implements ContainerRequestFilter, ContainerResponseFilter {

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Expand All @@ -50,4 +72,16 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
}
}

@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
try {
// suspending context before returning to the client
if (ContextTransactionManager.getInstance() != null &&
ContextTransactionManager.getInstance().getStatus() != Status.STATUS_NO_TRANSACTION) {
ContextTransactionManager.getInstance().suspend();
}
} catch (SystemException se) {
RTSLogger.ROOT_LOGGER.cannotGetTransactionStatus(responseContext, se);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
package org.wildfly.extension.rts.logging;

import javax.transaction.SystemException;
import javax.ws.rs.container.ContainerResponseContext;

import org.jboss.logging.BasicLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.annotations.Cause;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;

import static org.jboss.logging.Logger.Level.ERROR;

/**
*
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a>
Expand All @@ -41,4 +46,8 @@ public interface RTSLogger extends BasicLogger {

@Message(id = 1, value = "Can't import global transaction to wildfly transaction client.")
IllegalStateException failueOnImportingGlobalTransactionFromWildflyClient(@Cause SystemException se);

@LogMessage(level = ERROR)
@Message(id = 2, value = "Cannot get transaction status on handling response context %s")
void cannotGetTransactionStatus(ContainerResponseContext responseCtx, @Cause Throwable cause);
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
*/
public class XTSHandlerDeploymentProcessor implements DeploymentUnitProcessor {

private static final String TX_BRIDGE_HANDLER = OptionalJaxWSTxInboundBridgeHandler.class.getName();
private static final String TX_BRIDGE_WFTC_INTEGRATION_HANDLER = WildflyTransactionClientTxBridgeIntegrationHandler.class.getName();
private static final String TX_BRIDGE_HANDLER = OptionalJaxWSTxInboundBridgeHandler.class.getName();
private static final String TX_CONTEXT_HANDLER = JaxWSHeaderContextProcessor.class.getName();

public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,44 @@
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.MessageContext;

import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.txn.deployment.TransactionRollbackSetupAction;
import org.jboss.as.xts.XTSHandlerDeploymentProcessor;
import org.jboss.as.xts.jandex.EndpointMetaData;
import org.jboss.as.xts.logging.XtsAsLogger;
import org.jboss.wsf.spi.deployment.Endpoint;
import org.jboss.wsf.spi.invocation.Invocation;
import org.wildfly.transaction.client.ContextTransactionManager;

import java.util.List;

/**
* <p>
* Handler to integrate the handle message event with WildFly Transaction client (WFTC) SPI.
* This handler has to be defined in order to be called after the {@link OptionalJaxWSTxInboundBridgeHandler}.
* Check the handler enlistment at {@link XTSHandlerDeploymentProcessor}.
* Handler integrating the handle message event with WildFly Transaction Client (WFTC) SPI.
* </p>
* <p>
* This handler manages the outbound processing where it has to be processed
* before the {@link org.jboss.jbossts.txbridge.inbound.OptionalJaxWSTxInboundBridgeHandler}.
* Check the handler enlistment at {@link XTSHandlerDeploymentProcessor#updateXTSEndpoint(String, EndpointMetaData, List, DeploymentUnit)}.
* <p>
* <p>
* <i>NOTE:</i> the order of the JAX-WS handlers are defined as:
* <q>For outbound messages handler processing starts with the first handler in the chain
* and proceeds in the same order as the handler chain.
* For inbound messages the order of processing is reversed.
* </q>
* </p>
* <p>
* Importing transaction for incoming WS message is handled by WS integration class: AbstractInvocationHandler
* where the interceptor context is filled with the imported transaction.
* This handler works on outbound side. The inbound side is handled by WS integration class:
* {@link org.jboss.as.webservices.invocation.AbstractInvocationHandler#invokeInternal(Endpoint, Invocation)}.
* There is the place where WFTC imports the Narayana transaction for the incoming WS message.
* </p>
* <p>
* When the call leaves eJB there is invoked handler {@link TransactionRollbackSetupAction} verifying existence of the transactions.
* At that time the transaction should be suspended. In case of WS call where XTS transaction was imported the suspend
* of the transaction is done in XTS handler. This handler is part of the Narayana code and the transaction is thus suspended.
* But WFTC stores its own notion about transaction existence and none suspends the WFTC
* The outbound filter is useful for suspending the WFTC wrapper transaction. Otherwise only the underlaying Narayana transaction is suspended
* (Narayana XTS txbridge inbound filter does so).
* Then when the call leaves EJB there is invoked handler {@link TransactionRollbackSetupAction} verifying existence of the transactions.
* If the the WFTC transaction is not suspended then the setup action rolls-back it which leads to an errors in the server log.
* </p>
*/
public class WildflyTransactionClientTxBridgeIntegrationHandler implements Handler<MessageContext> {

Expand Down

0 comments on commit 05c17d5

Please sign in to comment.