JVM threads getting locked when using IPv6 methods with IPv4 address

Do you have threads locked in a state that looks like this?

java.lang.Thread.State: WAITING
at java.lang.Object.wait(Native Method)
- waiting on <26457185> (a java.util.HashMap)
at java.lang.Object.wait(Object.java:485)
at java.net.InetAddress.checkLookupTable(InetAddress.java:1267)

This usually happens when the applications trying to use IPv6, when the environment is really only configured for IPv4.

The solution is to configure the the Java processes to prefer the IPv4 stack. The default is to prefer the IPv6 stack. This can be done by specifying a JVM argument to prefer IPv4.

-Djava.net.preferIPv4Stack=true

A detailed explanation of this problem can be found here: http://wiki.zimbra.com/wiki/Configuring_for_IPv4

How to enable JMX on Tomcat running on EC2 (behind a firewall)

Step 1: Copy catalina-jmx-remote.jar into Tomcat’s lib folder. This jar file is available in the extras folder of Tomcat’s binary distribution.

Step 2: Modify Tomcat’s server.xml by adding a new Listener entry.

<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" 
rmiRegistryPortPlatform="9090" rmiServerPortPlatform="9091"/>

Step 3: Open both of these ports in your firewall. Ports 9090 and 9091 and just examples, you can choose to use any port numbers you like.

Step 4: Add the following options to Tomcat startup script.

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Djava.rmi.server.hostname=public-ip (or public dns)

All done! Restart Tomcat and connect to it using jconsole or visualvm from a remote system.

MongoDB: How to aggregate the lengths of nested arrays

Lets say you have collection (mycollection) that has an embedded object (tags) which happens to be an array.

> db.mycollection.find()
{ "_id" : ObjectId("515c8ab8e4b06d8f844ac0bd"), "tags" : [ "a", "b", "c" ] }
{ "_id" : ObjectId("515c8ab8e4b06d8f844ac0bc"), "tags" : [ "b", "c" ] }

You have to count the total number of tags across all documents in the collection. Here are a couple of ways to accomplish this.

1. MapReduce

db.mycollection.mapReduce(
    function() { emit('tags', { count: this.tags.length }); },
    function(key, values) {
        var result = { count: 0 };
        values.forEach(function(value) {
            result.count += value.count;
        });
        return result;
    },
    { out: { inline: 1 }}
);

First argument above is the map function. It scans the entire collection and emits the number of replies in each document under a constant key.

Second argument above is the reduce function. It will examine the emitted values consolidate (literally reduce) the result.

2. Aggregation Framework

db.mycollection.aggregate(
    { $project: { tags: 1 }},
    { $unwind: "$tags" },
    { $group: { _id: "result", count: { $sum: 1 }}}
);

First argument specifies that the field of interest is tags.

Second argument unwinds the array so that its elements can be iterated over.

Third argument does the total under a bucket called “result”