org.apache.activemq.artemis.jms.client.ThreadAwareContext Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.jms.client;
import jakarta.jms.IllegalStateException;
import java.util.Set;
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
/**
* Restricts what can be called on context passed in wrapped CompletionListener.
*/
public class ThreadAwareContext {
/**
* Necessary in order to assert some methods ({@link jakarta.jms.JMSContext#stop()}
* {@link jakarta.jms.JMSContext#close()} etc) are not getting called from within a
* {@link jakarta.jms.CompletionListener}.
*
* @see ThreadAwareContext#assertNotMessageListenerThread()
*/
private Thread completionListenerThread;
/**
* Use a set because JMSContext can create more than one JMSConsumer
* to receive asynchronously from different destinations.
*/
private final Set messageListenerThreads = new ConcurrentHashSet<>();
/**
* Sets current thread to the context
*
* Meant to inform an JMSContext which is the thread that CANNOT call some of its methods.
*
*
* @param isCompletionListener : indicating whether current thread is from CompletionListener
* or from MessageListener.
*/
public void setCurrentThread(boolean isCompletionListener) {
if (isCompletionListener) {
completionListenerThread = Thread.currentThread();
} else {
messageListenerThreads.add(Thread.currentThread().getId());
}
}
/**
* Clear current thread from the context
*
* @param isCompletionListener : indicating whether current thread is from CompletionListener
* or from MessageListener.
*/
public void clearCurrentThread(boolean isCompletionListener) {
if (isCompletionListener) {
completionListenerThread = null;
} else {
messageListenerThreads.remove(Thread.currentThread().getId());
}
}
/**
* Asserts a {@link jakarta.jms.CompletionListener} is not calling from its own {@link jakarta.jms.JMSContext}.
*
* Note that the code must work without any need for further synchronization, as there is the
* requirement that only one CompletionListener be called at a time. In other words,
* CompletionListener calling is single-threaded.
*
* @see jakarta.jms.JMSContext#close()
* @see jakarta.jms.JMSContext#stop()
* @see jakarta.jms.JMSContext#commit()
* @see jakarta.jms.JMSContext#rollback()
*/
public void assertNotCompletionListenerThreadRuntime() {
if (completionListenerThread == Thread.currentThread()) {
throw ActiveMQJMSClientBundle.BUNDLE.callingMethodFromCompletionListenerRuntime();
}
}
/**
* Asserts a {@link jakarta.jms.CompletionListener} is not calling from its own {@link jakarta.jms.Connection} or from
* a {@link jakarta.jms.MessageProducer} .
*
* Note that the code must work without any need for further synchronization, as there is the
* requirement that only one CompletionListener be called at a time. In other words,
* CompletionListener calling is single-threaded.
*
* @see jakarta.jms.Connection#close()
* @see jakarta.jms.MessageProducer#close()
*/
public void assertNotCompletionListenerThread() throws jakarta.jms.IllegalStateException {
if (completionListenerThread == Thread.currentThread()) {
throw ActiveMQJMSClientBundle.BUNDLE.callingMethodFromCompletionListener();
}
}
/**
* Asserts a {@link jakarta.jms.MessageListener} is not calling from its own {@link jakarta.jms.JMSContext}.
*
* Note that the code must work without any need for further synchronization, as there is the
* requirement that only one MessageListener be called at a time. In other words,
* MessageListener calling is single-threaded.
*
* @see jakarta.jms.JMSContext#close()
* @see jakarta.jms.JMSContext#stop()
*/
public void assertNotMessageListenerThreadRuntime() {
if (messageListenerThreads.contains(Thread.currentThread().getId())) {
throw ActiveMQJMSClientBundle.BUNDLE.callingMethodFromListenerRuntime();
}
}
/**
* Asserts a {@link jakarta.jms.MessageListener} is not calling from its own {@link jakarta.jms.Connection} or
* {@link jakarta.jms.MessageConsumer}.
*
* Note that the code must work without any need for further synchronization, as there is the
* requirement that only one MessageListener be called at a time. In other words,
* MessageListener calling is single-threaded.
*
* @see jakarta.jms.Connection#close()
* @see jakarta.jms.MessageConsumer#close()
*/
public void assertNotMessageListenerThread() throws IllegalStateException {
if (messageListenerThreads.contains(Thread.currentThread().getId())) {
throw ActiveMQJMSClientBundle.BUNDLE.callingMethodFromListener();
}
}
}