/** * Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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.synapse.message.store.impl.jms; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.MessageContext; import org.apache.synapse.message.MessageConsumer; import org.apache.synapse.message.store.Constants; import org.apache.synapse.message.store.impl.commons.MessageConverter; import org.apache.synapse.message.store.impl.commons.StorableMessage; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.ObjectMessage; import javax.jms.Session; public class JmsConsumer implements MessageConsumer { private static final Log logger = LogFactory.getLog(JmsConsumer.class.getName()); private Connection connection; private Session session; private javax.jms.MessageConsumer consumer; private JmsStore store; private String idString; private boolean isInitialized; /** Holds the last message read from the message store. */ private CachedMessage cachedMessage; /** Did last receive() call cause an error? */ private boolean isReceiveError; public JmsConsumer(JmsStore store) { if (store == null) { logger.error("Cannot initialize."); return; } this.store = store; cachedMessage = new CachedMessage(); isReceiveError = false; isInitialized = true; } public MessageContext receive() { boolean error; JMSException exception; if (!checkConnection()) { if (!reconnect()) { if (logger.isDebugEnabled()) { logger.debug(getId() + " cannot receive message from store. Cannot reconnect."); } return null; } else { logger.info(getId() + " reconnected to store."); isReceiveError = false; } } if (!checkConnection()) { if (logger.isDebugEnabled()) { logger.debug(getId() + " cannot receive message from store."); } return null; } try { Message message = consumer.receive(1); if (message == null) { return null; } if (!(message instanceof ObjectMessage)) { logger.warn(getId() + ". Did not receive a javax.jms.ObjectMessage"); message.acknowledge(); // TODO: return null; } ObjectMessage msg = (ObjectMessage) message; String messageId = msg.getStringProperty(Constants.OriginalMessageID); if (!(msg.getObject() instanceof StorableMessage)) { logger.warn(getId() + ". Did not receive a valid message."); message.acknowledge(); return null; } StorableMessage storableMessage = (StorableMessage) msg.getObject(); org.apache.axis2.context.MessageContext axis2Mc = store.newAxis2Mc(); MessageContext synapseMc = store.newSynapseMc(axis2Mc); synapseMc = MessageConverter.toMessageContext(storableMessage, axis2Mc, synapseMc); updateCache(message, synapseMc, messageId, false); if (logger.isDebugEnabled()) { logger.debug(getId() + " Received MessageId:" + messageId + " priority:" + message.getJMSPriority()); } return synapseMc; } catch (JMSException e) { error = true; exception = e; } if (error) { if (!isReceiveError) { logger.error(getId() + " cannot receive message from store. Error:" + exception.getLocalizedMessage());//, exception); } updateCache(null, null, "", true); cleanup(); return null; } return null; } public boolean ack() { boolean result = cachedMessage.ack(); if (result) { store.dequeued(); } return result; } public boolean cleanup() { if (logger.isDebugEnabled()) { logger.debug(getId() + " cleaning up..."); } boolean result = store.cleanup(connection, session, true); if (result) { connection = null; session = null; consumer = null; return true; } return false; } public boolean isAlive() { try { session.getAcknowledgeMode(); /** No straight forward way to check session availability */ } catch (JMSException e) { return false; } return true; } public Connection getConnection() { return connection; } public JmsConsumer setConnection(Connection connection) { this.connection = connection; return this; } public Session getSession() { return session; } public JmsConsumer setSession(Session session) { this.session = session; return this; } public javax.jms.MessageConsumer getConsumer() { return consumer; } public JmsConsumer setConsumer(javax.jms.MessageConsumer consumer) { this.consumer = consumer; return this; } public boolean isInitialized() { return isInitialized; } public void setId(int id) { idString = "[" + store.getName() + "-C-" + id + "]"; } public void setStringId(String idString) { this.idString = idString; } public String getId() { return getIdAsString(); } private String getIdAsString() { if (idString == null) { return "[unknown-consumer]"; } return idString; } private boolean checkConnection() { if (consumer == null) { if (logger.isDebugEnabled()) { logger.debug(getId() + " cannot proceed. Message consumer is null."); } return false; } if (session == null) { if (logger.isDebugEnabled()) { logger.debug(getId() + " cannot proceed. JMS Session is null."); } return false; } if (connection == null) { if (logger.isDebugEnabled()) { logger.debug(getId() + " cannot proceed. JMS Connection is null."); } return false; } return true; } private void writeToFileSystem() { } private void updateCache(Message message, MessageContext synCtx, String messageId, boolean receiveError) { isReceiveError = receiveError; cachedMessage.setMessage(message); cachedMessage.setMc(synCtx); cachedMessage.setId(messageId); } private boolean reconnect() { JmsConsumer consumer = (JmsConsumer) store.getConsumer(); if (consumer.getConsumer() == null) { if (logger.isDebugEnabled()) { logger.debug(getId() + " could not reconnect to the broker."); } return false; } connection = consumer.getConnection(); session = consumer.getSession(); this.consumer = consumer.getConsumer(); if (logger.isDebugEnabled()) { logger.debug(getId() + " ===> " + consumer.getId()); } //setStringId(consumer.getId()); return true; } private final class CachedMessage { private Message message = null; private MessageContext mc = null; private String id = ""; public CachedMessage setMessage(Message message) { this.message = message; return this; } public boolean ack() { try { if (message != null) { message.acknowledge(); } } catch (javax.jms.IllegalStateException e) { logger.warn("JMS Session is in an illegal state. Recovering session."); try { getSession().recover(); logger.warn("JMS Session recovered."); } catch (JMSException e1) { logger.error("Error occurred while recovering session: " + e.getLocalizedMessage(), e); return false; } return false; } catch (JMSException e) { logger.error(getId() + " cannot ack last read message. Error:" + e.getLocalizedMessage(), e); return false; } return true; } public Message getMessage() { return message; } public CachedMessage setMc(MessageContext mc) { this.mc = mc; return this; } public CachedMessage setId(String id) { this.id = id; return this; } public String getId() { return id; } } }