All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.netgrid.bauer.impl.FfmqTopicFactory Maven / Gradle / Ivy

package it.netgrid.bauer.impl;

import java.util.Hashtable;

import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import it.netgrid.bauer.EventHandler;
import it.netgrid.bauer.ITopicFactory;
import it.netgrid.bauer.Topic;
import it.netgrid.bauer.TopicFactory;
import net.timewalker.ffmq3.FFMQConstants;

public class FfmqTopicFactory implements ITopicFactory, ExceptionListener {
	
	private static final Logger log = LoggerFactory.getLogger(FfmqTopicFactory.class);
	
	private static Gson gson;
	
	static {
		GsonBuilder gsonBuilder = new GsonBuilder();
		gsonBuilder.setFieldNamingStrategy(new GsonNamingStrategy()); 
		gson = gsonBuilder.create();
	}
	
	public static final String PROVIDER_URL_PROP = "ffmqProvider";
	public static final String MESSAGE_HANDLER_RETRY_RATE_PROP = "messageHandlerRetry";
	public static final String MESSAGE_HANDLER_MAX_RETRY_PROP = "messageHandlerMaxRetry";
	
	public static final String DEFAULT_PROVIDER_URL = "tcp://localhost:10002";
	public static final String DEFAULT_MESSAGE_HANDLER_RETRY_RATE = "2000";
	public static final String DEFAULT_MESSAGE_HANDLER_MAX_RETRY = "10";
	
	private static final String TOPIC_USERNAME_NAME_FORMAT = "topic.%s.username";
	private static final String TOPIC_PASSWORD_NAME_FORMAT = "topic.%s.password";
	
	private Context context;
	private TopicConnectionFactory connFactory;
	

	@Override
	public  Topic getTopic(String name) {
		return new FfmqTopic(name, this);
	}

	private Context getContext() {
		if(context == null) {
			// Create and initialize a JNDI context
			Hashtable env = new Hashtable();
			env.put(Context.INITIAL_CONTEXT_FACTORY, FFMQConstants.JNDI_CONTEXT_FACTORY);
			env.put(Context.PROVIDER_URL, TopicFactory.getProperties().getProperty(FfmqTopicFactory.PROVIDER_URL_PROP, DEFAULT_PROVIDER_URL));
	
			try {
				context = new InitialContext(env);
			} catch (NamingException e) {
				log.error(e.getMessage(), e);
				context = null;
			}
		}
		
		return context;
		
	}
	
	private TopicConnectionFactory getConnFactory() {
		if(this.connFactory == null) {
			try {
				connFactory = (TopicConnectionFactory)this.getContext().lookup(FFMQConstants.JNDI_TOPIC_CONNECTION_FACTORY_NAME);
			} catch (NamingException e) {
				log.error(e.getMessage(), e);
				connFactory = null;
			}
		}
		
		return this.connFactory;
	}
	
	public MessageProducer getMessageProducer(TopicSession session, String topicName) {
		try {
			javax.jms.Topic topic = session.createTopic(topicName);
			return session.createProducer(topic);
		} catch (JMSException e) {
			log.error(e.getMessage(), e);
			return null;
		}
	}
	
	public TopicSubscriber getTopicSubscriber(TopicSession session, String topicName, String subscriberName) {
		if(session == null) {
			log.error(String.format("Unable to create topic in null session: %s %s", topicName, subscriberName));
			return null;
		}
		
		try {
			javax.jms.Topic topic = session.createTopic(topicName);
			return session.createDurableSubscriber(topic, subscriberName);
		} catch (JMSException e) {
			log.error(e.getMessage(), e);
			return null;
		}
	}
	
	public TopicSession buildTopicConsumerSession(String topicName, String subscriberName) {
		TopicConnection conn;
		try {
			conn = this.initTopicConsumerConnection(topicName, subscriberName);
			TopicSession session = conn.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);
			if(session == null) {
				log.error(String.format("Unable to create session for: %s %s", topicName, subscriberName));
				return null;
			}
			return session;
		} catch (JMSException e) {
			log.error(e.getMessage(), e);
			return null;
		}
	}
	
	public TopicSession buildTopicProducerSession(String topicName) {
		TopicConnection conn;
		try {
			conn = this.initTopicProducerConnection(topicName);
			conn.setExceptionListener(this);
			conn.start();
			return conn.createTopicSession(true, Session.AUTO_ACKNOWLEDGE);
		} catch (JMSException e) {
			log.error(e.getMessage(), e);
			return null;
		}		
	}
	
	private TopicConnection initTopicProducerConnection(String topicName) throws JMSException {
		TopicConnection retval;
		if(this.needsCredentials(topicName)) {
			retval = this.getConnFactory().createTopicConnection(this.getUsername(topicName), this.getPassword(topicName));
		} else {
			retval = this.getConnFactory().createTopicConnection();
		}
		return retval;
	}
	
	private TopicConnection initTopicConsumerConnection(String topicName, String clientID) throws JMSException {
		TopicConnection retval;
		if(this.needsCredentials(topicName)) {
			retval = this.getConnFactory().createTopicConnection(this.getUsername(topicName), this.getPassword(topicName));
		} else {
			retval = this.getConnFactory().createTopicConnection();
		}
		retval.setClientID(clientID);
		retval.start();
		return retval;
	}
	
	private boolean needsCredentials(String topicName) {
		return this.getUsername(topicName) != null &&
			this.getPassword(topicName) != null;
		
	}
	
	public int getHandlerMaxRetry() {
		return Integer.parseInt(TopicFactory.getProperties().getProperty(MESSAGE_HANDLER_MAX_RETRY_PROP, DEFAULT_MESSAGE_HANDLER_MAX_RETRY));
	}
	
	public int getHandlerRetryRate() {
		return Integer.parseInt(TopicFactory.getProperties().getProperty(MESSAGE_HANDLER_RETRY_RATE_PROP, DEFAULT_MESSAGE_HANDLER_RETRY_RATE));
	}
	
	private String getUsername(String topicName) {
		return TopicFactory.getProperties().getProperty(this.getUsernamePropertyName(topicName));
	}
	
	private String getPassword(String topicName) { 
		return TopicFactory.getProperties().getProperty(this.getPasswordPropertyName(topicName));
	}
	
	private String getUsernamePropertyName(String topicName) {
		return String.format(TOPIC_USERNAME_NAME_FORMAT, topicName);
	}
	
	private String getPasswordPropertyName(String topicName) {
		return String.format(TOPIC_PASSWORD_NAME_FORMAT, topicName);
	}
	
	public  E getEvent(TextMessage message, Class eventClass) throws JMSException {
		if (message == null) return null;
		String json = message.getText();
		if (json == null || json.trim().equals("")) return null;
		try {
			return gson.fromJson(json, eventClass);
		} catch (Exception e) {
			log.error(String.format("%s: can not parse event", json));
			try {
				message.acknowledge();
			} catch (JMSException e1) {
				log.error("Can not ACK message");
			}
			return null;
		}
	}
	
	public TextMessage buildMessage(Session session, Object payload) {
		String json = gson.toJson(payload);
		if(session == null) {
			log.error(String.format("Unable to create message in null session: %s", json));
			return null;
		}
		try {
			return session.createTextMessage(json);
		} catch (JMSException e) {
			log.error(String.format("Unable to create message: %s", json));
		}
		
		return null;
	}
	
	public  MessageListener buildMessageListener(final EventHandler handler) {
		return new FFmqMessageListener(this, handler);
	}

	@Override
	public void onException(JMSException exception) {
		log.warn(exception.getMessage(), exception);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy