[JAVA-357] Endless NullPointerException at com.mongodb.OutMessage.reset Created: 22/May/11  Updated: 25/Jun/13  Resolved: 24/Oct/11

Status: Closed
Project: Java Driver
Component/s: Cluster Management
Affects Version/s: 2.5.3
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Gregory DH Lee Assignee: Scott Hernandez (Inactive)
Resolution: Cannot Reproduce Votes: 1
Labels: redeploy
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Window 7 SP1 32bit
Glassfish 3.1 + Spring 3.0.5 (Can be ignore it)



 Description   

I had redeployed spring web application onto glassfish 3.1, I got endless NullPointerException at at com.mongodb.OutMessage.reset(OutMessage.java:73).
(you can also refer this page - http://groups.google.com/group/mongodb-user/browse_thread/thread/a51a1f5f3850ba46/74272391a3ee37ab?hl=en&lnk=gst&q=endless#74272391a3ee37ab )

Here is server log:
[#|2011-05-12T01:05:37.251+0900|SEVERE|glassfish3.1|com.mongodb.ReplicaSetS tatus|_ThreadID=27;_ThreadName=Thread-1;|unexpected
error getting config from node: localhost:10001
java.lang.NullPointerException
at com.mongodb.OutMessage.reset(OutMessage.java:73)
at com.mongodb.OutMessage.<init>(OutMessage.java:51)
at com.mongodb.OutMessage.query(OutMessage.java:38)
at com.mongodb.DBPort.findOne(DBPort.java:142)
at com.mongodb.ReplicaSetStatus$Node.update(ReplicaSetStatus.java:156)
at com.mongodb.ReplicaSetStatus.updateAll(ReplicaSetStatus.java:277)
at com.mongodb.ReplicaSetStatus$Updater.run(ReplicaSetStatus.java:238)

#]

How to reproduce this issue:
1. deploy application to glassfish
2. redeploy same application to glassfish (or, drop the application from the glassfish)
3. you can get that exception endless

I inject MongoDB Connecter as spring bean.
<bean id="MongoConnector" class="jwdm.core.bean.MongoConnector"
p:host="localhost" p:port="10001">

Here is full code of MongoConnector (as Spring bean):
public class MongoConnector {
private Mongo mongoDB;
private String host;
private String port;
// Return an instance of Mongo
public Mongo getMongo() {
logger.debug("Retrieving MongoDB");
if (mongoDB == null) {
try

{ List<ServerAddress> addrs = new ArrayList<ServerAddress>(); addrs.add(new ServerAddress(host, Integer.parseInt(port))); mongoDB = new Mongo(addrs); }

catch (UnknownHostException e)

{ logger.error(e.toString()); } catch (MongoException e) { logger.error(e.toString()); }


}
return mongoDB;
}
// Retrieve a db
public DB getDB(String dbname)

{ logger.debug("Retrieving db: " + dbname); return getMongo().getDB(dbname); }


// Retrieve a collection
public DBCollection getCollection(String dbname, String collection)

{ logger.debug("Retrieving collection: " + collection); return getDB(dbname).getCollection(collection); }


... getter , setter ...
}
</bean>

Before using spring bean style, I was using static factory style without spring.
But it produces same exception.

Here is static factory style code:

public class MongoDBFactory {

protected static Logger logger = LoggerFactory.getLogger(MongoDBFactory.class);

private static Mongo mongoDB;

// Make sure no one can instantiate our factory
private MongoDBFactory() {
}

// Return an instance of Mongo
public static Mongo getMongo() {
logger.debug("Retrieving MongoDB");
if (mongoDB == null) {
try

{ List<ServerAddress> addrs = new ArrayList<ServerAddress>(); addrs.add(new ServerAddress("localhost", 10001)); //addrs.add(new ServerAddress("leewin12.cafe24.com", 10001)); mongoDB = new Mongo(addrs); }

catch (UnknownHostException e)

{ logger.error(e.toString()); } catch (MongoException e) { logger.error(e.toString()); }

}

return mongoDB;
}

// Retrieve a db
public static DB getDB(String dbname)

{ logger.debug("Retrieving db: " + dbname); return getMongo().getDB(dbname); }

// Retrieve a collection
public static DBCollection getCollection(String dbname, String collection)

{ logger.debug("Retrieving collection: " + collection); return getDB(dbname).getCollection(collection); }

}

Thank you for your helps,
Greg



 Comments   
Comment by Michael D. Norman [ 21/Jun/11 ]

I was wrong. I have not been able to reproduce this with 2.6.3. The version on the server wasn't updated properly so we were seeing the problem only with an older driver.

Comment by Remon van Vliet [ 17/Jun/11 ]

We have the same problem. Occurs when redeploying a war without restarting the app server in (at least) GlassFish 3, Tomcat 6 and Jetty 7 which makes me think it's not related to specific app servers.

I'm relatively sure it's a problem unique to dependency injection frameworks (we use Guice, but Spring should be implementing these things in a similar way). When you redeploy a WAR file in most app servers it will recreate the war scoped classloader which may somehow interfere with using a singleton Mongo instance in your DI framework. If it indeed is a DI specific problem then technically you can't call this is a java driver bug in the mongo driver since the code is correct. I have been unable to find a decent workaround in Guice that still allows the Mongo instance to be a singleton though. Will update once I do.

UPDATE 1 : Cannot reproduce the issue with simple redeploying, nor with redeploying using a DI framework to provide the Mongo instance. Not sure if it's relevant but on the systems where I can reproduce it it's always thrown on com.mongodb.DBCursor.hasNext()
UPDATE 2 : Confirmed that having live threads running that have a DI injected reference to Mongo will reset static fields upon redeploy. Happens for other things too so doesn't seem mongo driver specific. Pretty sure you'll be stuck with app-side workaround.

Comment by Scott Hernandez (Inactive) [ 15/Jun/11 ]

Can you provide a simple war/web-app to reproduce this on tomcat 6? It does seem like a strange class-loader issue.

Comment by Michael D. Norman [ 15/Jun/11 ]

I am running into the same exception, but I'm using Tomcat 6. It looks like JAVA-227 attempted to solve a similar problem with NPEs on this line, but that code never made it into a release. I'm using the latest as of today, 2.6.3, and it appears to still have the same code in OutMessage. I'd be surprised if the code change made a difference, but then again, the code in OutMessage doesn't actually look wrong, so something odd is going on in the classloaders.

Comment by Gregory DH Lee [ 22/May/11 ]

Oops, I omitted mongodb info, I'm using single mongodb without any replicaset

Generated at Thu Feb 08 08:52:05 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.