According to the latest StackOverflow survey, Javascript is the top-ranked technology in terms of overall usage. Unsurprisingly, it's also top of the list for occupations, and with the advent of Node.js, has become increasingly in-demand.  

In this post, we'll be exploring the similarities of applications built in Node and JAVA. Rather than going into the specifics of each one, we'll focus on wrapping up the main components to get an app up and running. Ready to get our hands dirty? Let's go!

Getting Started

Before starting with Node.js, it's recommended that you have some basic familiarity with Javascript. However, if you're beginning to get accustomed to programming, don't give up! There are tons of tutorials like this one to help familiarize you with the language, as well as infinite ways to practice. All you need is a text editor and a browser to get started!

If you'd like to try the examples presented here by yourself, you can:

 Hands On

Dependency Management

NPM

More than a build tool, the Node Package Manager (NPM) - which comes as a bonus when we install Node.js - centralizes open-source libraries and is also useful for multiple purposes such as initializing an app from scratch with "npm init", installing dependencies, packaging the app, running it, testing, and more. You can learn more about NPM in more detail here.

The default file for assembling the project specs is the package.json, which can be as simple as the one below:

{
"name": "node-rest-ws",
"main": "server.js",
"dependencies": {
"express": "latest",
"body-parser": "~1.8.1",
"mongoose": "latest"
}
}

The "main" defines the JS file that initializes the application, similarly to a Main class in a JAVA project (any class containing the void main(String[]) method), and there's no standard name for it.

Once we run "npm install" after defining our application dependencies, a folder named "node_modules" is created on the project root folder, which is equivalent to the list of jars that are necessary for a JAVA app to compile.

If we add more dependencies after the first install, it won't create any  problems. We can simply specify what we want to install in order to be more precise (e.g. "npm install node-restful"), or simply trigger "npm install" again. 

Maven

As you might already know, Maven is the most popular build tool for managing JAVA project dependencies. There are a few others available as well, that are less common, such as the excellent Gradle.

Maven's central point is the pom.xml, which is commonly, if not always, saved on the project root folder as the package.json is for Node.

Below is the one used on our sample project:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.avenue.blog</groupId>
<artifactId>java-rest-ws</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>java-rest-ws</name>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
</dependencies>
</project>

 Database Config

No hurdles here, with these lines in our main server.js file, we have MongoDB all set:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/cms');

On the JAVA app the configuration is also pretty simple since we are using Spring Data MongoDB, so all we have to do is to define the following on the application.properties:

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=cms

 Backend Development

See how the CRUD managed via RESTful services is structured on the Node application to the left? Not too differently from what we have on the JAVA correspondent to the right. 

node_app.png java_app.png

 See the equivalents?

 Model

'use strict';
var mongoose = require('mongoose');

var ProductSchema = new mongoose.Schema({
name: String,
price: Number
});

module.exports = mongoose.model('Products', ProductSchema);
package com.avenue.blog.cms.model;

//..imports

@Document
public class Product {

@Id
private String id;
private String name;
private Double price;

//..getters and setters
}

Controller

'use strict';
var mongoose = require('mongoose'),
Product = mongoose.model('Products');

exports.list_all = function(req, res) {
Product.find({}, function(err, product) {
if (err)
res.send(err);
res.json(product);
});
};

exports.save = function(req, res) {
var product = new Product(req.body);
product.save(function(err, product) {
if (err)
res.send(err);
res.json(product);
});
};

exports.read = function(req, res) {
Product.findById(req.params.id, function(err, product) {
if (err)
res.send(err);
res.json(product);
});
};

exports.delete = function(req, res) {
Product.remove({
_id: req.params.id
}, function(err, product) {
if (err)
res.send(err);
res.json({ message: 'Product deleted' });
});
};
package com.avenue.blog.cms.service;

//..imports

@Service
public class ProductService {

@Autowired
private ProductRepository repository;

@Transactional(readOnly=true)
public List<Product> listAll() {
return repository.findAll();
}

@Transactional(readOnly = true)
public Product read(String id) {
return repository.findOne(id);
}

@Transactional
public Product create(Product p) {
if (p != null)
return repository.insert(p);
return null;
}

@Transactional
public Product update(Product p) {
if (p != null &&
repository.exists(p.getId()))

return repository.save(p);
return null;
}

@Transactional
public void delete(String id) {
if (repository.exists(id))
repository.delete(id);
}
}

 REST endpoints

'use strict';
module.exports = function(app) {
var product = require('../service/productService');

app.route('/api/products')
.get(product.list_all)
.post(product.save)
.put(product.save);

app.route('/api/products/:id')
.get(product.read)
.delete(product.delete);
};
package com.avenue.blog.cms.api;

//..imports

@RestController
@RequestMapping("/api/products")
public class ProductResource {

@Autowired
private ProductService service;

@RequestMapping(method = RequestMethod.GET)
public List<Product> listAll() {
return service.listAll();
}

@RequestMapping(method = RequestMethod.GET, value = "/{id}")
public Product read(@PathVariable String id) {
return service.read(id);
}

@RequestMapping(method = RequestMethod.POST)
public Product create(@RequestBody Product p) {
return service.create(p);
}

@RequestMapping(method = RequestMethod.PUT)
public Product update(@RequestBody Product p) {
return service.update(p);
}

@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
public void delete(@PathVariable String id) {
service.delete(id);
}
}

Putting it All Together

On our Node app we are linking the pieces starting from the server.js, defining the models, database, routes (which plug the controllers), and finally the application port, whereas on our JAVA app this is in place with annotations (remember that we're getting the advantage of all that Spring Boot can offer along with the most recent JDK). Before long, though, it's likely that we'll have similar support in Node.js. Check it out - attempts are already underway: take a look here.

Final server.js file:

var express = require('express'),
bodyParser = require('body-parser'),
Product = require('./src/model/productModel'),
Category = require('./src/model/categoryModel');

var app = express();
app.use(bodyParser.json());

var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/cms');

var productRoutes = require('./src/routes/productRoutes');
productRoutes(app);

var categoryRoutes = require('./src/routes/categoryRoutes');
categoryRoutes(app);

app.listen(3000);
console.log('Server running at port 3000');

 Running the Application

Now it's time to see if our efforts had any results. To test the exposed services, I've used Postman. See below.

Creating a product

node_example_post.png

Updating a category

node_example_put.png

Retrieving all products

node_example_get.png

As we can see above, some of the services exposed by the Node application were successfully executed. To call the API's exposed by the JAVA app and test, all we need to do is change the port to 3001 since the same URI names were chosen and it's already up. 

Frontend Development

Angular.js would be my natural choice for developing the UI for consuming both backend applications' REST APIs. Why? Simply because it is Javascript based and is a big success!

Working with JAVA, many of us have always had contact at one time or another with pure JSP/Servlet, Struts, JSF, or Spring MVC applications. These are still used for some newly created projects, and we'll always face them when working with legacy systems. But the world is changing. With the emphasis on Mobile First development, and the growing concern of building responsive apps that run well, multi-platform, JS-based client side apps are the way to go. 

Some of the many frameworks for building Javascript fullstack applications with Node and Angular include:

Conclusion

Node.js really worth trying, even taking into consideration that's not recommended yet for any kind of app. Note: I say yet because it's evolving at such a fast pace that this argument will be defeated any day now. It's efficient for both fast development, and enabling lightweight apps to run with minimal effort. 

Recommended references besides the official website:

The code mentioned in this article is available for download here, have fun!

What are your thoughts regarding Node? Are you already using it on your projects? Please share with us! =)


Author

Milena Santos

Software Engineer at Avenue Code