Archive for December, 2010
Joda Time if you appreciate a good quality of life
Dec 7th
I’ve had it! When I go out clubbing and hit on women, one of the things that invariably comes up in the conversation is which date library I code to when using my made skillz in Java.
Word to the wise: Do NOT answer that you use the Java Date or Calendar classes. Too many times have women straight out told me that I was a looser with no self respect because of that answer.
I’m now at a point where I use exclusively Joda Time. And you should to. No bullshit formatting, date math and time zones. Add to that great documentation.
HornetQ dynamic destination creation and references through Spring
Dec 7th
As per my last post, we are currently looking into migrating from ActiveMQ towards HornetQ. One of the missing features which we used and depend on are dynamic queues and topics. Our main goal is to avoid touching any java code and depend solely on Spring configuration changes.
Non dynamic destination configuration through spring
<bean name="myDestination" class="org.hornetq.api.jms.HornetQJMSClient" factory-method="createQueue"> <constructor-arg index="0" value="ExampleQueue"/> </bean> <bean name="jmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="defaultDestination" ref="myDestination"/> </bean>
In the above example, the queue TestQueue will already need to be defined on your HornetQ server.
Dynamic creation through a Spring FactoryBean implementation
Using a simple FactoryBean implementation and the HornetQ management api, we can achieve dynamic destination creation.
<bean name="myDestination" class="com.mikem.HornetQueueFactory"> <property name="name" value="TestQueue"/> </bean> <bean name="jmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="defaultDestination" ref="myDestination"/> </bean>
Notice the different class used to define the myDestination bean. This is a simple implementation of a Spring FactoryBean.
public class HornetQueueFactory implements FactoryBean {
private String name;
@Override
public Class getObjectType() {
return Queue.class;
}
@Override
public boolean isSingleton() {
return true;
}
@SuppressWarnings("unchecked")
@Override
public Queue getObject() throws Exception {
boolean created = false;
ObjectName on = ObjectNameBuilder.DEFAULT.getJMSServerObjectName();
JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1097/jmxrmi"), new HashMap());
MBeanServerConnection mbsc = connector.getMBeanServerConnection();
JMSServerControl serverControl = (JMSServerControl)MBeanServerInvocationHandler.newProxyInstance(mbsc, on, JMSServerControl.class, false);
String[] queueNames = serverControl.getQueueNames();
if (!ArrayUtils.contains(queueNames, this.name)){
created = serverControl.createQueue(name);
System.out.println("Created new queue with name " + name);
} else {
created = true;
}
if (!created) {
throw new RuntimeException("Queue isn't created. Not sure why.");
}
return HornetQJMSClient.createQueue(name);
}
@Required
public void setName(String name) {
this.name = name;
}}
Notes:
- JMX/RMI needs to be configured and on for this to work
- Obviously, this is a naive implementation only used to see if it could be done.
- Once it’s all cleaned up, I will probably use a single factory for both Queues and Topics
ActiveMQ – not what it used to be?
Dec 7th
I’ve posted a quick update to this here.
When I started this job a couple years ago, we were mildly invested in ActiveMQ with a single queue for some mission critical work. Since I’d had good experience with ActiveMQ 4.x in previous jobs, I didn’t hesitate to push forward and suggest we invest more in ActiveMQ and architect solutions around it’s usage. After all, I had experienced flawless performance and up time with 4.x.
Forward 2 years: We now have 30 or so topics and queues with moderate usage and it’s incapable of staying up more than a few minutes when configured as a network of brokers.
We’ve gone so far as paying the big bucks to get consulting from the folks at FuseSource. Unfortunately, the suggestions and help have been … uh … expensive with no results at all.
The setup
The setup is relatively straightforward:
- 3 brokers in different cities in different countries which need to work as a network of brokers.
- Latency can be high (80ms)
- Java clients using the client libraries over the tcp protocol
- C++ clients using the ActiveCPP library
- A few dozen topics and queues
- No big messages (5MB max with the average being closer to a few hundred k)
- Moderate traffic (a few hundred thousand messages per day overall)
Everything performs well enough in a single broker setup, but that’s un-acceptable for us.
What was done
Pretty much everything :)
Our expert had us upgrade to the latest version (5.4.2) with horrendous results; the KahaDB would continuously corrupt. Let me say this about trying to fix a basic problem with a minor upgrade: It’s bullshit. If version 5.4.1 can’t do something as straightforward as we’re trying to do, some suggestion about upgrading a point release isn’t going to do anything.(edit: The language was harsh. As it turns out, the minor upgrade was to adress another issue and not the network of brokers issue). And don’t be mistaken; our usage is basic and reasonable and definitely falls into the advertised set of features touted by ActiveMQ.
What’s next
We’re throwing all our weight behind JBoss HornetQ right now. The team is pretty psyched because they’re all fed up and disillusioned with the ActiveMQ product. Obviously, the migration path will not be easy, but at least we should no more be prisoner to a buggy product. (edit: Again, harsh: I’d say ‘prisoner to a product that doesn’t work in our configuration’)