/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.message.broker.impl;
import org.opencastproject.message.broker.api.MessageReceiver;
import org.opencastproject.message.broker.api.MessageSender.DestinationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InterruptedIOException;
import java.io.Serializable;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.ObjectMessage;
/**
* A class to receive messages from a ActiveMQ Message Broker.
*/
public class MessageReceiverImpl extends MessageBaseFacility implements MessageReceiver {
/** The logging facility */
private static final Logger logger = LoggerFactory.getLogger(MessageReceiverImpl.class);
/** The OSGi service PID */
private static final String SERVICE_PID = "org.opencastproject.message.broker.impl.MessageReceiverImpl";
/**
* Private function to get a message or none if there is an error.
*
* @param destinationId
* The destination queue or topic to pull the message from.
* @param type
* The type of the destination either queue or topic.
* @return A message or none if there was a problem getting the message.
*/
private Message waitForMessage(String destinationId, DestinationType type) {
if (getSession() == null || !isConnected()) {
return null;
}
MessageConsumer consumer = null;
try {
// Create the destination (Topic or Queue)
Destination destination;
if (type.equals(DestinationType.Queue)) {
destination = getSession().createQueue(destinationId);
} else {
destination = getSession().createTopic(destinationId);
}
// Create a MessageConsumer from the Session to the Topic or Queue
try {
consumer = getSession().createConsumer(destination);
} catch (JMSException e) {
if (e.getCause() instanceof InterruptedIOException) {
logger.trace("Exception due to message receiver shutdown: {}", e);
} else {
throw e;
}
}
// Wait for a message
return consumer.receive();
} catch (JMSException e) {
if (isConnected()) {
logger.error("Unable to receive messages", e);
}
} finally {
try {
if (consumer != null) {
consumer.close();
}
} catch (JMSException e) {
logger.error("Unable to close connections after receipt of message", e);
}
}
return null;
}
protected Serializable getSerializable(String destinationId, DestinationType type) {
Serializable messageObject = null;
while (true) {
// Wait for a message
Message message = waitForMessage(destinationId, type);
if (message != null && message instanceof ObjectMessage) {
ObjectMessage objectMessage = (ObjectMessage) message;
try {
return objectMessage.getObject();
} catch (JMSException e) {
logger.error("Unable to get message {}", message, e);
}
}
logger.debug("Skipping invalid message: {}", message);
/* Try to reconnect */
if (!isConnected() && !connectMessageBroker()) {
return null;
}
}
}
@Override
public FutureTask<Serializable> receiveSerializable(final String destinationId, final DestinationType type) {
FutureTask<Serializable> futureTask = new FutureTask<Serializable>(new Callable<Serializable>() {
@Override
public Serializable call() {
return getSerializable(destinationId, type);
}
});
return futureTask;
}
}