use of org.apache.qpid.proton.amqp.transaction.TransactionalState in project activemq-artemis by apache.
the class AMQPSessionCallback method serverSend.
private void serverSend(final Transaction transaction, final Message message, final Delivery delivery, final Receiver receiver) throws Exception {
message.setConnectionID(receiver.getSession().getConnection().getRemoteContainer());
invokeIncoming((AMQPMessage) message, (ActiveMQProtonRemotingConnection) transportConnection.getProtocolConnection());
serverSession.send(transaction, message, false, false);
afterIO(new IOCallback() {
@Override
public void done() {
connection.lock();
try {
if (delivery.getRemoteState() instanceof TransactionalState) {
TransactionalState txAccepted = new TransactionalState();
txAccepted.setOutcome(Accepted.getInstance());
txAccepted.setTxnId(((TransactionalState) delivery.getRemoteState()).getTxnId());
delivery.disposition(txAccepted);
} else {
delivery.disposition(Accepted.getInstance());
}
delivery.settle();
} finally {
connection.unlock();
}
connection.flush();
}
@Override
public void onError(int errorCode, String errorMessage) {
connection.lock();
try {
receiver.setCondition(new ErrorCondition(AmqpError.ILLEGAL_STATE, errorCode + ":" + errorMessage));
connection.flush();
} finally {
connection.unlock();
}
}
});
}
use of org.apache.qpid.proton.amqp.transaction.TransactionalState in project activemq-artemis by apache.
the class ProtonServerReceiverContext method onMessage.
/*
* called when Proton receives a message to be delivered via a Delivery.
*
* This may be called more than once per deliver so we have to cache the buffer until we have received it all.
*
* */
@Override
public void onMessage(Delivery delivery) throws ActiveMQAMQPException {
Receiver receiver;
try {
if (!delivery.isReadable()) {
return;
}
if (delivery.isPartial()) {
return;
}
receiver = ((Receiver) delivery.getLink());
Transaction tx = null;
byte[] data;
data = new byte[delivery.available()];
receiver.recv(data, 0, data.length);
receiver.advance();
if (delivery.getRemoteState() instanceof TransactionalState) {
TransactionalState txState = (TransactionalState) delivery.getRemoteState();
tx = this.sessionSPI.getTransaction(txState.getTxnId(), false);
}
sessionSPI.serverSend(this, tx, receiver, delivery, address, delivery.getMessageFormat(), data);
flow(amqpCredits, minCreditRefresh);
} catch (Exception e) {
log.warn(e.getMessage(), e);
Rejected rejected = new Rejected();
ErrorCondition condition = new ErrorCondition();
if (e instanceof ActiveMQSecurityException) {
condition.setCondition(AmqpError.UNAUTHORIZED_ACCESS);
} else {
condition.setCondition(Symbol.valueOf("failed"));
}
condition.setDescription(e.getMessage());
rejected.setError(condition);
connection.lock();
try {
delivery.disposition(rejected);
delivery.settle();
} finally {
connection.unlock();
}
}
}
use of org.apache.qpid.proton.amqp.transaction.TransactionalState in project activemq-artemis by apache.
the class AmqpReceiver method accept.
/**
* Accepts a message that was dispatched under the given Delivery instance.
*
* This method allows for the session that is used in the accept to be specified by the
* caller. This allows for an accepted message to be involved in a transaction that is being
* managed by some other session other than the one that created this receiver.
*
* @param delivery
* the Delivery instance to accept.
* @param session
* the session under which the message is being accepted.
* @param settle
* true if the receiver should settle the delivery or just send the disposition.
*
* @throws IOException
* if an error occurs while sending the accept.
*/
public void accept(final Delivery delivery, final AmqpSession session, final boolean settle) throws IOException {
checkClosed();
if (delivery == null) {
throw new IllegalArgumentException("Delivery to accept cannot be null");
}
if (session == null) {
throw new IllegalArgumentException("Session given cannot be null");
}
if (session.getConnection() != this.session.getConnection()) {
throw new IllegalArgumentException("The session used for accept must originate from the connection that created this receiver.");
}
final ClientFuture request = new ClientFuture();
session.getScheduler().execute(new Runnable() {
@Override
public void run() {
checkClosed();
try {
if (!delivery.isSettled()) {
if (session.isInTransaction()) {
Binary txnId = session.getTransactionId().getRemoteTxId();
if (txnId != null) {
TransactionalState txState = new TransactionalState();
txState.setOutcome(Accepted.getInstance());
txState.setTxnId(txnId);
delivery.disposition(txState);
session.getTransactionContext().registerTxConsumer(AmqpReceiver.this);
}
} else {
delivery.disposition(Accepted.getInstance());
}
if (settle) {
delivery.settle();
}
}
session.pumpToProtonTransport(request);
request.onSuccess();
} catch (Exception e) {
request.onFailure(e);
}
}
});
request.sync();
}
use of org.apache.qpid.proton.amqp.transaction.TransactionalState in project activemq-artemis by apache.
the class AmqpSender method doSend.
private void doSend(AmqpMessage message, AsyncResult request, AmqpTransactionId txId) throws Exception {
LOG.trace("Producer sending message: {}", message);
Delivery delivery = null;
if (presettle) {
delivery = getEndpoint().delivery(EMPTY_BYTE_ARRAY, 0, 0);
} else {
byte[] tag = tagGenerator.getNextTag();
delivery = getEndpoint().delivery(tag, 0, tag.length);
}
delivery.setContext(request);
Binary amqpTxId = null;
if (txId != null) {
amqpTxId = txId.getRemoteTxId();
} else if (session.isInTransaction()) {
amqpTxId = session.getTransactionId().getRemoteTxId();
}
if (amqpTxId != null) {
TransactionalState state = new TransactionalState();
state.setTxnId(amqpTxId);
delivery.disposition(state);
}
encodeAndSend(message.getWrappedMessage(), delivery);
if (presettle) {
delivery.settle();
request.onSuccess();
} else {
pending.add(delivery);
getEndpoint().advance();
}
}
use of org.apache.qpid.proton.amqp.transaction.TransactionalState in project activemq-artemis by apache.
the class AmqpTransactionTest method testUnsettledTXMessageGetTransactedDispostion.
@Test(timeout = 30000)
public void testUnsettledTXMessageGetTransactedDispostion() throws Exception {
AmqpClient client = createAmqpClient();
AmqpConnection connection = addConnection(client.connect());
AmqpSession session = connection.createSession();
assertNotNull(session);
AmqpSender sender = session.createSender(getQueueName());
AmqpMessage message = new AmqpMessage();
message.setText("Test-Message");
sender.send(message);
AmqpReceiver receiver = session.createReceiver(getQueueName());
receiver.setStateInspector(new AmqpValidator() {
@Override
public void inspectDeliveryUpdate(Sender sender, Delivery delivery) {
if (delivery.remotelySettled()) {
LOG.info("Receiver got delivery update for: {}", delivery);
if (!(delivery.getRemoteState() instanceof TransactionalState)) {
markAsInvalid("Transactionally acquire work no tagged as being in a transaction.");
} else {
TransactionalState txState = (TransactionalState) delivery.getRemoteState();
if (!(txState.getOutcome() instanceof Accepted)) {
markAsInvalid("Transaction state lacks any outcome");
} else if (txState.getTxnId() == null) {
markAsInvalid("Transaction state lacks any TX Id");
}
}
if (!(delivery.getLocalState() instanceof TransactionalState)) {
markAsInvalid("Transactionally acquire work no tagged as being in a transaction.");
} else {
TransactionalState txState = (TransactionalState) delivery.getLocalState();
if (!(txState.getOutcome() instanceof Accepted)) {
markAsInvalid("Transaction state lacks any outcome");
} else if (txState.getTxnId() == null) {
markAsInvalid("Transaction state lacks any TX Id");
}
}
TransactionalState localTxState = (TransactionalState) delivery.getLocalState();
TransactionalState remoteTxState = (TransactionalState) delivery.getRemoteState();
if (!localTxState.getTxnId().equals(remoteTxState)) {
markAsInvalid("Message not enrolled in expected transaction");
}
}
}
});
session.begin();
assertTrue(session.isInTransaction());
receiver.flow(1);
AmqpMessage received = receiver.receive(2, TimeUnit.SECONDS);
assertNotNull(received);
received.accept(false);
session.commit();
sender.getStateInspector().assertValid();
connection.close();
}
Aggregations