[JAVA-213] Make the Mongo class proxy safe Created: 08/Nov/10  Updated: 05/Dec/17  Resolved: 28/Apr/12

Status: Closed
Project: Java Driver
Component/s: API, Codecs
Affects Version/s: 2.3
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: ZedroS Assignee: Unassigned
Resolution: Done Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Currently, when calling new Mongo() the following happen:

  • default hard coded settings are used
  • the driver then tries to establish a connection

When using reflection tools like cglib to build a proxy around a class, a common behaviour is to call the default constructor to wrap around it (through a subclass).

This doesn't work with the Mongo class (or could in a misleading way if there's a local mongo server listening on the defaults port, which could change, esp in production).

IMHO, the best approach here would be to have an explicit call to mongo to open the connection. However, at "worst", a way to setup the default settings could be enough, esp. if these settings can be done through java. One could also consider not providing a default constructor (since the current one isn't clean), but it would mean more work when proxying around.

thanks in advance



 Comments   
Comment by Jeffrey Yemin [ 28/Apr/12 ]

Since zero-arg Mongo constructor no longer tries to connect to a local instance, closing this. Please comment if you disagree.

Comment by Jeffrey Yemin [ 02/Feb/12 ]

@Kevin, the current version of the driver behaves as you indicate. Without mongod running, this code:

    Mongo mongo = new Mongo();
    DB db = mongo.getDB("db1");
    DBCollection collection = db.getCollection("cool");
 
    collection.drop();

doesn't throw any exception until the call to drop().

Can this be closed, or is there more to it?

Comment by Kevin Thomas [ 23/Mar/11 ]

I agree that it should be possible to construct a Mongo object without establishing a connection to the database. In its current form, the Mongo object causes application initialisation to fail in Spring applications that inject Mongo objects into other objects. This makes it very difficult to make Spring applications resistant to Mongo failures, and forces such applications to be started AFTER the Mongo database, thus reducing operational flexibility.

Comment by Remon van Vliet [ 27/Jan/11 ]

The issue is related to the Proxy design pattern I think, not http ones. Am I misunderstanding your comment?

Comment by Kornelis Sietsma [ 27/Jan/11 ]

Note that this causes an extremely painful problem on Ubuntu systems (at least) - if you have "useSystemProxies" set in /usr/sun-java-6/net.properties, it sets Java to use the system-wide proxy properties by default. However, it doesn't seem to set "nonProxyHosts" properly!
The net result is a basic Mongo connection to localhost will try to go through the system http proxy, and (in our environment at least) hang indefinitely.
This isn't really the Mongo driver's fault, but it's very hard to diagnose, and quite counterintuitive that a simple Mongo connect would go looking for a http proxy at all!

Comment by Remon van Vliet [ 21/Dec/10 ]

I agree that a DB connection should be established when an operation is performed that requires one. For us having the Mongo(..) constructors throwing exceptions means our dependency injection framework (Google Guice) in our case fails to inject Mongo or related classes but cannot (or will not) display the actual cause of the failed injection. This complicates resolving configuration or code issues quite a bit.

Comment by ZedroS [ 21/Dec/10 ]

I can't do

ProxiedMongo(){
super( new MongoURI( config.getURI() ) );
}

For the lazy proxy matter, it simply breaks its intend: the db connection would happen on each lazy proxy creation, not when actually used.

On the bigger picture it would mean also I have to inject this ProxiedMongo everywhere, considering that:

  • there's code I don't have an hand on (morphia for example)
  • there's code already written => would have to be changed
  • one should never forget to use it: if someone somewhere use or inject just mongo it would break it down (using the wrong settings)
Comment by Eliot Horowitz (Inactive) [ 09/Nov/10 ]

Why can't you do

ProxiedMongo(){
super( new MongoURI( config.getURI() ) );
}

Comment by ZedroS [ 09/Nov/10 ]

hi Eliot

Thanks for your answer

The issue is linked with proxying, in my case in the context of Wicket but it could happen to anyone using proxy.

To create a proxy, the approach is usually to extend the proxied class through a subclass. Then a new instance of the subclass will be created, allowing to intercept each call made to the proxied class (and then do whatever needed).

In the case of the mongo class, having such subclass doesn't work. Indeed, the subclass must call the parent constructor, and goes at the parameter less constructor. For example like this:
ProxiedMongo extends Mongo{

ProxiedMongo(){
super();
}
}

calling super here trigger this default settings connection mechanism, which fails when there's no locally available mongodb instance (in reality, tools like CGLib are used for this subclass creation, which is then done automatically).

What's done next after the proxying is deeply use case specific. In my own use case, it does lazy proxing on injected field: first only an "empty" proxy is done. If and when it's first called, then the real instance of the mongo class will be fetched and used. Used in a web framework, this helps avoiding page getting too big (full of injected members of which most aren't used on every request).

Comment by Eliot Horowitz (Inactive) [ 09/Nov/10 ]

I don't think a config option for overriding localhost makes sense.

Why can't you just put the mongo uri string in a config file and instantiate with that?

Comment by ZedroS [ 09/Nov/10 ]

what would be your preferred option ?

For example, if I was to provide a patch providing a config file for the default settings, would it be ok for you ?

thanks again

Comment by Eliot Horowitz (Inactive) [ 08/Nov/10 ]

Overall this is the API most people seem most comfortable with.
Can see over time if that changes

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