DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Data Engineering
  3. Databases
  4. MongoDB and Java

MongoDB and Java

Giorgio Sironi user avatar by
Giorgio Sironi
·
Apr. 30, 12 · Interview
Like (1)
Save
Tweet
Share
35.72K Views

Join the DZone community and get the full member experience.

Join For Free
So you want a NoSQL database, and you have chosen MongoDB. Here is a tutorial on how easy MongoDB can be integrated with Java application and some advice on how to isolate your code from the database as much as possible, for encapsulation purposes.

The API

Many aspects of the MongoDB API are not language specific, like the terms and the formats used for communicating with the persistence mechanism (JSON on the client side and BSON for transport and storage).

You can download a single JAR containing the Java bindings of the API, where the com.mongodb package is the main one that you will import classes from.

The setup is pretty simple: a hierarchy of Mongo (connection), DB and Collection objects, each contained into the other. A Collection loosely correspond to a relational table, but since embedded objects are allowed and arbitrary fields can be added to contained objects, it is more similar to an Aggregate class.

Mongo mongo = new Mongo("127.0.0.1");
DB db = mongo.getDB("test_database");
DBCollection collection = db.getCollection("test");

You can insert in a collection instances of DBObject (usually BasicDBObject), which can be created from a JSON string or programmatically:

DBObject article = new BasicDBObject();
article.put("title", "MongoDB and Java");
collection.insert(article);

Querying also with a DBObject that resemble in structure what you want (only valorize fields if you want to make a match on their value):

DBObject query = new BasicDBObject();
DBObject result = collection.findOne(query);

Special string keys (starting with $) allow for matching not based on equality. Check out MongoDB's Java tutorial for more about queries and indexes.

Isolation

I don't want com.mongodb.DBObject hanging around in arbitrary places in my applications, which in most places has nothing to do with MongoDB and persistence: this persistence agnosticism tells me to try hiding the database from most of my code.

Even if DBObjects and their implementations are the format that must be used to talk with MongoDB, we are not forced to use them inside the application. We can:

  • Convert JSON objects (instances of a class of yours) to DBObjects for storage.
  • Convert DBObjects returned after querying into JSON objects.

JSON objects can be just JSON strings (a rare choice), a JSON manipulable representation (there are plenty of Java libraries for that), or domain objects. The com.mongodb.util.JSON class has two static methods for going back and forth between a String and DBObject, so everything that you can serialize to a JSON string can be used inside the application. The impedance mismatch between object aggregates and MongoDB's model is minimal.

The natural choice for hiding the translation between domain and Mongo-based format is the Repository pattern, which in fact models a Collection of objects. If the conversion is really complex, a Data Mapper like Morphia can be used internally.

But for starting out, producing a JSON string representation of an object manually may be enough. In any case, the persistence strategy decision is hidden inside the particular Repository implementation, so you'll be able to change it later if the code grows.

Writing tests

There is no Fake equivalent for the Mongo connection object: Sqlite can be used as a fast, in-memory, non-transactional test database for relational solutions, but there aren't alternate implementations of MongoDB yet.

So when tests involve persistence, we must use the real one. The mongod service must be started separately (usually as a Unix daemon or a Windows service). On Linux platforms, check that the configuration in mongodb.conf defines a dbpath option as a folder where the mongodb user can write.

At the end of each test, resetting the database is necessary. In end to end tests, and in the tests of the Repository itself, you will then use a brand new instance of the database. There is no schema to create, nor constraints to be satisfied: it's very simple as even if the database do not exist MongoDB will create an emtpy one for you.
Here is an example, the test for my Repository containing JSONObject instances (representing User's here):

package it.polimi.cubrikusers.persistence;

import static org.junit.Assert.*;

import java.net.UnknownHostException;

import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;

public class MongoUserRepositoryTest {
    DB db;
    MongoUserRepository repository;
    
    @Before
    public void setUp() throws UnknownHostException, MongoException
    {
        Mongo connection = new Mongo("127.0.0.1");
        db = connection.getDB("test");
        DBCollection collection = db.getCollection("users");
        repository = new MongoUserRepository(collection);
    }
    @Test
    public void testCanStoreAUserJSONObjectAndRetrieveIt() {
        JSONObject user = new JSONObject()
            .put("id", 1)
            .put("membership", new JSONObject()
                .put("username", "giorgio"));
        repository.add(user);
        JSONObject retrieved = repository.findBy("id", 1);
        assertEquals(user.getJSONObject("membership").getString("username"),
                     retrieved.getJSONObject("membership").getString("username"));
    }
    
    public void tearDown() {
        db.dropDatabase();
    }

}

Here's the Repository implementation, if you're curious:

package it.polimi.cubrikusers.persistence;

import org.json.JSONObject;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;

public class MongoUserRepository {

    private DBCollection collection;

    public MongoUserRepository(DBCollection collection) {
        this.collection = collection;
    }
    
    public void add(JSONObject user) {
        DBObject object = (DBObject) JSON.parse(user.toString());
        collection.insert(object);
    }

    public JSONObject findBy(String field, Object value) {
        BasicDBObject query = new BasicDBObject();
        query.put(field, value);
        DBObject found = collection.findOne(query);
        return new JSONObject(JSON.serialize(found));
    }
}

I am using the JSONObject and related classes from json.org.

Of course in most of the unit tests, you will be able to stub the Repository, and to avoid touching MongoDB altogether for greater speed and simplicity.

MongoDB Java (programming language) Database Object (computer science) Relational database JSON Testing

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • What Are the Different Types of API Testing?
  • A Gentle Introduction to Kubernetes
  • How To Best Use Java Records as DTOs in Spring Boot 3
  • 19 Most Common OpenSSL Commands for 2023

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: