(Part 1)
This post is the first part of a series on building a mobile backend with MongoDB, Express, and Node; otherwise known as a MEN Stack.
Articles in the Series
- How to Build a Mobile Backend with MongoDB and Express (this article)
- How to Connect Your iOS or Android App to a Localhost Server
- How to Build a RESTful iOS Employee Manager App (coming soon)
- How to Build a RESTful Android Employee Manager App (coming soon)
TLDR
- You will build a custom Mobile BaaS using a MEN Stack.
- MEN Stack means MongoDB, Express, and Node. Yes, it sounds bad.
- I won’t cover User Authentication in this article.
- You will have RESTful API Routes for GET, POST, PUT, and DELETE.
Sections
Introduction
Today I’m going to show you how to build a mobile backend for your iOS or Android mobile application. Having a backend server is incredibly common for enterprise-level mobile applications. There’s also an added benefit being able to build your own mobile backend – That is you don’t have to pay the price of using a service like Firebase.
There are a lot of different Technology stacks I can be used to build out a mobile backend. Today, I’m going to show you how to build out a mobile backend using MongoDB, Express, and Node. What does that spell? It’s called a MEN Stack. That’s right, MEN.
What Will Not Be Covered
What we will not have in this build is User Authentication. User Authentication is an important security measure in any mobile backend, however, it deserves more discussion time in a different article for a different day. Authentication can be done by so many different methods that it really comes down to whether you want your users to use a secret API key, log in with credentials and generate an API key from a web interface, provide a public facing API, or just build a private API for internal use with a business. Okay, so let’s get started.
Setting Up Your Development Environment
- Install Homebrew (Mac only) – http://treehouse.github.io/installation-guides/mac/homebrew.html
-
Install Node and NPM (Windows) – http://treehouse.github.io/installation-guides/windows/node-windows.html
-
Install Node and NPM (Mac) – http://treehouse.github.io/installation-guides/mac/node-mac.html
-
Install MongoDB (Windows) – http://treehouse.github.io/installation-guides/windows/mongo-windows.html
-
Install MongoDB (Mac) – http://treehouse.github.io/installation-guides/mac/mongo-mac.html
-
Download a free app called Postman – https://www.getpostman.com
The 10,000 Foot Perspective
The way this works is pretty simple when you look at it from a 10,000-foot perspective. The details can get messy when looking at it up close. So, let’s look at the big picture! Your iOS or Android app will create a web request using a native class object. That request starts running asynchronously so that the user interface doesn’t lock up while it is waiting to hear back from your server. Your server is going to get that request just like it would get a request to load a web page if you were to go to your server in a web browser. The MEN stack server will understand what your mobile app is looking to do by the type of request your app is making. The way your app will communicate with your server is through an HTTP protocol, and the verbs it will use are GET – to retrieve data, PUT – to update existing data, POST – to add new data, and DELETE – to remove existing data. Each of these requests will be handled by Express in your MEN server through routes that you will set up. Think of routes as various doorways to your database. The server will handle the request and then send a response back to your app. The response will either contain data that is relevant to your app and which can be displayed to the user in the user interface, or it will contain an error, which should be gracefully handled by your application.
Building The Server
- First, let’s create a project folder for our server to call home. I am going to place it on my desktop. I am going to call it “men-server-app”.
- Next, I am going to initialize the Node Packaging Manager inside the project folder. This will build out my package.json file where I can then add dependencies, maintain the app’s version, update the project’s description, and so on. Open up a terminal window, type cd + space and then drag the project folder into the terminal window and hit Return.
Now you should be inside your project’s directory.
Now, let’s initialize npm by typing the following:
$ npm init
This is how I filled my package.json file out…
Now, you should have a simple little package.json file in your project.
- Let’s create the entry point for the server application. We called it app.js. In your terminal window, type…
$ touch app.js
- Let’s install Express. Express is a JavaScript library that is built on top of Node. It simplifies working with Node by providing a cleaner syntax for doing what Node already does. This means, you, the developer, can get into a groove much faster!
$ npm install express --save
This command, once executed, will now include Express as a dependency. If you open up your package.json file, you should see it listed there as a dependency. If you look in your project folder, you should now see a folder called node_modules. If you are using git version control, you will want to add this folder to your gitignore file. Why don’t we do that now!
- Create a gitignore file.
$ touch .gitignore
Make sure you have the period in there. This will make the file hidden.
Pro Tip: To toggle seeing hidden files on your Mac, press Command + Shift + . .
You can open your project directory in your favorite text editor. I will use Atom. To open the directory from Terminal, type …
$ atom .
Add the following to your gitignore file.
### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
Cool, now save it and let’s initialize Git!
- Initialize Git.
$ git init
- Add a Readme file
$ touch Readme.md
The Readme file will be visible if you plan on posting your repository on Bitbucket or Github.
- Install Nodemon. Nodemon simplifies the starting of the server when changes are made.
$ npm install nodemon --save-dev
- Let create a folder to hold our source code and then move the app.js file inside it and update the path to the app.js file inside our package.json file.
$ mkdir src
Move your app.js file inside the new src folder. Your folder structure should look like this…
Now, change the entry for main in your package.json file to reflect the new location for your app.js file.
"main": "./src/app.js",
- Add the following code to your app.js file to get your server ready to start.
'use strict';
// Import Statements
var express = require('express');
// Configure Express
var app = express();
// Configure Server to Listen on Port 3000
app.listen(3000, function(){
console.log("The server is running on port 3000");
});
- In Terminal, start the server by typing …
$ nodemon
You should see
Open up your web browser and set your address to
http://localhost:3000
You should get
That means you have no routes setup, but you do have a working server! To kill your server, just hit control + c.
Milestone 1
Let’s take a step back and understand what we just did. We created a server that runs only on your computer and is accessible using your web browser by navigating to localhost at port 3000. You can only access this server from your computer. You cannot access it from an external device, such as your iPhone or Android smartphone without using a tunneling service. More on that later.
We also restructured the project folder where you got a chance to edit the package.json file to let npm know where the entry point is for your web server. Now, let’s work on Routes.
API Routes
What we will do is create a sub-directory in our source folder for our API routes. This practice keeps our source code modular. Each folder that you create and add code to must be included in your app.js file using a require statement. It’s pretty simple, but if you have never seen it before, at least now you will understand what’s going on.
It’s important to understand the basics of the HTTP Protocol, the method of communication between our server and your mobile app. There are four main HTTP request types, or verbs as some like to call them, that you should be familiar with and will be discussed here. They are GET, POST, PUT, and DELETE.
GET
When you go to Google.com to search for the latest Medium post on mobile development, when you type in https://www.google.com and hit enter, your web browser sends a message to Google’s server in the form of a GET request. Google’s server sends a response with the requested information. The information to render Google’s webpage is in that response.
POST
POST requests are used to add information to the database that is associated with a web server. Think about it, when you make a post on Facebook, you are adding content to the user feed and your personal profile wall. POST requests are where you send information to the server, usually in the form of JSON or XML. The server processes the POST request and then sends a response back to you saying everything looked good or letting you know that there was a problem. It’s a lot like a bank transaction when you deposit a check. You give the teller a check. The teller, in this case, is the server. The teller looks at the check, checks for authenticity, inputs the information into the computer system to verify that the sending account has sufficient funds and then initiates the transfer. When all is said and done, the teller then looks at you and says, “You are all set and your funds will be available immediately.” You will do the same thing here.
PUT
A PUT request is nearly identical to a POST request, but it’s used for updating information that already exists in your database. Each entry in a database has an ID field. You will send the updated information to the server in JSON format with the ID of the entry you wish to update. The server will verify that an entry exists with that ID and then make the updates. Once the updated information has been added, your server will send a response on whether it was successful.
DELETE
DELETE is delete. If I have to explain this one, then I will probably just go and get a cup of coffee and give up on the world. The only thing worth mentioning here is that you will be sending to the server an ID value so that the server knows what entry to delete. It will respond with the information that was deleted.
Setting Up the API Package
Step 1, add an API subdirectory in your source folder.
$ mkdir api
Now, add an index.js file to your new API package. Your folder structure should look something like this:
Add the following code to your index.js file inside your API package.
'use strict';
// Import Express
var express = require('express');
// Create a Router to prevent namespace collisions
var router = express.Router();
/*
API ROUTES
*/
// TODO: GET Route - fetches ALL employees
// TODO: GET Route - fetches employee by ID
// TODO: POST Route - adds an employee to the database
// TODO: PUT Route - updates an existing employee in the database
// TODO: DELETE Route - removes an existing employee out of the database
// Export the router so it can be accessed in app.js
// Think of this like the Video Out cable on the back of your DVD player.
// When you require the Router in the app.js file, that would be you plugging
// in the cable into this socket.
module.exports = router;
I commented the code so it is self-explanatory. Take a minute to read it and understand what is going on.
Next, let’s connect this file to the app.js file by requiring the Router object.
Now, let’s get the GET route up and running with a “Hello World” statement to ensure all is working as expected.
Simple GET Route Test
Add the following code under the TODO for the GET route.
router.get('/employees', function(request, response){
response.send('Hello World');
});
Now, save the file, stop the server if it’s running (Control + c), and start it back up by typing nodemon and hitting Return.
Go to your web browser and go to the following URL:
http://localhost:3000/api/employees
You should now see:
Body-Parser
There’s a cool library that we need to add to our project called Body-Parser. It allows us to parse through JSON data that our app sends to the server. Since the app will send employee information in the form of JSON, it kind of makes sense why we will need it. Go to Terminal and add this line of code and hit Return:
$ npm install body-parser --save -E
Now, let’s go back to the app.js file and include Body-Parser with a require statement. Add var parser = require(‘body-parser’); after the router import statement. Your code should look like this:
Let’s configure Express to use the Body-Parser library. Add the app.use(parser.json()); right before the use statement for the API.
Great! Now, we are all set to parse json POST and PUT requests. Now, we need to create our data model.
Adding a Database With a Data Model
The data model is a blueprint for objects to be saved, or persisted, to our database. Don’t worry, your eyes are not playing tricks on you. We don’t have a functioning database yet. Don’t worry, it’s pretty darn simple to implement.
Steps
- In your src directory, add a sub-directory called models.
-
Add a file inside the models directory called employee.js. This file is where your model will live.
- Add a file inside the src directory called database.js. This is the file that Express uses to connect to your database. I hope that’s clear. Your project structure should now look like this:
MongoDB and Mongoose
Now is the time to get MongoDB and Mongoose up and running. I know, your head is probably spinning a bit at this point. Let’s do a quick recap. First, you got your server to run and handle a simple web request, in the form of a GET to a single route. You then set your project up to be able to parse incoming JSON data. Now, it is time for the database. MongoDB handles maintaining your database. Mongoose is like the Bouncer at the door to your database that makes sure only the expected data is coming into your database with the proper format. It brings a schema to your NoSQL (Not Only Structured Query Language) database. And yes, that IS what NoSQL stands for.
Steps
- Run the Mongo Daemon in the terminal. You need Mongo up and running to install Mongoose. In a new terminal tab (just hit Command + T), CD into your project folder and enter the following and hit Return:
$ mongod
You should get some cool console output to the effect of something ending in this:
- In your original terminal tab, let’s stop your server if it is currently running and restart it.
$ nodemon
- Now, let’s install Mongoose. In a new tab in Terminal, add the following and hit Return:
$ npm install --save -E mongoose
- Add the following to your database.js file:
'use strict';
var mongoose = require('mongoose');
const host = 'localhost';
const projectName = 'men-server-app';
mongoose.connect('mongodb://' + host + '/' + projectName, function(err) {
if(err) {
console.log('Failed connecting to MongoDB.');
}
else {
console.log('Successfully connected to MongoDB!');
}
});
- Add a require statement for the database file in your app.js file. It should look like the following:
- Now, let’s make sure you can connect to your database. Stop your server and restart it. Now, you should see the following in your console output:
- Let’s build out the schema for your Employees table, or in the MongoDB world, it’s called a Collection. Add the following code to your Employee.js file.
'use strict';
var mongoose = require('mongoose');
// Create the Schema
var employeeSchema = new mongoose.Schema({
firstName: String,
lastName: String,
phone: String,
email: String
});
// Build the Model
var model = mongoose.model('Employee', employeeSchema);
// Export the Model
module.exports = model;
Finally, add a reference to your model in your index.js file.
GET – fetching all employees
Now, in your index.js file, modify the GET route to query the database and send a response. Edit the GET route to look like this:
// NOTE: GET Route - fetches ALL employees
router.get('/employees', function(request, response){
// query directly from the model Todo object.
Employee.find({}, function(err, employees){
if(err) {
return response.status(500).json({message: err.message});
}
response.json({employees: employees});
});
});
This way, if there is an issue, your server will respond with a Status Code of 500 – internal server error; otherwise, the response will serve the requested information in JSON format. Let’s save the file and restart our server.
Now, go to your web browser and reload http://localhost:3000/api/employees. You should get something like this:
- Create a POST route by adding the following code to your index.js file:
// NOTE: POST Route - adds an employee to the database
router.post('/employees', function(request, response){
var employee = request.body;
Employee.create(employee, function(err, employee){
if(err) {
return response.status(500).json({err: err.message});
}
response.json({'employee': employee, message: 'Employee Created'});
})
});
Postman
Now comes the time to use Postman. Launch Postman, enter the URL from above, set the request type to GET, and hit Send.
You should see in the response the following:
POST – Adding a New Employee
Your route will be:
http://localhost:3000/employees
Set your request type to POST.
Set the body of the request to the following:
{
"firstName": "Elon",
"lastName": "Musk",
"phone": "(555)867-5309",
"email": "elonmusk@spacex.com"
}
Make sure your MIME Type is set to JSON.
Then hit send!
You should see the following in the response.
If you refresh your web browser, you should also see:
Congratulations! You have just created a backend that saves and retrieves data using the HTTP protocol!
PUT – Updating an Existing Employee
Now, let’s add the following code to your index.js file for handling a PUT request.
// NOTE: PUT Route - updates an existing employee in the database
router.put('/employees/:id', function(request, response){
// Get the ID of the Todo to update
var id = request.params.id;
var employee = request.body;
if(employee && employee._id != id) {
return response.status(500).json({err: "Did not find a match to the ID provided."});
}
Employee.findByIdAndUpdate(id, employee, {new: true}, function(err, employee){
// the {new: true} is an option. With this set to true, the data
// returned in the response body contains the updated data, rather
// than the old data.
if(err) {
return response.status(500).json({err: err.message});
}
response.json({'employee': employee, message: 'Employee Updated'});
});
});
Save the file and restart your server.
Now, let’s craft a PUT request in Postman. You need the employee ID of the person you wish to update. Look at your browser and get the employee id for the entry we just added.
Your request URL should look something like this:
http://localhost:3000/api/employees/5a948cc39c4b557382d791e0
For the update, we are going to change Elon’s email address to Tesla. Yeah, we got it wrong.
{
"_id": "5a948cc39c4b557382d791e0",
"firstName": "Elon",
"lastName": "Musk",
"phone": "(555)867-5309",
"email": "elonmusk@tesla.com"
}
Go ahead and hit Send!
Updated!
DELETE – Removing an Employee
Now, let’s add the following code to your index.js file to handle DELETE requests. Just like PUT requests, we need the ID of the employee you wish to terminate.
// NOTE: DELETE Route - removes an existing employee out of the database
router.delete('/employees/:id', function(request, response){
// Get the ID of the Todo to update
var id = request.params.id;
var employee = request.body;
if(employee && employee._id != id) {
return response.status(500).json({err: "Did not find a match to the ID provided."});
}
Employee.findByIdAndRemove(id, function(err, employee){
if(err) {
return response.status(500).json({err: err.message});
}
response.json({'employee': employee, message: 'Employee Deleted'});
});
});
Save the file and restart your server.
Now, let’s craft your DELETE request in Postman. Your Route should look like this:
http://localhost:3000/api/employees/5a948cc39c4b557382d791e0
Your Request body should look like this:
{
"_id": "5a948cc39c4b557382d791e0"
}
Hit Send!
Now, refresh your browser window and see if you have any employees in your database. It should look like this:
Next, we must connect our server to a Tunneling Service to forward our server’s responses to and send requests from external devices.
Next Article: How to Connect Your iOS or Android App to a Localhost Server
[…] How to Build a Mobile Backend with MongoDB and Express […]