/* * * Copyright (C) 2012-2014 R T Huitema. All Rights Reserved. * Web: www.42.co.nz * Email: robert@42.co.nz * Author: R T Huitema * * This file is part of the signalk-server-java project * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * 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 nz.co.fortytwo.signalk.server; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.broker.BrokerPlugin; import org.apache.activemq.broker.BrokerService; import org.apache.activemq.broker.TransportConnector; import org.apache.activemq.broker.jmx.ManagementContext; import org.apache.activemq.broker.region.policy.IndividualDeadLetterStrategy; import org.apache.activemq.broker.region.policy.OldestMessageEvictionStrategy; import org.apache.activemq.broker.region.policy.PolicyEntry; import org.apache.activemq.broker.region.policy.PolicyMap; import org.apache.activemq.broker.region.policy.PrefetchRatePendingMessageLimitStrategy; import org.apache.activemq.camel.component.ActiveMQComponent; import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQTopic; import org.apache.activemq.pool.PooledConnectionFactory; import org.apache.activemq.usage.MemoryUsage; import org.apache.activemq.usage.SystemUsage; import org.apache.camel.component.jms.JmsConfiguration; import nz.co.fortytwo.signalk.util.ConfigConstants; import nz.co.fortytwo.signalk.util.Util; public class ActiveMqBrokerFactory { public static BrokerService newInstance() throws Exception { final BrokerService broker = new BrokerService(); broker.setUseShutdownHook(false); broker.setDeleteAllMessagesOnStartup(true); // vm connector TransportConnector connector = new TransportConnector(); connector.setUri(new URI("tcp://localhost:61616")); broker.addConnector(connector); broker.addConnector("ws://localhost:61614"); TransportConnector stomp = new TransportConnector(); stomp.setUri(new URI("stomp+nio://0.0.0.0:"+Util.getConfigPropertyInt(ConfigConstants.STOMP_PORT)+"?transport.hbGracePeriodMultiplier=1.5")); broker.addConnector(stomp); TransportConnector mqtt = new TransportConnector(); mqtt.setUri(new URI("mqtt+nio://0.0.0.0:"+Util.getConfigPropertyInt(ConfigConstants.MQTT_PORT))); broker.addConnector(mqtt); List<BrokerPlugin> plugins = new ArrayList<BrokerPlugin>(); BrokerPlugin[] pluginArray = broker.getPlugins(); if(pluginArray!=null){ plugins.addAll(Arrays.asList(pluginArray)); } plugins.add(new ActiveMqSubscriptionPlugin()); broker.setPlugins(plugins.toArray(new BrokerPlugin[0])); broker.setPersistent(false); configureBroker(broker); //"activemq:topic:ActiveMQ.Advisory.Connection?mapJmsMessage=false" final ActiveMQTopic topic = new ActiveMQTopic("ActiveMQ.Advisory.Connection"); broker.setDestinations(new ActiveMQDestination[] { topic }); final ManagementContext managementContext = new ManagementContext(); managementContext.setCreateConnector(true); broker.setManagementContext(managementContext); return broker; } private static void configureBroker(BrokerService broker) { SystemUsage usage = new SystemUsage(); MemoryUsage mem = new MemoryUsage(); mem.setLimit(16*1024*1024); usage.setMemoryUsage(mem); broker.setSystemUsage(usage); //DLQ strategy PolicyMap map = new PolicyMap(); map.put(new ActiveMQQueue(">"), queuePolicy(">")); map.put(new ActiveMQTopic(">"), topicPolicy(">")); PolicyEntry qEntry = new PolicyEntry(); qEntry.setQueue("signalk.>"); IndividualDeadLetterStrategy strategy = new IndividualDeadLetterStrategy(); strategy.setQueuePrefix("DLQ."); strategy.setUseQueueForQueueMessages(true); strategy.setProcessExpired(false); strategy.setProcessNonPersistent(true); qEntry.setDeadLetterStrategy(strategy); PrefetchRatePendingMessageLimitStrategy preFetchRate = new PrefetchRatePendingMessageLimitStrategy(); preFetchRate.setMultiplier(2.0); qEntry.setPendingMessageLimitStrategy(preFetchRate); qEntry.setMessageEvictionStrategy(new OldestMessageEvictionStrategy()); map.put(new ActiveMQQueue("signalk.>"), qEntry); broker.setDestinationPolicy(map); } private static PolicyEntry topicPolicy(String name) { PolicyEntry rc = new PolicyEntry(); rc.setTopic(name); rc.setProducerFlowControl(false); return rc; } private static PolicyEntry queuePolicy(String name) { PolicyEntry rc = new PolicyEntry(); rc.setQueue(name); rc.setProducerFlowControl(false); return rc; } public static ActiveMQComponent newAMQInstance(){ ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(); connectionFactory.setBrokerURL("vm:localhost"); // use a pooled connection factory between the module and the queue PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(connectionFactory); // how many connections should there be in the session pool? pooledConnectionFactory.setMaxConnections(100); pooledConnectionFactory.setMaximumActiveSessionPerConnection(100); pooledConnectionFactory.setCreateConnectionOnStartup(true); pooledConnectionFactory.setBlockIfSessionPoolIsFull(false); JmsConfiguration jmsConfiguration = new JmsConfiguration(pooledConnectionFactory); jmsConfiguration.setDeliveryPersistent(false); jmsConfiguration.setTimeToLive(1000*10); ActiveMQComponent activeMQComponent = ActiveMQComponent.activeMQComponent("vm:localhost"); return activeMQComponent; } }