Posts tagged Java
Extending Spring-Data to select a database index with Jedis pools
Jan 16th
We came up with a not so un-common use-case of wanting to setup a Jedis connection pool that would automatically select a given database index on each connection. A colleague and I were about to patch the Spring-Data source code (we are already running a patched version), but instead found a very elegant solution by digging in a bit more:
The problem
The spring-data org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionFactory class offers no way to configure it to use a specific database. It defaults to database index 0 (in other words, does nothing on a new connection – so Redis automatically works on index 0).
Given that we will be running automated integration tests on a single Redis server instance, and that those tests will flush the database on each run (i.e.: select 2; flushdb), we needed an easy way to get a new connection factory instance that would first select the configured database index when a connection is created.
Without that database index selection, any integration tests running concurrently would flush or interfere with the data of the other running tests.
The solution
We simply extended the org.springframework.data.keyvalue.redis.connection.jedis.JedisConnectionFactory class and overrode the fetchJedisConnector() protected method:
public class MyCustomJedisConnectionPoolFactory extends JedisConnectionFactory {
private static final int DEFAULT_REDIS_DATABASE_INDEX = 0;
private int databaseIndex = 0;
@Override
protected Jedis fetchJedisConnector() {
Jedis jedis = super.fetchJedisConnector();
if (this.databaseIndex != DEFAULT_REDIS_DATABASE_INDEX) {
jedis.select(this.databaseIndex);
}
return jedis;
}
public void setDatabaseIndex(int databaseIndex) {
this.databaseIndex = databaseIndex;
}
}
The if statement isn’t strictly necessary in the fetchJedisConnector() method, but given that most of the time we will be using the default database, it seemed like it was worth it.
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
Arrays, what’s their point. Dito.
Dec 26th
When I first saw the post on Reddit, I found the reaction harsh (I still think the original poster meant “why use arrays instead of lists”).
As with Erlang, in Java arrays get in the way of readability. I understand arrays and the different usages, but I still prefer a List which is inifinitely more usable.
New project – TumblrJ
Dec 19th
Didn’t find much in the Java space for Tumblr, and I’m looking for a project, so I just got started. First check-in was done tonight:
http://code.google.com/p/tumblrj/
Not much to look at right now, but it will come for sure.
(New development is a bit slow because I just switched to Mac and the key mappings don’t match with the windows world, so I’m having to relearn a bit)
Hibernate session load vs. get gotcha
Aug 21st
The Hibernate documentation (3.2) for the session.get() and session.load() methods state:
load Returns: the persistent instance or proxy
get Returns: a persistent instance or nul
Notice “or proxy” in the load documentation. This last part took me an hour to figure out while debugging an application. In my case, for whatever reason (which I haven’t figured out), the load method was returning a proxy instead of an full instance, resulting in a state exception (closed session). For some unknown reason, this was only happening while running inside the web container and access the method through a transactional service. Test cases ran fine.
So changing my dao method from:
return (User) getSession().load(User.class, id)
to
return (User) getSession().get(User.class, id);
fixed everything.
Jackrabbit first steps – Getting the bunny hop to work
Aug 12th
I just got hired by a company that’s into content. Specifically, they’re building a product/platform on top of JSR-170. Should be pretty exciting to learn the new domain …
While I wait to start, I’m getting ready by reading up and trying out a few things so I can jump in right away.
Initial setup wasn’t as easy as I’d like … what can I say, I’m lazy and I like nicely packaged downloads. Jackrabbit doesn’t offer that except through maven, and I’m still not on board with maven, so I had to download the 56 dependencies manually (brand new home computer being used for the first time in dev – so I have none of the usual suspects which a dev machine would have; lucene, commons-x, …).
(Interestingly, this is the first project I see which uses the sl4j library. I’ve always been lazy and stuck to log4j cause it “just works”, so never bothered. This might be a good occasion to indirectly see it at work.)
Seems, up to now (yes, by now, I’ve done more than just the first hop), that this is a great abstraction for any content platform … wish I’d known before. A failed project in my current company was greatly due to a data model deemed complicated by the PHP guys … (yes, ellipsis denotes an unfinished or unexpressed thought or opinion)