Optional URL parameters in angular 6 typescript

My development environment details:

Angular CLI: 6.0.7
Node: 8.11.2
typescript: 2.7.2

I wanted to implement optional URL parameters in angular 6. It means, when the URL params are passed for a angular 6 route, some values in the form should be pre-populated based on the params. When the URL is not coming with any parameters, user can enter any values to the form.(not pre-populated).

There are two ways you can achieve this feature in angular 6:

1. You can define Routes with mandatory parameters
In  app-routing.module.ts

{ path: ‘getModel/:name’, component: TestModelComponent } , 

Here the name parameter has to be passed when called ‘getModel/testname’ otherwise this call will not be succeeded.

2. You can define Routes with optional parameters

Suppose, you want to populate ‘requested by’ field in the form , if the param is passed in the URL. Otherwise it will work as normal. User has to enter the value in the form field.

You don’t have to do anything in the app-routing. Where as little bit of logic change in the component.ts will suffice.

When there is requestedby=testuser in the URL:

http://localhost:4200/getModel/testmodel;requestedby=testuser 

You have to do the following steps in the app.component.ts:

1. Imports

import { ActivatedRoute, Router } from ‘@angular/router’;

2. Add constructor args

constructor(private route: ActivatedRoute, private router: Router)

3. Call the method to handle pre-population of params in ngOnInit() :

ngOnInit() {  prepopulateIfUrlParamsPassed();  }

4. Implement the prepopulateIfUrlParamsPassed() method as follows:

prepopulateIfUrlParamsPassed() {
 this.route.params.subscribe(params => {
  if(params.requestedby){
     this.requestedby = params.requestedby;
  }
 ); 
}

this.requestedby will be assigned / used in the form as model.

<input class="form-control col-sm-10" id="requestedby" name="requestedby"
[(ngModel)]="requestedby">

Now when the URL param ;requestedby=testuser is passed, the value will be automatically assigned in the form field.

Otherwise, it will be empty. User can enter any text in the form field.

Recent times , we develop applications, which are totally separated as Server side applications and client side applications.
Here , Client side application can be anything like android, html app, or any other REST service consumers.

When I was working on one such client side applications, I wanted to test how the application is able to consume a REST service. I want a server side application which simply returns a json response, so that I can test it with my app.

I just want it quickly and i just need it for a test. So I decided to use nodeJs and express js to develop such a REST service almost in 15 minutes of time. 🙂

All I did was described as steps below:

1. Create a folder , enter to that folder then run
npm init
It will ask you a few details such as name , version etc, just follow the flow and enter.

2. It will create packages.json file as follows:
{
"name": "myserver",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "mksiva",
"license": "ISC"
}

3. Now I am going to install two important modules

  1. express js
  2. body-parser

Express JS
Express is a light-weight web application framework to help organize your web application into an MVC architecture on the server side. You can use a variety of choices for your templating language (like EJS, Jade, and Dust.js).

You can then use a database like MongoDB with Mongoose (for modeling) to provide a backend for your Node.js application. Express.js basically helps you manage everything, from routes, to handling requests and views.

Body parser
Body-parser extract the entire body portion of an incoming request stream and exposes it on req.body as something easier to interface with . I hear, yes! you can do it by yourself as well but using body-parser will do what is required and will save your trouble.

I am installing this as we might want to test some POST rest service.

Run the following commands:

1. npm install express --save
2. npm install body-parser --save

This will add express js and body-parser dependencies in packages.json file
"dependencies": {
"body-parser": "^1.17.1",
"express": "^4.15.2"
}

4. Now our application structure is ready, we will develop some small server which returns a json file when we call ‘/api’.
1. Create a file called server.js
//Import require modules
var express = require('express');
var bodyParser = require('body-parser');

// define our app using express
var app = express();

// this will help us to read POST data.
app.use(bodyParser.urlencoded({ extended: true }));

app.use(bodyParser.json());

var port = process.env.PORT || 8080;

// instance of express Router
var router = express.Router();

// test route to make sure , it works.
router.get('/', function(req, res) {
res.json({ message: 'Hello! welcome to our rest api!' });
});

// all our routes will be prefixed with /api
app.use('/api', router);

// state the server
app.listen(port);

console.log('Server listening on port ' + port);

It is done now, run node server.js

It will print “Server listening on port 8080” and it is running now.

If you hit http://localhost:8080/api

You will see:

Thats it. You can test your the simple REST service now.

If you want to know the basics of node.js you can check the following blog: Node js Getting started.

I wanted to create an REST API service application which exposes a few services to create user(sign up) and get user creation result.

I have analyzed and thought of using some latest technologies in the market, so I ended up on Gradle + Spring boot + Swagger2 combination.

Let us see how can we create an app using the above combination.

First, we will quickly see what are those technologies.

Gradle
Gradle is a build automation and dependency management system that builds built upon concepts of apache ant, apache maven and introduces a groovy based domain specific language instead of XML (maven).Gradle

Spring boot
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. Spring Boot

Swagger
Swagger is a powerful open source framework backed by a large ecosystem of tools that helps you design, build, document, and consume your RESTful APIs.Swagger

Spring boot uses tomcat as a web server by default, but you can exclude tomcat and use ‘jetty’ instead of tomcat.

First step:
We have to create a folder(project folder) and run the following command to create gradle related artifacts in the project.

Folder name : springboot-gradle-swagger2-app

cd springboot-gradle-swagger2-app
gradle init --type java-library

Java-library is the project type to create. It creates maven folder structure and other stuff.

You can see the following file structure:

Second Step: (build.gradle)
In this step we update build.gradle file with all the required dependencies for spring boot , swagger2.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.3.RELEASE")
}
}
// Apply the java plugin to add support for Java
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'application'
repositories {
maven { url "http://repo.spring.io/libs-snapshot" }
mavenCentral()
jcenter()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
// The production code uses the SLF4J logging API at compile time
compile ("org.slf4j:slf4j-api:1.7.21")
compile ("org.springframework.boot:spring-boot-starter-web:1.5.3.RELEASE")
compile ("org.springframework.boot:spring-boot-gradle-plugin:1.5.3.RELEASE")
testCompile ("org.springframework.boot:spring-boot-starter-test:1.2.3.RELEASE")
testCompile ("junit:junit:4.12")
compile ("io.springfox:springfox-swagger2:2.4.0")
compile ("io.springfox:springfox-swagger-ui:2.4.0")
}

We will need 2 dependencies for swagger, that are swagger2 and swagger-ui.

Third Step: – Create controller

In this step , we create a controller named ‘SignUpController.java’ to create users , retrieve users by email etc.
This is not calling any real service in fact, it is just a controller to demonstrate the basic rest functionality and swagger ui.

package com.mksiva.controller;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.mksiva.dto.UserDO;
@RestController
@RequestMapping("/api")
public class SignUpController {

@RequestMapping(value = "", method = RequestMethod.GET)
public String status() {
return "MyApp Interface API Service is running!";
}

@RequestMapping(value = "/user/{email}", method = RequestMethod.GET)
@ResponseBody
public String getUserByEmail(@PathVariable("email") String email) {
return email;
}

@RequestMapping(value = "/userCreationResult/{email}", method = RequestMethod.GET)
@ResponseBody
public String userCreationResultByKey(@PathVariable("email") String email) {
return "User [" + email + "] creation is in progress...";
}

@RequestMapping(value = "/user", method = RequestMethod.POST, consumes = {
MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
public String createUser(@RequestBody UserDO aUserDO) {
return aUserDO.getEmail();
}
}

Fourth Step: – Create Spring boot application class

In this step ,we create a java file called “Application.java” , this is the important file, to start spring boot application., this is where all the
application level configuration should go, Like Mapper(json to Object mappers) etc.

package com.mksiva.controller;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {

System.out.println("Let's inspect the beans provided by Spring Boot:");

String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}

Fifth Step: – Swagger config

In this step, we will create “SwaggerConfig.java” to configure swagger and it is target REST ent points mapping using annotations.

package com.mksiva.controller;

import static springfox.documentation.builders.PathSelectors.regex;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.mksiva.controller"))
.paths(regex("/api.*")) // .paths(postPaths()) PathSelectors.ant("/api/*")
.build()
.apiInfo(apiInfo());
}

private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"MyApp REST API",
"To interface with MyApp from any other applications.",
"MyApp API",
"Terms of service",
"",
"",
"API license URL");
return apiInfo;
}
}

Sixth Step: – creating Data Transfer Object
In this step , we will create a entity or data object called ‘UserDO.java”. and it is needed to be passed as a parameter to rest service, so that
the json input format is derived from this class.
package com.mksiva.dto;

import io.swagger.annotations.ApiModelProperty;

public class UserDO {
@ApiModelProperty(required = true)
private String name;

@ApiModelProperty(required = true)
private String email;

@ApiModelProperty(required = true)
private String phone;

private String aboutMe;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public String getAboutMe() {
return aboutMe;
}

public void setAboutMe(String aboutMe) {
this.aboutMe = aboutMe;
}
}

Seventh Step: – Checking the application files:

We should be having the following files in order to start spring boot application.

  1. SignUpController.java
  2. Application.java
  3. SwaggerConfig.java
  4. UserDO.java

The following is the files list:

Eighth Step: – Gradle commands

1. >gradle eclipse – To make the project as a eclipse project
2. >gradle build – To build the project
2. >gradle bootRun – To build the project and start the spring boot application.

We will now start the rest server:

> gradle bootRun

You can see the server starts up:


Now the Spring boot server is started, it is a tomcat server , that runs on port 8080.

You can access application by typing http://localhost:8080/api :
You will see the message “MyApp Interface API Service is running!”.

You can also check all the rest services provided by our application using swagger explorer. It is very useful and you can test the rest api from
there itself, if you want.

Try Swagger API explorer (http://localhost:8080/swagger-ui.html)

From this swagger explorer, you can see the REST API available,

what is the input and what it does and other important details.

That’s it. Have fun.

When you are trying to convert any java object to json, you may run in to this problem.

“com.fasterxml.jackson.core.JsonGenerationException: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)”

This is due to null key in the map of objects (or collection of objects). JsonGenerator cannot serialize the null key into json.

Ignore ‘null’ values in the map:

So we can ignore ‘null’ key and values from the ObjectMapper by using:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);

Now any null value in Map object serialized through this mapper is going to be ignored.

Serialise a map with ‘null’ key:

By default, Jackson doesn’t allow the serialization of a Map with a null key. If you do try to write out such a map, you’ll get the following exception:

com.fasterxml.jackson.core.JsonGenerationException: Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)

you can define a custom, null key serializer and override the default behavior:

class CustomNullKeySerializer extends StdSerializer {
public CustomNullKeySerializer () {
this(null);
} public CustomNullKeySerializer (Class t) {
super(t);
}

@Override
public void serialize(Object nullKey, JsonGenerator jsonGenerator, SerializerProvider unused)
throws IOException, JsonProcessingException {
jsonGenerator.writeFieldName("");
}
}

Now the Map with the null key will work just fine – and the null key will be written as an empty String.

Ignore ‘Null’ fields globally:

You can also set to ignore the null fields globally by

mapper.setSerializationInclusion(Include.NON_NULL);

Now any null field in any class serialized through this mapper is going to be ignored.

I have written a blog on Introduction to Node.js. Please check that link to know some basics.

In this tutorial, We will look in to the following topics:

  • Node.js Dev environment set up
  • Hello World node.js web application, which prints or responds with ‘Hello World’
  • Explanation on the hello.js file

After this tutorial, you should be able to:

  • create a simple web server using node.js , which prints ‘Hello World’.
  • Understand the parts of the hello.js file.

You have to install the node.js in your machine. Please follow the instructions from https://nodejs.org/en/download/ to install node.js.

After installing, run the following command to verify the installation.
node --version

It should print the version of your node.js.

nodeversion

Developing the hello world program in node.js:

Now we are going to develop a small program that will print ‘Hello World from Node!’. Please note this is just a program, NOT a web server.

    1. Create a file called ‘helloWorld.js’, Enter the following line:
      console.log("Hello, World from Node!")
    2. Execute using node helloWorld.js and enter in the node REPL.
    3. You can see the message.

repl_nodejs

Developing a web server using node.js and responding with ‘Hello World from Node.js web server!’:

Now we are going to develop a small web server using node.js. Our server will simply respond  ‘Hello World from Node.js web server!’ when you make a request. The file is called ‘helloServer.js

var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World from Node.js web server!");
response.end();
}).listen(8090);

Node.js uses lots of inbuilt modules to accomplish various tasks for example file access, interacting with operating system services etc.

We have used such a module called ‘http’ to develop a web server which will listen to 8090 port and emits the message ‘Hello World from Node.js web server!’.

It is simple? Let us run and see whether we have developed a web application or not.

Just run ‘node helloServer.js’ and hit enter.
node helloServer.js

servermsg

Now try to browse it from the browser and see what happens! http://localhost:8090/

serverres

So we have developed a small standalone (helloWorld.js) program and a web server(helloServer.js) and successfully executed it.

So What is node js?

Is it a web server? a framework? a language? what is it?

Well, it is not exactly a web server or a language. it is a java script runtime. But you can also develop a web server using node js.

NodeJs is a java script run-time based on chrome’s V8 java script engine.

It is a non blocking input output ( I/O ) model, which uses call backs to handle responses back and forth.

Callback is working on the basis of “Don’t wait for/call me, I will call you when I am done” concept..We will see more to it.

intro

Node Js in short

  • Event driven (uses event loop model)
  • Non Blocking IO
  • Asynchronous
  • Lightweight
  • run-time environment or eco system

It is NOT a new programming language; Java script is used as a programming language to develop node.js applications.

Node.js is used to develop a web server normally, but it could be much more than that.

You can create applications in JavaScript, running locally or remotely and use that with HTML 5 and Canvas interfaces and client side libraries.

It’s ideal for web applications that are frequently accessed but doing simple computational operations.

What is blocking IO or typical synchronous approach of web applications?

Please check the diagram below:blockingio

Blocking  IO model,  the incoming requests to the server are processed one by one or synchronously. It means when the request is completed, the next will be processed so the other incoming requests should wait for their turn.

It is called ‘Blocking IO or synchronous IO’.

Non-Blocking IO or asynchronous IO:

nonblockingio

In non blocking IO or asynchronous IO model, the requests are processed asynchronously. No one is waiting for the others to finish their task. each and every one is served independently.

In node.js the event loop is taking care of processing incoming requests without blocking(asynchronous). Non blocking IO is working based on call back methods, so when the process is completed, the call back will be called saying, it is done. please have your response.

Node.js is async and does not block resources for other requests.

Node.js Architecture and event loop:

Node.js takes a different approach by serving all requests from one single thread. The program code running in this thread is still executed synchronously but every time a system call takes place it will be delegated to the event loop along with a callback function.

The main process will not be put to sleep and will continue serving other requests. As soon as the previous system call is completed, the event loop will execute the callback passed. This callback will usually deal with the result returned and continue the program flow.

Node.js REPL

You can install node.js in your machine and play around with REPL.

Yes what is REPL?  REPL – read eval print loop – a command line interface to play around and do some operations with node.js.

Please check my post on getting started with node.js simple program.

In the command prompt type ‘node’ enter, you can go to REPL:repl_nodejs

 

 

 

 

 

Next in the Node.js series, we will look into what is event loop?  and how node.js handles concurrent requests with Single-Threaded model. Please check my post on getting started with node.js simple program.

Angular JS

Binding fields in HTML form with Java script was a big and tedious logic we will normally write in jquery and Java script days. Angular js comes to rescue from writing lot of glueing and boiler plate coding in front end development.

Angular js is MVC client side framework which developed to ease life of front end developers.I have developed a few applications using angular js. In this blog post, I will share some issues I had faced and how I fixed.

ObjectId to string issue with mongodb

In my application, i use nodejs with angular js and mongodb as backend.

Everything is fine, models are getting stored in to db and able to update , delete etc. But problems come when i retrieve with where clause. For example, I store some reference as id in a collection. But when i fire a query with where clause, it is not returning.

The problem here is ObjectId and String type problems.

Whenever I save a model first time it is going to db as ObjectId type. but when i update the model and store it, it gets changed to ‘String’ type. here the problem arises.

When I run a find() with where clause , if it is ObjectId , there is not problems, but after some update in to model, it is saved as ‘String’, so it is not getting matched by the query.

I have written some logic to avoid this problem.

There are 2 ways you can fix this problem.

Before you read/find, you interrupt and convert the where condition value to ObjectID. Every read operation will be interrupted and the conversion happens before executing find against DB.
Interrupt the update/save operation of every model and convert the reference to ObjectId and save it.

I am going to the 2nd way as compare to read operations(there are much more find/reads) , the updates are less.

I will have the ‘Before save’ operation hooks in node js to interrupt the save operation of every model and do the conversion as follows:

module.exports = function (MyModel) {
var ObjectId = require('mongodb').ObjectId;
MyModel.observe('before save', function convertPersonIdToObjectId(ctx, next) {try {
if (ctx.instance) {
if (ctx.instance.personId) {
var comp_id = new ObjectId(ctx.instance.personId); // make an ObjectId
delete ctx.instance.personId;
ctx.instance.personId = comp_id;
}} else {
if (ctx.data.personId) {
var comp_id = new ObjectId(ctx.data.personId); // make an ObjectId
delete ctx.data.personId;
ctx.data.personId = comp_id;}}
} catch (err) {
console.log(err);
}  next();});};

-PersonId is the reference I store in my MyModel collection. now it is getting stored as ObjectId.

As a developer, I often use username and passwords in the test classes especially in integration test cases.

Sometime we forgot to delete this, which leads to code base having passwords and that is not safe. I normally use properties file to store username and password( encrypted ) using Base64 algorithm.

So I will run a java program and pass the real password and encode it and then store it in the properties files.

Whenever i need it , i will call the util program to decode and then use it in test cases.So that the password is not human readable.

I am going to write steps to show you how to encode and store it in properties file, then how to read properties file in java.

Step 1:
Create a maven project. Please check this link Creating maven java project
You can see a project structure like this:

in Eclipse as follows:

Step 2:
Now Please create a java class called PropertiesUtil.java with the following contents:

This class will contain methods to do the following:

  1. 1.Encode the given string
  2. 2.Decode the given string
  3. 3.Get the string from a properties file and/or decode it


package com.mksiva.app;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Properties;
/**
*
* @author mksiva
*
*/
public class PropertiesUtil {

/**
* Encoding using base64
* @param aInput
* @return
*/
public static String encode(String aInput) {
byte[] bytesEncoded = Base64.getEncoder().encode((aInput).getBytes());
return new String(bytesEncoded);
}

/**
* Decoding using base64
* @param aEncrypterInput
* @return
*/
public static String decode(String aEncrypterInput) {
byte[] bytesDecoded = Base64.getDecoder().decode(aEncrypterInput);
return new String(bytesDecoded);
}

/**
* Getting the config.properties file as stream.
* @return an InputStream
*/
private InputStream getStream() {
InputStream in = getClass().getClassLoader().getResourceAsStream("config.properties");
return in;
}

/**
* Getting the password (encoded/not) and decode it and return it
* @param aPropertyKey
* @param aDecode
* @return decoded String
*/
public static String getValueFromPropertiesFile(String aPropertyKey, boolean aDecode) {

Properties prop = new Properties();
InputStream in = new PropertiesUtil().getStream();
try {
prop.load(in);
String propValue = prop.getProperty(aPropertyKey);
if (propValue != null && aDecode) {
return decode(propValue);
}
return propValue;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}

Step 3:
Create a property file called “config.properties” under “src/main/resources”.Encoding the password and store it in the properties file.(config.properties)

package com.mksiva.app;
/**
* App
*
*/
public class App
{
public static void main( String[] args )
{
String thePasswordToEncode = "password";
System.out.println(PropertiesUtil.encode(thePasswordToEncode));
}
}

Run the above program and get the password and store it in config.properties.

config.properties:
userName=test
passWord=cGFzc3dvcmQ=

Step 4:
Whenever I needed the password, I will first decode is using decodeFromPropertiesFile method from the PropertiesUtil.java, and then use it.

Testing the decode method:
package com.mksiva.app;

/**
* App
*
*/
public class App
{
public static void main( String[] args )
{
String decodedPassword = PropertiesUtil.getValueFromPropertiesFile("passWord", true);
System.out.println(decodedPassword);
}
}

The above program will print the decoded password string ‘password’. Which can be used in other parts of the application.

What is Unit testing?

Unit testing is a way to test your units(i.e parts) of your program. Usually unit tests should include not only positive scenarios but also negative scenarios that can occur in your piece of code. Examples are exceptions, error, negative results like that.

Is it really important?
YES!
But most of the developers are not taking unit testing seriously, thinking it is a waste of time.

If you are thinking in that way, then you will certainly waste lot of time doing manual testing with different set of data/ scenarios to test your piece of code.

Every time , when there is a change, you will end up missing some steps(lazyness) and  it could  introduce new bugs when it is getting tested in IT(Integration testing) environment.

So, you be patient and put some time to write test cases, cover all the possible scenarios( positive and negative).

So next time when you change something in your code, it will break in unit testing, then you can easily fix and avoid bugs being popped up in IT.

Most importantly you are running all the testing scenarios which you could possibly miss when manually unit testing your code.(manually unit testing your code is NOT preferable).

What is Junit?

JUnit is a testing framework for writing test cases and test suites(set of test cases) to test your program unit by unit.

We will see how can we write and execute unit test cases in java using maven and junit.

Creating java project using maven:

Make sure you have java and maven installed in your system. You can run ‘mvn -version’ to check ,if the maven is installed. You want to install maven please check this post Install maven in linux .

Assuming we have created a project using maven, please check this post on How to create java project using maven.

You can run the following mvn command to create a simple project:

mvn archetype:generate -DgroupId=com.mksiva.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

It creates a project with default maven structure.

If you look at the generated pom.xml:

<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.mksiva.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

The JUnit is included by default. so you can use whatever version you want. I am going to use 4.10.

Writing Unit test cases and actual methods.

Writing failed test cases first then write our real methods to make it success. This particular method is called ‘TDD’ Test Driven Development.

We want to develop a method which will return addition of two numbers, if the inputs are not proper( null), then will throw our own exception, called AdditionProgramException.(custom exception), usually when you try to do some operation with null or improper input, you will get ‘NullPointerException’ or Exception but for our example purpose, we throw our own exception.

We have 2 classed created App.java, AppTest.java.

mvn_folder

Writing test case first:
The add method is not there, so we will go and create a new method add() in our App.java

unittest_error

we have added now a method.

App.java

package com.mksiva.app;

/**
* App
*
*/
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
}

/**
*
* @param aNumber
* @param aSecondNumber
* @return int addition result
*/
public int add(int aNumber, int aSecondNumber) {
int result = 0;
return result;
}
}

AppTest.java:

/**
* Testing addition
* /
@Test
public void testAdd() {
int number1 = 3;
int number2 = 3;
int theExpectedResult = 6;
int theActualResult = myTestingApp.add(number1, number2);
assertEquals(theExpectedResult, theActualResult);
}

Now we have written a test case and going to run it.

In terminal or command line, go to the directory of the project and run:

mvn clean test

you will see:

T E S T S
-------------------------------------------------------
Running com.mksiva.app.AppTest
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.065 sec <<< FAILURE! - in com.mksiva.app.AppTest
testAdd(com.mksiva.app.AppTest)  Time elapsed: 0.011 sec  <<< FAILURE!
java.lang.AssertionError: expected:<6> but was:<0>
at org.junit.Assert.fail(Assert.java:93)
at org.junit.Assert.failNotEquals(Assert.java:647)
at org.junit.Assert.assertEquals(Assert.java:128)
at org.junit.Assert.assertEquals(Assert.java:472)
at org.junit.Assert.assertEquals(Assert.java:456)
at com.mksiva.app.AppTest.testAdd(AppTest.java:47)
Results :
Failed tests:
AppTest.testAdd:47 expected:<6> but was:<0>
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE

Carefully look at the error message, expected result was 6 but actual is 0. So our add() is not returning correct value. So now we have to fix it.

We will change App.java as follows:

public int add(int aNumber, int aSecondNumber) throws AdditionProgramException {
int result = 0;
result = aNumber + aSecondNumber;
return result;
}

re-run mvn clean test in terminal:

The message is now as follows;

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.mksiva.app.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.106 sec - in com.mksiva.app.AppTest
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.048 s

We will add Exception handling now. And finally our App.java is fully implemented.

pom.xml

<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.mksiva.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

App.java

package com.mksiva.app;
/**
* App
*
*/
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
}
/**
*
* @param aNumber
* @param aSecondNumber
* @return int addition result
* @throws AdditionProgramException
*/
public Integer add(Integer aNumber, Integer aSecondNumber) throws AdditionProgramException {
Integer result = 0;
if(aNumber == null || aSecondNumber == null){
throw new AdditionProgramException("Null param passed.");
}
try {
result = aNumber + aSecondNumber;
} catch (Exception e) {
throw new AdditionProgramException(e);
}
return result;
}
}

AppTest.java

package com.mksiva.app;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
/**
* Unit test for simple App.
*/
public class AppTest{
@Mock
App myTestingApp;
/**
* This will be called before any test executions.
*/
@Before
public void startUp(){
myTestingApp = new App();
}
/**
* This will be called after all the test cases are executed.
* So any clean up or freeing up operation should be done here.
*/
@After
public void cleanUp(){
myTestingApp = null;
}
/**
* Testing addition
* @throws AdditionProgramException
*/
@Test
public void testAdd() throws AdditionProgramException {
int number1 = 3;
int number2 = 3;
int theExpectedResult = 6;
int theActualResult = myTestingApp.add(number1, number2);
assertEquals(theExpectedResult, theActualResult);
}
@Test
public void testAddWithNull() throws AdditionProgramException {
Integer number1 = null;
Integer number2 = 3;
try {
myTestingApp.add(number1, number2);
} catch (AdditionProgramException e) {
assertEquals("Null param passed.", e.getMessage());
}
}
}

Now the test cases are executed and we have also covered positive and a negative testing scenarios.

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.mksiva.app.AppTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.131 sec - in com.mksiva.app.AppTest

Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.355 s

In Eclipse: Right click the AppTest.java –> run as –> Junit

eclipse_testrun2

The test results in eclipse:

 

testresult

 

Happy coding!.

Maven Java project can be created in 2 ways:

  1. Through command line
  2. Through an IDE like eclipse, net beans, IDEA etc.

Please check the blog for setting up maven Installing maven in linux

This tutorial will explain how to create a java project using maven through command line.

Creating a project

You will need a directory to put you project contents into. So please create directory and go to there, and run the following command to create a java project, using simple archetype.

$ cd hello-world-app

$ mvn archetype:generate -DgroupId=com.mksiva.app -DartifactId=helloworld-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

The project is created in the name of ‘artifactId’ you have passed.      You can see the project created message as :

...eclipsespace/hello-world-app/helloworld-app
[INFO] -----------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------
[INFO] Total time: 16.824 s
[INFO] Finished at: 2014-10-30T15:02:38+01:00
[INFO] Final Memory: 18M/162M

What did I just do?

You executed the Maven goal archetype:generate, and passed in various parameters to that goal. The prefix archetype is the plugin that contains the goal. If you are familiar with Ant, you may conceive of this as similar to a task. This goal created a simple project based upon an archetype.

The folder structure will be created, that is the standard directory structure of any maven project:

selection_003

Importing this project to IDE

To work further on this project, we will import this into any ide. Eclipse is used here to work on it.

So making this project ready to be imported, we will run the following command:

$ mvn eclipse:eclipse

Now this project can be imported to any IDE.

Eclipse IDE it can be done as follows:

Open-> File-> Import -> Maven -> Import existing maven projects

then import. Click Finish.

selection_004selection_005

Please look at the pom.xml. It is simple and it has only one dependency junit. Because our hello world app requires only junit external dependency to do the test.


<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.mksiva.app</groupId>
<artifactId>helloworld-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>helloworld-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

If you look at the App.Java, a simple add() method is added to perform addition of 2 numbers.

package com.mksiva.app;

/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}

public int add(int param1, int param2){
return param1 + param2;
}
}

So we write unit test case to cover that as follows in AppTest.java class.

/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
.
.
/**
* Rigourous Test 🙂
*/
public void testAdd()
{
assertEquals( 3, new App().add(1, 2) );
}
}

Build the project

$ mvn package

The command line will print out various actions, and end with the following:

app/helloworld-app/target/helloworld-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.616 s
[INFO] Finished at: 2016-10-30T16:05:46+01:00
[INFO] Final Memory: 20M/146M

Unlike the first command executed (archetype:generate) you may notice the second is simply a single word – package. Rather than a goal, this is a phase. A phase is a step in the build lifecycle, which is an ordered sequence of phases. When a phase is given, Maven will execute every phase in the sequence up to and including the one defined.

For example, if we execute the compile phase, the phases that actually get executed are:

validate
generate-sources
process-sources
generate-resources
process-resources
compile

You may test the newly compiled and packaged JAR with the following command:

$ java -cp target/helloworld-app-1.0-SNAPSHOT.jar com.mksiva.app.App

Which will print

 Hello World!