/*
* JBoss, Home of Professional Open Source
* Copyright 2016, Red Hat Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.test.integration.transaction.inflow;
import javax.resource.ResourceException;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.resource.spi.work.TransactionContext;
import javax.resource.spi.work.WorkException;
import javax.resource.spi.work.WorkManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.jboss.as.test.shared.TimeoutUtil;
import org.jboss.logging.Logger;
/**
* Implementation of resource adapter for transaction inflow testing.
*
* @author Ondrej Chaloupka <ochaloup@redhat.com>
*/
public class TransactionInflowResourceAdapter implements ResourceAdapter {
private static final Logger log = Logger.getLogger(TransactionInflowResourceAdapter.class);
private BootstrapContext bootstrapContext;
static final String MSG = "inflow RAR test message";
static final String ACTION_COMMIT = "commit";
static final String ACTION_ROLLBACK = "rollback";
public void start(BootstrapContext ctx) throws ResourceAdapterInternalException {
log.tracef("Starting '%s' with context '%s'", TransactionInflowResourceAdapter.class.getSimpleName(), ctx);
this.bootstrapContext = ctx;
}
public void stop() {
log.tracef("Stopping (do nothing) '%s'", TransactionInflowResourceAdapter.class.getSimpleName());
}
public void endpointActivation(MessageEndpointFactory endpointFactory, ActivationSpec spec) throws ResourceException {
Xid xid = TransactionInflowXid.getUniqueXid(42);
TransactionInflowWork work = new TransactionInflowWork(endpointFactory, MSG);
TransactionContext txnCtx = new TransactionContext();
txnCtx.setXid(xid);
TransactionInflowWorkListener workListener = new TransactionInflowWorkListener();
try {
bootstrapContext.getWorkManager().startWork(work, WorkManager.IMMEDIATE, txnCtx, workListener);
} catch (WorkException e) {
throw new IllegalStateException("Can't start work " + work + " with txn " + txnCtx);
}
// start Work blocks until the execution starts but not until its completion
int timeout = TimeoutUtil.adjust(10_000); // timeout 10 seconds
long start = System.currentTimeMillis();
while(!workListener.isCompleted() && (System.currentTimeMillis() - start < timeout)) {
Thread.yield(); // active waiting
}
if(!workListener.isCompleted()) throw new IllegalStateException("Work " + work + " of xid " + xid + " does not finish.");
try {
bootstrapContext.getXATerminator().prepare(xid);
// depends on value in spec we commit or roll-back
TransactionInflowRaSpec activationSpec = (TransactionInflowRaSpec) spec;
if(activationSpec.getAction().equals(ACTION_COMMIT)) {
bootstrapContext.getXATerminator().commit(xid, false);
} else if(activationSpec.getAction().equals(ACTION_ROLLBACK)) {
bootstrapContext.getXATerminator().rollback(xid);
} else {
new IllegalStateException("Spec '" + activationSpec + "' defines unknown action");
}
} catch (XAException xae) {
throw new IllegalStateException("Can't process prepare/commit/rollback calls for xid: " + xid, xae);
}
}
public void endpointDeactivation(MessageEndpointFactory endpointFactory, ActivationSpec spec) {
// nothing to do
}
public XAResource[] getXAResources(ActivationSpec[] specs) throws ResourceException {
return null;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bootstrapContext == null) ? 0 : bootstrapContext.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TransactionInflowResourceAdapter other = (TransactionInflowResourceAdapter) obj;
if (bootstrapContext == null) {
if (other.bootstrapContext != null)
return false;
} else if (!bootstrapContext.equals(other.bootstrapContext))
return false;
return true;
}
}