Search in sources :

Example 1 with TransactionalState

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();
            }
        }
    });
}
Also used : ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) SimpleString(org.apache.activemq.artemis.api.core.SimpleString) IOCallback(org.apache.activemq.artemis.core.io.IOCallback) TransactionalState(org.apache.qpid.proton.amqp.transaction.TransactionalState)

Example 2 with TransactionalState

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();
        }
    }
}
Also used : Transaction(org.apache.activemq.artemis.core.transaction.Transaction) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) Receiver(org.apache.qpid.proton.engine.Receiver) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ActiveMQSecurityException(org.apache.activemq.artemis.api.core.ActiveMQSecurityException) ActiveMQAMQPInternalErrorException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException) ActiveMQAMQPNotFoundException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException) ActiveMQAMQPException(org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException) ActiveMQSecurityException(org.apache.activemq.artemis.api.core.ActiveMQSecurityException) TransactionalState(org.apache.qpid.proton.amqp.transaction.TransactionalState)

Example 3 with TransactionalState

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();
}
Also used : ClientFuture(org.apache.activemq.transport.amqp.client.util.ClientFuture) Binary(org.apache.qpid.proton.amqp.Binary) JmsOperationTimedOutException(org.apache.qpid.jms.JmsOperationTimedOutException) InvalidDestinationException(javax.jms.InvalidDestinationException) IOException(java.io.IOException) TransactionalState(org.apache.qpid.proton.amqp.transaction.TransactionalState)

Example 4 with TransactionalState

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();
    }
}
Also used : Delivery(org.apache.qpid.proton.engine.Delivery) Binary(org.apache.qpid.proton.amqp.Binary) TransactionalState(org.apache.qpid.proton.amqp.transaction.TransactionalState)

Example 5 with TransactionalState

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();
}
Also used : AmqpSender(org.apache.activemq.transport.amqp.client.AmqpSender) Sender(org.apache.qpid.proton.engine.Sender) AmqpConnection(org.apache.activemq.transport.amqp.client.AmqpConnection) AmqpSession(org.apache.activemq.transport.amqp.client.AmqpSession) AmqpReceiver(org.apache.activemq.transport.amqp.client.AmqpReceiver) AmqpClient(org.apache.activemq.transport.amqp.client.AmqpClient) Delivery(org.apache.qpid.proton.engine.Delivery) AmqpSender(org.apache.activemq.transport.amqp.client.AmqpSender) AmqpMessage(org.apache.activemq.transport.amqp.client.AmqpMessage) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) AmqpValidator(org.apache.activemq.transport.amqp.client.AmqpValidator) TransactionalState(org.apache.qpid.proton.amqp.transaction.TransactionalState) Test(org.junit.Test)

Aggregations

TransactionalState (org.apache.qpid.proton.amqp.transaction.TransactionalState)8 Delivery (org.apache.qpid.proton.engine.Delivery)4 Accepted (org.apache.qpid.proton.amqp.messaging.Accepted)3 Rejected (org.apache.qpid.proton.amqp.messaging.Rejected)3 DeliveryState (org.apache.qpid.proton.amqp.transport.DeliveryState)3 ErrorCondition (org.apache.qpid.proton.amqp.transport.ErrorCondition)3 IOException (java.io.IOException)2 InvalidDestinationException (javax.jms.InvalidDestinationException)2 ActiveMQSecurityException (org.apache.activemq.artemis.api.core.ActiveMQSecurityException)2 SimpleString (org.apache.activemq.artemis.api.core.SimpleString)2 IOCallback (org.apache.activemq.artemis.core.io.IOCallback)2 ActiveMQAMQPException (org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException)2 ActiveMQAMQPInternalErrorException (org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException)2 ActiveMQAMQPNotFoundException (org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException)2 AmqpClient (org.apache.activemq.transport.amqp.client.AmqpClient)2 AmqpConnection (org.apache.activemq.transport.amqp.client.AmqpConnection)2 AmqpMessage (org.apache.activemq.transport.amqp.client.AmqpMessage)2 AmqpSender (org.apache.activemq.transport.amqp.client.AmqpSender)2 AmqpSession (org.apache.activemq.transport.amqp.client.AmqpSession)2 AmqpValidator (org.apache.activemq.transport.amqp.client.AmqpValidator)2