/* * Copyright 2014, The Sporting Exchange Limited * * Licensed 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 com.betfair.cougar.transport.activemq; import com.betfair.cougar.core.api.ev.ExecutionObserver; import com.betfair.cougar.transport.activemq.monitoring.ManagedActiveMQConnection; import com.betfair.cougar.transport.api.protocol.events.EventServiceBindingDescriptor; import com.betfair.cougar.transport.jms.JmsEventTransportImpl; import com.betfair.cougar.util.jmx.JMXControl; import org.apache.activemq.ActiveMQConnection; import org.apache.activemq.ActiveMQSession; import org.apache.activemq.ActiveMQSslConnectionFactory; import org.springframework.beans.factory.annotation.Required; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; /** * This class implements an ActiveMQ JMS based transport implementation. The implementation * contains a set of defaults for a Sonic transport that are overrideable through spring * config if you'd like to do something different */ public class ActiveMQEventTransportImpl extends JmsEventTransportImpl { //Connection arguments, spring injected private String destinationUrl; // ssl settings private String trustStorePath; private String trustStoreType; private String trustStorePassword; //Sonic properties private boolean loadBalancing = true; //Sonic uses this to determine if the url list should be traversed sequentially private boolean sequential = true; private boolean durableMessageOrder = true; private boolean faultTolerant = true; private int faultTolerantReconnectTimeoutSeconds = 30; private int socketConnectTimeoutSeconds = 10; private int initialConnectTimeoutInSeconds = 10; private int reconnectTimeoutInMinutes = 10; private int monitorIntervalInSeconds = 20; private int pingIntervalInSeconds = 20; //Other spring properties private ActiveMQSubscriptionEventListener activeMQSubscriptionEventListener; // monitoring bits private ManagedActiveMQConnection managedSonicConnection = new ManagedActiveMQConnection(); public ActiveMQEventTransportImpl() throws JMSException { this(new ActiveMQSslConnectionFactory()); } public ActiveMQEventTransportImpl(ConnectionFactory connectionFactory) { super(connectionFactory); } @Override protected int defaultAcknowledgementMode() { return ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE; } @Override protected void initConnectionFactory(javax.jms.ConnectionFactory connectionFactory) { ActiveMQSslConnectionFactory activeMQConnectionFactory = (ActiveMQSslConnectionFactory) connectionFactory;//NOSONAR // TODO: Setup // activeMQConnectionFactory.setConnectionURLs(destinationUrl); // activeMQConnectionFactory.setLoadBalancing(loadBalancing); // activeMQConnectionFactory.setSequential(sequential); // activeMQConnectionFactory.setDurableMessageOrder(durableMessageOrder); // activeMQConnectionFactory.setFaultTolerant(faultTolerant); // activeMQConnectionFactory.setFaultTolerantReconnectTimeout(faultTolerantReconnectTimeoutSeconds); // activeMQConnectionFactory.setSocketConnectTimeout(socketConnectTimeoutSeconds * 1000); // activeMQConnectionFactory.setInitialConnectTimeout(initialConnectTimeoutInSeconds); // activeMQConnectionFactory.setReconnectTimeout(reconnectTimeoutInMinutes); // activeMQConnectionFactory.setMonitorInterval(monitorIntervalInSeconds); // activeMQConnectionFactory.setPingInterval(pingIntervalInSeconds); } protected void connectionCreated(Connection c) { managedSonicConnection.setConnection((ActiveMQConnection)c); if (activeMQSubscriptionEventListener != null) {//NOSONAR // ((ActiveMQConnection)c).addTransportListener(activeMQSubscriptionEventListener); } } @Override protected void connectionClosed(Connection c) { managedSonicConnection.setConnection(null); } public String getDestinationUrl() { return destinationUrl; } @Required public void setDestinationUrl(String destinationUrl) { this.destinationUrl = destinationUrl; } @Override protected void subscriptionAdded(ExecutionObserver observer) { if (activeMQSubscriptionEventListener != null) { activeMQSubscriptionEventListener.addObserver(observer); } } protected void registerMBeans(JMXControl jmxControl, EventServiceBindingDescriptor eventServiceBindingDescriptor, String transportIdentifierSuffix) { jmxControl.registerMBean("CoUGAR.activemq.transport:type=connection,serviceName="+eventServiceBindingDescriptor.getServiceName()+",serviceVersion="+eventServiceBindingDescriptor.getServiceVersion()+transportIdentifierSuffix, managedSonicConnection); } @Override protected String getTransportShortName() { return "activemq"; } //-------------------------- Sonic Overridable properties ----------------/ public boolean isLoadBalancing() { return loadBalancing; } public void setLoadBalancing(boolean loadBalancing) { this.loadBalancing = loadBalancing; } public boolean isSequential() { return sequential; } /** * Sonic Sequential connection set searching: * If true, starts attempting to connect to the first broker in the list; * if false, starts attempting to connect to a random element in the list. * After that, tries to connect to each broker in sequence until a * successful connect occurs, or the list is exhausted. * * @param sequential - if true, start with the first broker in the list, if false choose one randomly */ public void setSequential(boolean sequential) { this.sequential = sequential; } public boolean isDurableMessageOrder() { return durableMessageOrder; } /** * Enable or disable preservation of message order for reconnecting durable suscribers * * @param durableMessageOrder, if true, reconnecting durable subscribers will preserve message order */ public void setDurableMessageOrder(boolean durableMessageOrder) { this.durableMessageOrder = durableMessageOrder; } public boolean isFaultTolerant() { return faultTolerant; } /** * Enables fault tolerant connection creation. * * @param faultTolerant */ public void setFaultTolerant(boolean faultTolerant) { this.faultTolerant = faultTolerant; } public int getFaultTolerantReconnectTimeoutSeconds() { return faultTolerantReconnectTimeoutSeconds; } /** * Indicates how long (in seconds) the client will try to establish a connection, * only applicable to fault tolerant connections * * @param faultTolerantReconnectTimeoutSeconds * */ public void setFaultTolerantReconnectTimeoutSeconds(int faultTolerantReconnectTimeoutSeconds) { this.faultTolerantReconnectTimeoutSeconds = faultTolerantReconnectTimeoutSeconds; } public int getSocketConnectTimeoutSeconds() { return socketConnectTimeoutSeconds; } /** * Sets a timeout for establishing a connection to the broker. A value of zero indicates an infinite timeout * * @param socketConnectTimeoutSeconds - the socket connection timeout in seconds to use */ public void setSocketConnectTimeoutSeconds(int socketConnectTimeoutSeconds) { this.socketConnectTimeoutSeconds = socketConnectTimeoutSeconds; } public int getInitialConnectTimeoutInSeconds() { return initialConnectTimeoutInSeconds; } /** * Sets the initial connection timeout for fault tolerant connections. Default is set to 30s * A value of zero indicates an indefinite timeout, and -1 indicates that client runtime will * attempt each URL (in your list) one at a time until a connection has been made. * * @param initialConnectTimeoutInSeconds - timeout for fault tolerant connection establishment */ public void setInitialConnectTimeoutInSeconds(int initialConnectTimeoutInSeconds) { this.initialConnectTimeoutInSeconds = initialConnectTimeoutInSeconds; } public int getReconnectTimeoutInMinutes() { return reconnectTimeoutInMinutes; } /** * Sets how long a persistent client will attempt to reconnect in minutes. * If offline, persistent client sends are stored in the local client. * * @param reconnectTimeoutInMinutes */ public void setReconnectTimeoutInMinutes(int reconnectTimeoutInMinutes) { this.reconnectTimeoutInMinutes = reconnectTimeoutInMinutes; } public int getMonitorIntervalInSeconds() { return monitorIntervalInSeconds; } /** * Sets the admin flow control monitoring interval. A value of zero indicates that no monitoring will occur * * @param monitorIntervalInSeconds */ public void setMonitorIntervalInSeconds(int monitorIntervalInSeconds) { this.monitorIntervalInSeconds = monitorIntervalInSeconds; } public int getPingIntervalInSeconds() { return pingIntervalInSeconds; } /** * Sets the interval between pings. A value of zero will disable the ping * * @param pingIntervalInSeconds */ public void setPingIntervalInSeconds(int pingIntervalInSeconds) { this.pingIntervalInSeconds = pingIntervalInSeconds; } /** * Sets the setSonicSubscriptionEventListener * * @param activeMQSubscriptionEventListener */ public void setActiveMQSubscriptionEventListener(ActiveMQSubscriptionEventListener activeMQSubscriptionEventListener) { activeMQSubscriptionEventListener.setEventTransport(this); this.activeMQSubscriptionEventListener = activeMQSubscriptionEventListener; } public void setTrustStorePath(String trustStorePath) { this.trustStorePath = trustStorePath; } public void setTrustStoreType(String trustStoreType) { this.trustStoreType = trustStoreType; } public void setTrustStorePassword(String trustStorePassword) { this.trustStorePassword = trustStorePassword; } }