A CRUD App with MongoDB Java - Java Source Code
Main.java
package com.javaquizplayer.examples.mongocrudapp; import org.bson.Document; import java.util.Scanner; import java.util.List; import java.util.Random; import java.util.logging.*; /** * Application's starter class. * Displays a main menu, accepts user options and inputs, performs * database operations and returns a result. * See MongoOps.java, which has functions for database operations. */ public class Main { private static Scanner scanner; private static MongoOps mongoOps; // Flag specifies if the app has an error and is set to false. private static boolean runapp = true; // A set of Name and City field values from which the program // selects a value randomly, when the user doesn't enter one. private static final String [] NAMES = { "Arian", "Kwame", "Jack", "Lin", "Marie" }; private static final String [] CITIES = { "Avalon", "Shangri-La", "Troy", "Utopia", "Xanadu" }; /* * Main method, runs the program. */ public static void main(String [] args) { // Initial setup: // Sets the logger. // Loads application properties. // Instantiate the MongoOps object to get the database // connection and then perform database operations. // Initialize the scanner object. System.out.println("\nStarting the app... "); setupLogger(); try { AppProperties props = new AppProperties(); mongoOps = new MongoOps(props); } catch(RuntimeException e) { System.out.println(e.getMessage()); runapp = false; } scanner = new Scanner(System.in); // Indefinite while loop displays the menu, accepts user's choice, // performs a CRUD action and prints an output. Exit the loop // (and the program) when the user chooses so. COMMAND_LOOP: while (runapp) { showMenu(); System.out.print("Enter Menu Option [ <ENTER> to exit ]: "); String option = scanner.nextLine().trim(); if (option.isEmpty() || option.equals("0")) { // User has entered a "0" -or- pressed <ENTER> // Exit the while-loop and the program. break COMMAND_LOOP; } System.out.println(""); try { processMenuOptions(option); } catch(RuntimeException e) { System.out.println(e.getMessage()); runapp = false; } System.out.print("\nPress <ENTER> to Continue..."); scanner.nextLine(); } // Close the resources and exit the program. closeResources(); System.out.println("CRUD Company App - Closed."); } /* * Routine to turn off the MongoDB Java driver logging output on the * console. This log output interferes with the program functionality. * Only, the severe errors are logged. */ private static void setupLogger() { Logger logger = Logger.getLogger("org.mongodb.driver"); logger.setLevel(Level.SEVERE); } /* * Displays the menu and its options. */ private static void showMenu() { System.out.println(""); System.out.println(" x------------------------------x"); System.out.println(" CRUD Company App - Main Menu "); System.out.println(" x------------------------------x"); System.out.println(" 1. Add "); System.out.println(" 2. Update "); System.out.println(" 3. Delete "); System.out.println(" 4. Query All "); System.out.println(" 5. Query by Field "); System.out.println(" 0. Exit "); System.out.println(" x------------------------------x"); System.out.println(""); } /* * Process the user entered menu option. * Calls the appropriate CRUD routine based upon the input option. * Throws a RuntimeException propagated from the doXXX method, if * there is a database error during a write. */ private static void processMenuOptions(String option) { switch(option) { case "1": doAdd(); break; case "2": doUpdate(); break; case "3": doDelete(); break; case "4": doQueryAll(); break; case "5": doQueryByNameAndOrCity(); break; default: System.out.println("Not a valid option!"); } } /* * Routine for the add option. * Accepts a Name and City value, and if not provided generates * random values for them. Calls a database routine to add a * document into the database with the entered values. The newly * added document is returned and printed. * Throws a RuntimeException propagated from the MongoOps.java class * method, if there is a database error during a write. */ private static void doAdd() { System.out.println("[ Add Document, enter Name and City field values ]"); System.out.print("Enter Name [ Defaults to a random Name ]: "); String name = scanner.nextLine().trim(); System.out.print("Enter City [ Defaults to a random City ]: "); String city = scanner.nextLine().trim(); if (name.isEmpty()) { name = NAMES[new Random().nextInt(NAMES.length)]; } if (city.isEmpty()) { city = CITIES[new Random().nextInt(CITIES.length)]; } Document doc = mongoOps.insertDoc(name, city); System.out.println("Document added: " + doc.toJson()); } /* * Routine for the update option. * Accepts a Name to query the document and a City value to be updated. * Calls a database routine to update the document in the database * using the entered values. An update status message is printed. * Throws a RuntimeException propagated from the MongoOps.java class * method, if there is a database error during a write. */ private static void doUpdate() { System.out.println("[ Update a Document, for a matching Name ]"); System.out.print("Enter Name to match: "); String name = scanner.nextLine().trim(); if (! name.isEmpty()) { System.out.print("Enter City to update: "); String city = scanner.nextLine().trim(); if (! city.isEmpty()) { long modifiedCount = mongoOps.updateDoc(name, city); System.out.println("Updated " + modifiedCount + " document(s)"); } else { System.out.println("City value required to update!"); } } else { System.out.println("Name value required to update!"); } } /* * Routine for the delete option. * Accepts a Name to query the document and delete. Calls a database * routine to delete the document in the database using the entered * Name value. A delete status message is printed. * Throws a RuntimeException propagated from the MongoOps.java class * method,if there is a database error during a write. */ private static void doDelete() { System.out.println("[ Delete a Document ]"); System.out.print("Enter Name to delete: "); String name = scanner.nextLine().trim(); if (name.isEmpty()) { System.out.println("Name value required to delete!"); } else { long deletedCount = mongoOps.deleteDoc(name); System.out.println("Deleted " + deletedCount + " document(s)"); } } /* * Routine for the query all option. * Calls a database routine to get all the documents in the database. * The returned documents are printed. */ private static void doQueryAll() { System.out.println("[ Query All Result ]"); List<Document> docs = mongoOps.getAll(); if (docs.isEmpty()) { System.out.println("No documents found!"); } else { docs.forEach(doc -> System.out.println(doc.toJson())); } } /* * Routine for the query by name and/or city option. * Accepts the Name and/or City values to query by. * - When no values are entered for both fields, no query is made * - When both values are entered, the database is queried with * Name -and- City. * - When only one field value is entered, the database is queried * with that field only. * Calls a database routine to select the documents in the database * based upon the field values entered. The returned documens are * printed. */ private static void doQueryByNameAndOrCity() { System.out.println("[ Query by Name and/or City ]"); System.out.print("Enter Name: "); String name = scanner.nextLine().trim(); System.out.print("Enter City: "); String city = scanner.nextLine().trim(); if (name.isEmpty() && city.isEmpty()) { System.out.println("Cannot query without one of the values!"); } else { List<Document> docs = mongoOps.queryByField(name, city); if (docs.isEmpty()) { System.out.println("No documents found!"); } else { System.out.println("Document(s) found:"); docs.forEach(doc -> System.out.println(doc.toJson())); } } } /* * Close to release resources for the Scanner and the MongoDB connection. */ private static void closeResources() { if (scanner != null) { scanner.close(); } if (mongoOps != null) { mongoOps.close(); } } }
MongoOps.java
package com.javaquizplayer.examples.mongocrudapp; import java.util.List; import java.util.ArrayList; import org.bson.Document; import org.bson.conversions.Bson; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.result.*; import com.mongodb.client.model.Updates; import com.mongodb.client.model.Filters; import com.mongodb.MongoException; /** * Class has MongoDB database connection creation and CRUD operation methods. * See Main.java, where this class is accessed. */ public class MongoOps { private MongoClient mongoClient; private MongoCollection<Document> collection; /* * Constructor with the input application properties to build the connection URL. * Gets connection to the database and creates an instance of the collection. * Throws a RuntimeException if the conection URL, the database namespace or * the collection name are not valid. */ public MongoOps(AppProperties props) { try { final String URL = "mongodb://" + props.getPropertyValue(AppProperties.HOST_K) + ":" + props.getPropertyValue(AppProperties.PORT_K) + "/"; mongoClient = MongoClients.create(URL); collection = mongoClient .getDatabase("crud") .getCollection("test"); } catch(RuntimeException e) { System.out.println("Database connection format, database or collection name error."); throw new RuntimeException(e); } System.out.println("Connected to MongoDB database."); } /* * Routine to close the database connection. */ public void close() { if (mongoClient != null) { mongoClient.close(); } System.out.println("\nMongoDB database connection closed."); } /* * Returns the document inserted in the database collection using * the input field values. The inserted document, in addition, * has the _id field, which was generated by the driver software * as part of the insert operation. * Throws a RuntimeException if there is a database error during the write. */ public Document insertDoc(String name, String city) { Document doc = new Document("name", name).append("city", city); try { collection.insertOne(doc); } catch(MongoException e) { System.out.println("Database insert error."); throw new RuntimeException(e.getMessage()); } return doc; } /* * Returns the number of documents updated in the database collection * using the input field values. Updates the first matching document. * Throws a RuntimeException if there is a database error during the write. */ public long updateDoc(String name, String city) { Bson filter = Filters.eq("name", name); Bson update = Updates.set("city", city); UpdateResult result = null; try { result = collection.updateOne(filter, update); } catch(MongoException e) { System.out.println("Database update error."); throw new RuntimeException(e.getMessage()); } return result.getModifiedCount(); } /* * Returns the number of documents deleted from the database collection * using the input Name field value. Deletes the first matching document. * Throws a RuntimeException if there is a database error during the write. */ public long deleteDoc(String name) { Bson filter = new Document().append("name", name); DeleteResult result = null; try { result = collection.deleteOne(filter); } catch(MongoException e) { System.out.println("Database delete error."); throw new RuntimeException(e.getMessage()); } return result.getDeletedCount(); } /* * Returns all documents from the database collection. */ public List<Document> getAll() { return collection.find().into(new ArrayList<Document>()); } /* * Returns the documents from the database collection based upon * the input field values. * - When both values are entered, the database is queried with * Name -and- City. * - When only one field value is entered, the database is queried * with -that- field only. */ public List<Document> queryByField(String name, String city) { Bson filter = null; if (name.isEmpty()) { // Query by City filter = Filters.eq("city", city); } else if (city.isEmpty()) { // Query by Name filter = Filters.eq("name", name); } else { // Query with Name and City filter = Filters.and(Filters.eq("name", name), Filters.eq("city", city)); } return collection.find(filter).into(new ArrayList<Document>()); } }
AppProperties.java
package com.javaquizplayer.examples.mongocrudapp; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.Files; import java.util.Properties; /* * Class provides read access to the MongoDB connection * information (host and port) stored in a properties file. */ public class AppProperties { // Represents persistent set of properties, // (key/value pairs that can retrieved). private Properties properties; // Property keys public static final String HOST_K = "host"; public static final String PORT_K = "port"; // Location where the file is stored. private static final String BASE_DIRECTORY = System.getProperty("user.dir"); // The properties file name. private static final String APP_PROPS_FILE = "application_properties.properties"; /* * Constructs an instance. * Loads the properties from the file. * Throws an runtime exception in case of a problem with the properties file. */ public AppProperties() { try { properties = loadPropertiesFromFile(); } catch(IOException e) { System.out.println("Error reading the properties file: " + APP_PROPS_FILE); throw new RuntimeException(e.toString()); } } /* * Returns the value of the specified property. */ public String getPropertyValue(String propertyName) { return properties.getProperty(propertyName); } /* * Loads and returns the properties from the file. * Throws IOException if there is a problem with the file. */ private Properties loadPropertiesFromFile() throws IOException { Path path = Paths.get(BASE_DIRECTORY, APP_PROPS_FILE); InputStream fis = Files.newInputStream(path); Properties loadedProperties = new Properties(); loadedProperties.load(fis); fis.close(); return loadedProperties; } }
Return to top
This page uses Java code formatting from http://hilite.me/.