A Skeleton for Real Time Pitch Detection

See Real Time Visualization of a Spectrogram for reference on how to get this html page to respond to mic input (ie needs to be served by Tomcat).

This uses a modification of the pitch detection code found at updates.html5rocks.com to identify frequencies between E (329.6 Hz) and E (659.3 Hz).


<html>
<head>
<script type="text/javascript">

function interpolate(x, x0, xf, y0, yf) {
	// (x - x0)/(xf - x0) = (y - y0)/(yf - y0)
	// y = ( (x-x0)/(xf-x0) ) * (yf-y0) + y0
	return Math.floor( ( (x-x0)/(xf-x0) ) * (yf-y0) + y0 );
}

// colors:['#000000', '#ff0000', '#ffff00', '#ffffff']
// positions:[0, 64-1, 192-1, 255]
// 0 = parseInt('00', 16), 256-1 = parseInt('ff', 16)
function findColor(val) {
	var r, rDec, g, gDec, b, bDec;
	if(val < 64) {
		rDec = interpolate(val, 0, 64-1, 0, 256-1);
		r = rDec.toString(16);
		g = '00';
		b = '00';
	} else if (val < 192) {
		r = 'ff';
		gDec = interpolate(val, 64, 192-1, 0, 256-1); 
		g = gDec.toString(16);
		b = '00';
	} else {
		r = 'ff';
		g = 'ff';
		bDec = interpolate(val, 192, 256-1, 0, 256-1); 
		b = bDec.toString(16);
	}
	return '#'+r+g+b;
}

function canvasFillCoordinate(leftX, topY, color) {
	getCanvas().getContext('2d').fillStyle = color;
    getCanvas().getContext('2d').fillRect(leftX, topY, 2, 4);
}

function canvasShift(shiftAmount) {
	// Copy old image data to the left 1
	var imgData=getCanvas().getContext('2d').getImageData(0,0,getCanvas().width,getCanvas().height);
	getCanvas().getContext('2d').putImageData(imgData,shiftAmount,0);
}

function canvasInitialize(width, height) {
	getCanvas().getContext('2d').strokeStyle='#000000';
	
	// Set canvas parameters
	getCanvas().width = width;
	getCanvas().height = height;

	// Outline
    getCanvas().getContext('2d').clearRect(0,0,width,height);
	getCanvas().getContext('2d').rect(0,0,width,height);
	getCanvas().getContext('2d').stroke();
}

function noteFromPitch( frequency ) {
	var noteNum = 12 * (Math.log( frequency / 440 )/Math.log(2) );
	return Math.round( noteNum ) + 69;
}

function frequencyFromNoteNumber( note ) {
	return 440 * Math.pow(2,(note-69)/12);
}

function centsOffFromPitch( frequency, note ) {
	return ( 1200 * Math.log( frequency / frequencyFromNoteNumber( note ))/Math.log(2) );
}

function autoCorrelate( buf, sampleRate) {
	//var MIN_SAMPLES = 4;	// corresponds to an 11kHz signal
	//var MAX_SAMPLES = 1000; // corresponds to a 44Hz signal
	
	var MIN_SAMPLES = 60;	// corresponds to an 11kHz signal, 800
	var MAX_SAMPLES = 160; // corresponds to a 44Hz signal, 300
	var SIZE = 1000;
	var best_offset = -1;
	var best_correlation = 0;
	var rms = 0;

	var retVal = new Object();
	retVal.confidence = 0;
	retVal.currentPitch = 0;

	if (buf.length < (SIZE + MAX_SAMPLES - MIN_SAMPLES))
		return retVal;  // Not enough data

	for (var i=0;i<SIZE;i++) {
		var val = (buf[i] - 128)/128;
		rms += val*val;
	}
	rms = Math.sqrt(rms/SIZE);

	for (var offset = MIN_SAMPLES; offset <= MAX_SAMPLES; offset++) {
		var correlation = 0;

		for (var i=0; i<SIZE; i++) {
			correlation += Math.abs(((buf[i] - 128)/128)-((buf[i+offset] - 128)/128));
		}
		correlation = 1 - (correlation/SIZE);
		if (correlation > best_correlation) {
			best_correlation = correlation;
			best_offset = offset;
		}
	}
	if ((rms>0.01)&&(best_correlation > 0.01)) {
		retVal.confidence = best_correlation * rms * 10000;
		retVal.currentPitch = sampleRate/best_offset;
	}
	return retVal;
}

function createPitchUpdater(analyser, sampleRate) {
	var noteStrings = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
	var buflen = 2048;
	var timeLength = 500;
	var maxFreq = 500;
	canvasInitialize(timeLength,maxFreq);
	
	return function updatePitch(e) {
		canvasShift(-1);
		
		var buf = new Uint8Array( buflen );
		analyser.getByteTimeDomainData( buf );
		
		var retVal = autoCorrelate( buf, sampleRate );
		var floorCurrentPitch = Math.floor( retVal.currentPitch ) ;
		
		if (retVal.confidence > 10) {
			var note =  noteFromPitch( retVal.currentPitch );
			var noteString = noteStrings[note%12];
			var detune = centsOffFromPitch( retVal.currentPitch, note );
			
			var color;
			if (Math.abs(detune)<10) {
				color = "green";
			} else {
				color = "red";
			}
//			if (detune == 0 ) {
//			} else {
//				var color;
//				
//				var desc;
//				if (detune < 0) {
//					desc = "flat";
//				} else {
//					desc = "sharp";
//				}
//				
//				var detuneVal = Math.abs( Math.floor( detune ) );
//			}
			
			//var color = findColor(sample);
			canvasFillCoordinate(timeLength-4, floorCurrentPitch - 250, color);
			
			getLog().innerHTML = ' Note:' + noteString + ' Pitch:'+retVal.currentPitch + ' FloorCurrentPitch:' + floorCurrentPitch + ' confidence:' + retVal.confidence + ' sampleRate:' + sampleRate + '\n<br>';
		}
	}
}

function onSuccess(stream) {
	// stream -> mediaSource -> javascriptNode -> destination
    var context = new webkitAudioContext();
    var mediaStreamSource = context.createMediaStreamSource(stream);
	var analyser = context.createAnalyser();
    analyser.smoothingTimeConstant = 0.3;
    analyser.fftSize = 2048;
	var javascriptNode = context.createScriptProcessor(2048, 1, 1);
	mediaStreamSource.connect(analyser);
	analyser.connect(javascriptNode);
	javascriptNode.connect(context.destination);
	
	javascriptNode.onaudioprocess = createPitchUpdater(analyser, context.sampleRate);
}

function onError() {
	alert('Error');
}

function getLog() {
	return document.getElementById('mylog');
}

function getCanvas() {
	return document.getElementById('mycanvas');
}	
  
function documentReady() {
	var dataObject = {video: false, audio: true}; // dataObject.video, dataObject.audio
	if(navigator.getUserMedia) {
        navigator.getUserMedia(dataObject, onSuccess, onError);
	} else if(navigator.webkitGetUserMedia) {
        navigator.webkitGetUserMedia(dataObject, onSuccess, onError);
	}
}
</script>
</head>
<body onload="documentReady();">
   <canvas id="mycanvas"></canvas>
   <div id="mylog"></div>
</body>
</html>

Real Time Visualization of an FFT

From www.smartjava.org

This code needs to be added to a Tomcat server to work. This allows the microphone in Chrome to be connected. See Real Time Visualization of Raw Sound from Microphone Input using HTML5.


<html>
<head>
<script type="text/javascript">

function canvasFillRect(leftX, topY, width, height) {
	var gradient = getCanvas().getContext('2d').createLinearGradient(0,0,0,300);
	gradient.addColorStop(1,'#000000');
	gradient.addColorStop(0.75,'#ff0000');
	gradient.addColorStop(0.25,'#ffff00');
	gradient.addColorStop(0,'#ffffff');
	getCanvas().getContext('2d').fillStyle=gradient;
	getCanvas().getContext('2d').fillRect(leftX, topY, width, height);
}

function canvasInitialize(width, height) {
	getCanvas().getContext('2d').strokeStyle='#000000';
	
	// Set canvas parameters
	getCanvas().width = width;
	getCanvas().height = height;

	// Outline
    getCanvas().getContext('2d').clearRect(0,0,width,height);
	getCanvas().getContext('2d').rect(0,0,width,height);
	getCanvas().getContext('2d').stroke();
}

function onSuccess(stream) {
	// stream -> mediaSource -> javascriptNode -> destination
    var context = new webkitAudioContext();
    var mediaStreamSource = context.createMediaStreamSource(stream);
	var analyser = context.createAnalyser();
    analyser.smoothingTimeConstant = 0.3;
    analyser.fftSize = 2048;
	var javascriptNode = context.createScriptProcessor(2048, 1, 1);
	mediaStreamSource.connect(analyser);
	analyser.connect(javascriptNode);
	javascriptNode.connect(context.destination);
	
	javascriptNode.onaudioprocess = createProcessBuffer(analyser);
}

function createProcessBuffer(analyser) {
	return function processBuffer() {
		var fftData =  new Uint8Array(analyser.frequencyBinCount);
        analyser.getByteFrequencyData(fftData);
		
		// clear canvas and draw border
		canvasInitialize(1024,500);
	
		var average = 0;
		for(var i=0; i<fftData.length; i++) {
			var sample = fftData[i];
			canvasFillRect(i*5, 250-sample, 3, sample);
			average = average + sample;
		}
		average = average/fftData.length;
		getLog().innerHTML = 'FFT Length:'+fftData.length + ' Average:' + average + '\n<br>';
	};
}

function onError() {
	alert('Error');
}

function getLog() {
	return document.getElementById('mylog');
}

function getCanvas() {
	return document.getElementById('mycanvas');
}	
  
function documentReady() {
	var dataObject = {video: false, audio: true}; // dataObject.video, dataObject.audio
	if(navigator.getUserMedia) {
        navigator.getUserMedia(dataObject, onSuccess, onError);
	} else if(navigator.webkitGetUserMedia) {
        navigator.webkitGetUserMedia(dataObject, onSuccess, onError);
	}
}
</script>
</head>
<body onload="documentReady();">
   <canvas id="mycanvas"></canvas>
   <div id="mylog"></div>
</body>
</html>

Visualizing Raw Data Samples from a Microphone

This code uses javascript to visualize mic data samples within Chrome.

This code must be deployed in a Web Server like Tomcat. See Real Time Visualization of Raw Sound from Microphone Input using HTML5.


<html>
<head>
<script type="text/javascript">
function canvasDrawLine(oPosX, oPosY, fPosX, fPosY) {
	var ctx = getCanvas().getContext('2d');
	ctx.beginPath();
	ctx.moveTo(oPosX, oPosY);
	ctx.lineTo(fPosX, fPosY);
	ctx.stroke();
}

function canvasDrawSquare(ulPosX, ulPosY, lrPosX, lrPosY) {
	canvasDrawLine(ulPosX, ulPosY, ulPosX, lrPosY);
	canvasDrawLine(ulPosX, lrPosY, lrPosX, lrPosY);
	canvasDrawLine(lrPosX, lrPosY, lrPosX, ulPosY);
	canvasDrawLine(lrPosX, ulPosY, ulPosX, ulPosY);
} 

function canvasInitialize(width, height) {
	// Set canvas parameters
	getCanvas().width = width;
	getCanvas().height = height;

	// Outline
    getCanvas().getContext('2d').clearRect(0,0,width,height);
	canvasDrawSquare(0,0,width,height);
}

function onSuccess(stream) {
	// stream -> mediaSource -> javascriptNode -> destination
    var context = new webkitAudioContext();
    var mediaStreamSource = context.createMediaStreamSource(stream);
	var javascriptNode = context.createScriptProcessor(2048, 1, 1);
	mediaStreamSource.connect(javascriptNode);
	javascriptNode.connect(context.destination);
	
	javascriptNode.onaudioprocess = processBuffer;
}

function processBuffer(e) {
	var micData = e.inputBuffer.getChannelData(0);
	
	// clear canvas and draw border
	getCanvas().getContext('2d').strokeStyle='#000000';
	canvasInitialize(1024,500);
	
	// draw samples values in green
	getCanvas().getContext('2d').strokeStyle='#00ff00';
	var average = 0;
	var gain = 100;
	for(var i=0; i<1024; i++) {
		var sample1 = micData[2*i];
		var sample2 = micData[2*i+1];
		var val = (sample1+sample2)*gain; // combine two samples and multiply by gain
		canvasDrawSquare(i, 250, i+1, 250-val);
		average = average + sample1*sample1 + sample2*sample2;
	}
	average = Math.sqrt(average);
	getLog().innerHTML = average + '\n<br>';
}

function onError() {
	alert('Error');
}

function getLog() {
	return document.getElementById('mylog');
}

function getCanvas() {
	return document.getElementById('mycanvas');
}	
  
function documentReady() {
	var dataObject = {video: false, audio: true}; // dataObject.video, dataObject.audio
	if(navigator.getUserMedia) {
        navigator.getUserMedia(dataObject, onSuccess, onError);
	} else if(navigator.webkitGetUserMedia) {
        navigator.webkitGetUserMedia(dataObject, onSuccess, onError);
	}
}
</script>
</head>
<body onload="documentReady();">
   <canvas id="mycanvas"></canvas>
   <div id="mylog"></div>
</body>
</html>

HTML5 Animations, Revisited

Revisiting HTML5 Animations

This time, introducing the idea of function closure. The createDrawer sets up variables that can be initialized and then used by the drawer.

The main animation is done through the setInterval function which is called ever 100 milliseconds.


<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function startDrawingLine(canvas){
	// draw border
	initializeCanvas(canvas, 500,500);
	
	// call draw every 100 milli seconds
	setInterval(createDrawer(canvas), 10);
}

function initializeCanvas(canvas, width, height) {
	// Set canvas parameters
	canvas.width = width;
	canvas.height = height;

	// Outline
	var ctx = canvas.getContext('2d');
	ctx.beginPath();
	ctx.moveTo(0, 0);
	ctx.lineTo(0, height);
	ctx.lineTo(width, height);
	ctx.lineTo(width, 0);
	ctx.lineTo(0, 0);
	ctx.stroke();
}

function createDrawer(canvas) {
	var ctx = canvas.getContext('2d');
	var theta = Math.PI/8;
	var size = 30;
	var oPosX = 0;
	var oPosY = 0;
	var fPosX = oPosX+size*Math.cos(theta);
	var fPosY = oPosY+size*Math.sin(theta);
	
	return function drawer() {
		if(fPosX > canvas.width || fPosX < 0) {
			theta = Math.PI - theta;
		}
		if (fPosY > canvas.height || fPosY < 0){
			theta = -theta;
		}
		
		oPosX = oPosX+size/10*Math.cos(theta);
		oPosY = oPosY+size/10*Math.sin(theta);
		fPosX = oPosX+size*Math.cos(theta);
		fPosY = oPosY+size*Math.sin(theta);
		
		// draw line
		ctx.strokeStyle='#000000';
		ctx.beginPath();
		ctx.moveTo(oPosX, oPosY);
		ctx.lineTo(fPosX, fPosY);
		ctx.stroke();
	};
}
</script>
</head>

<body onload="startDrawingLine(document.getElementById('mycanvas'));">
   <canvas id="mycanvas"></canvas>
</body>
</html>

A Basic Dashboard

This article will demonstrate how to put together a basic dashboard that can be used to visualize data. The server and client in this article will refer to Windows machines.

Technologies Used

  • Java 7 Update 51 – Create applications from the Java Programming Language
  • Maven 3.0.5 – Project Management system for Java Programs
  • Eclipse – Development Environment to develop Java Programs
  • Git 1.9.4 – Version Control system, Unix command prompt for Windows
  • CopSSH 4.8.0 – SSH system for Windows
  • MongoDB 2.6.2 – Database system
  • Tomcat 7.0.54 – Web Server
  • Jenkins 1.568 – Continuous Integration, Job Management
  • JQuery 1.8.2 – Javascript/Ajax API
  • HighCharts – Javascript Chart Generator

Architecture Overview
We will build a Server which has the following capabilities:

  • Client Access via SSH
  • Hosting source code via Git
  • Accessing shared data from a MongoDB database
  • Hosting a front end webpage to visualize the shared data
  • Running periodic jobs to fetch and refresh the shared data

We will build a Client which has the following capabilities:

  • Accessing the server via SSH
  • Accessing source code via Git
  • Modifying shared data from a MongoDB database
  • Developing a Front End Web Application to visualize the shared data
  • Developing a Back End Java Application to fetch and refresh the shared data

Step 1: Setup the git user on the Server
Start, Right Click Computer, Manage, Select Configuration, Select Local Users and Groups, New user, Add user name “git” and give a password and keep track of it (it will need letters, numbers and a few special characters). Double click git and uncheck “Change password on next login”.

Make the directory “C:\Users\git”.

You will use the username and home directory below to login to the Server from the Client using SSH.

Step 2: Setup CopSSH on the Server
The Server will use CopSSH to allow SSH capability to provide access to the shared Java code (aka source code).

From github.com
From git-scm.com
CopSSH Installer – http://download.cnet.com/CopSSH/3001-7240_4-10218944.html?spi=dd79c53bc9a32dcbcf09df4229e7d536&dlm=0

Press Next through all screens, but enter a password and keep track of it. This will setup ssh as a Windows service.

Open CopSSH, Users Tab, Add, Forward, select git, Forward, enter home directory “C:\Users\git”, Forward, Apply. This verifies that step 1 above worked.

Step 3: Setup Git on the Client and Server
The Client will use Git as a command prompt and for modifying source code.
The Server will use Git as a command prompt and for hosting source code.

Git Installer – https://github.com/msysgit/msysgit/releases/download/Git-1.9.4-preview20140611/Git-1.9.4-preview20140611.exe

After installation, configure Git to be run from the command line:
Right click Computer, Advanced system settings, Environment variables, Under System variables select PATH, Edit, append “;C:\Program Files (x86)\Git\bin”. This will allow git to be run from the command line.

Two scripts are needed to upload and download source code via the ‘git push’ and ‘git clone’ commands. Copy the two scripts “git-upload-pack.exe” and “git-receive-pack.exe” from “C:\Program Files (x86)\Git\libexec\git-core” to “C:\Program Files (x86)\Git\bin”.

TEST SSH CONNECTION
From the client, open Git Bash. Type the command ‘ssh git@my.server.com’. Here my.server.com represents the domain name such as http://www.google.com or it could be your ip address.

When prompted enter the password for the git user that you created above. The Git Bash command prompt should change to show you are logged in (ie git@my.server.com). This step verifies that CopSSH was installed correctly. If you have trouble here, make sure the CopSSH service is running by opening the CopSSH Control Panel.

USE PUBLIC AND PRIVATE KEYS FOR AUTOMATIC AUTHENTICATION
Open Git Bash on the Client. Type the command ‘cd ~/.ssh’. Then, generate the public/private keys by typing the command ‘ssh-keygen’. Enter “id_rsa” as the file name and don’t enter a passphrase.

The .ssh folder should now contain id_rsa and id_rsa.pub. Copy the id_rsa.pub file from the Client to the “C:\Users\git” folder on the server.

Open Git Bash on the Server. Type the command following two commands to append the public key to the authorized_keys file


cd "C:\Users\git"
cat id_rsa.pub >> authorized_keys

Go back to the Git Bash on the Client and type the command ‘ssh git@my.server.com’. This time you should not need to type in a password. (You may need to delete the known_hosts file in the .ssh directory and close and reopen Git Bash)

CREATE THE REPOSITORY FOR YOUR PROJECT
From the Server, Open Git Bash and enter the following commands (replace project with the name of your project):


cd "C:\Users\git"
mkdir project.git
cd project.git
git --bare init

From the Client, Open Git Bash and enter the following commands after moving to a directory where you wish to store your project:


mkdir project
cd project
git init
touch new
git add -A
git commit -m "initial commit"
git remote add origin git@my.server.com:project.git
git push origin master

From now on, any other clients that want access to this code can issue:


git clone git@my.server.com:project.git

Step 4: Setup MongoDB on the Server
The Server will use MongoDB to provide access to the shared data.

From docs.mongodb.org
64 bit MongoDB Installer – https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-2.6.2.zip

You can run this command to find out if you need 64 bit or 32 bit:


wmic os get osarchitecture

Copied to server, extracted all the files, copied the bin folder to “C:\mongodb\bin” (and other miscellaneous files moved to mongodb folder).

CONFIGURE AND START MONGO DB SERVER


Open Git Bash on the Server
cd /c/mondodb
mkdir data
mkdir data/db
 
mkdir data/log
echo logpath="C:\mongodb\data\log\mongo.log" > "C:\mongodb\mongod.cfg"
echo dbpath="C:\mongodb\data\db" >> "C:\mongodb\mongod.cfg"
sc.exe create MongoDB binPath= "\"C:\mongodb\bin\mongod.exe\" --service --config=\"C:\mongodb\mongod.cfg\"" DisplayName= "MongoDB 2.6 Standard" start= "auto"

If you reopen the Services from Task Manager, Services Tab, Services button, you will see “MongoDB 2.6 Standard”
You may start MongoDB from the services or enter the command ‘net start MongoDB’.

ADD DATA TO MONGO DB

From docs.mongodb.org


Open Git Bash on the Server
/c/mongodb/bin/mongo.exe
db
(displays test, the database created by default)
use mydb
(creates a database called mydb, switches to that database)
j = { name : "mongo" }
k = { x : 3 }
(creates some data)
db.testData.insert(j)
db.testData.insert(k)
(creates the testData collection and adds the data to the collection)
show collections
(shows the new testData collection)

TEST CONNECTION FROM THE CLIENT

Mongo VUE Installer – http://www.mongovue.com/Installer-1.6.9.zip

Open Mongo VUE, hit Connect, hit plus button, Enter ‘MongoDB’ in Name, add ‘my.server.com’ in Server, add 27017 in Port and ‘testData’ in Database(s). The configuration above created a ‘test’ database by default. There is no username or password.

Hit Save, Connect. You can expand ‘mydb’ database to see the ‘testData’ collection and double click that to see the 2 documents added (name=mongo and x=3).

Step 5: Setup Java on the Client and Server
The Client will use Java to develop the Web Application and Java Application.
The Server will use Java to run Tomcat.

For help, see Getting Started with Java’s Hello World: Part I
From www.oracle.com
Java 7 Update 51 Installer – http://download.oracle.com/otn/java/jdk/7u51-b13/jdk-7u51-windows-x64.exe

After installation, configure Java to be run from the command line:
Right click Computer, Advanced system settings, Environment variables, Under System variables select PATH, Edit, append “;C:\Program Files\Java\jdk1.7.0_51\bin”.

You can test this by opening a command prompt and running the following command ‘java -version’. If it shows 1.7.0_51, Java has been installed correctly.

Step 6: Setup Maven on the Client and Server
The Client will use Java to develop the Web Application and Java Application.
The Server will use Maven to run a periodic job using a Jenkins script.

For help, see Getting Started with Java’s Hello World: Part II
From maven.apache.org
Maven 3.0.5 Installer – http://www.dsgnwrld.com/am/maven/maven-3/3.0.5/binaries/apache-maven-3.0.5-bin.zip

After installation, configure Maven to be run from the command line:
Right click Computer, Advanced system settings, Environment variables, Under System variables select PATH, Edit, append “;C:\apache-maven-3.0.5\bin”.

Create a new system variable, JAVA_HOME whose value is “C:\Program Files\Java\jdk1.7.0_51”.

You can test this by opening a command prompt and running the following command ‘maven -version’. If it shows 3.0.5, Maven has been installed correctly.

Step 7: Setup Eclipse on the Client
For help, see Getting Started with Java’s Hello World: Part III

Step 8: Create a Back End Java Project to Add More Data to Mongo DB
For help, see the Getting Started tutorial links in above.

CREATE THE BACK END PROJECT
Create a new Maven project (create a default Java Application, assuming Java, Maven and Eclipse are installed). In the pom.xml file, add the mongo dependency.

ADD THE BACK END PROJECT MAVEN DEPENDENCIES


<!-- Mongo DB -->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>2.11.3</version>
</dependency>

ADD THE BACK END CONTROLLER CLASS TO POPULATE THE MONGO DB WITH DATA
In the src/main/java folder, add a package and a class:


package my.company.com.BackEnd;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.ServerAddress;

public class BackEndController {
	public static void main(String[] args) {
		System.out.println("Starting BackEndController");
		DB mongoDB = createMongoDB("my.server.com", "", "", "mydb");
		DBCollection testCollection = mongoDB.getCollection("test_collection");
		deleteAllEntries(testCollection);
		
		DBObject record1 = new BasicDBObject();
		record1.put("First", "Johnny");
		record1.put("Last", "Smith");
		testCollection.save(record1);
		
		DBObject record2 = new BasicDBObject();
		record2.put("First", "Jane");
		record2.put("Last", "Smith");
		testCollection.save(record2);
		
		System.out.println("Finishing BackEndController");
	}
	
	public static DB createMongoDB(String replicaSetURL, String username, String password, String databaseName) {
		try {
			ArrayList addresses = new ArrayList();
			for (String address: replicaSetURL.split(",")) {
				addresses.add(new ServerAddress(address));
			}
			Mongo mongo = new Mongo(addresses);
			mongo.slaveOk();
			DB mongoDB = mongo.getDB(databaseName);
			mongoDB.authenticate(username, password.toCharArray());
			return mongoDB;
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	public static List findAll(DBCollection collection) {
		List objects = new ArrayList();
		DBCursor cursor = collection.find();
		try {
			while(cursor.hasNext()) {
				DBObject object = cursor.next();
				objects.add(object);
			}
		} finally {
			cursor.close();
		}
		return objects;
	}
	
	public static  void deleteAllEntries(DBCollection collection){
		List objects = findAll(collection);
		for(DBObject object: objects) {
			collection.remove(object);
		}
	}
}

Right click, Run As Java. Then, use Mongo VUE to verify the “test_collection” collection was created and the new data records were added.

COMMIT THE CODE FOR THE BACK END PROJECT
From Eclipse, delete this project from the Package Explorer (but don’t delete from your hard drive). Copy the contents to the project folder created above. Then commit this project to the Git central repository, by opening Git Bash from the Client and running the following commands:


Move to the project directory
git status
(Should show all the files that you are about to add for the Back End Project)
git add -A
git commit -m "Adding the Back End project"
git push origin master

This code represents code that is responsible for fetching external data, within the Back End that you wish to display.

Step 9: Integrate Tomcat with Eclipse
For help, see “Setup Server” from Creating a New Web App to Handle File Upload.

Step 10: Create the Front End Web App to Display Data from Mongo DB

CREATE THE FRONT END PROJECT
Create a new Maven project (create a default Java Web Application, assuming Java, Maven, Eclipse and Tomcat are installed).

ADD THE POM DEPENDENCIES FOR THE FRONT END PROJECT
In the pom.xml file, add the mongodb (connect to database), spring (configure web app servlet) and httpclient (connect to server) dependencies.


<!-- Mongo DB -->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>2.11.3</version>
</dependency>
 
 
<!-- org.springframework.web.servlet -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>3.0.5.RELEASE</version>
</dependency>
 
<!-- HttpClient -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2.2</version>
</dependency>

ADD THE SERVLET FOR THE FRONT END PROJECT
In the src/main/webapp/WEB-INF folder, edit the web.xml file to contain the following (notice we are using version=2.5):


<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
 
    <display-name>Archetype Created Web Application</display-name>
 
    <servlet>
        <servlet-name>FrontEndController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/fecontroller-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>FrontEndController</servlet-name>
        <url-pattern>/fecontroller/*</url-pattern>
    </servlet-mapping>
</web-app>

ADD THE BEANS NEEDED FOR THE SERVLET
In the WEB-INF folder add the file “fecontroller-servlet.xml” containing the following:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <context:component-scan base-package="my.company.com.FrontEnd" />
 
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
 
</beans>

ADD THE DISPLAY WEB PAGE FOR THE SERVLET
Add the src/main/webapp/WEB-INF/fecontroller-display.jsp file to have the following (we will substitute the body with something else):


<html>
<body>
<h2>Front End Controller Display</h2>
 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
 
<div id="container" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>
<script type="text/javascript">
$(function () {
    $('#container').highcharts({
        chart: {
            plotBackgroundColor: null,
            plotBorderWidth: 1,//null,
            plotShadow: false
        },
        title: {
            text: 'User Time Percentages'
        },
        tooltip: {
            pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
        },
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                dataLabels: {
                    enabled: true,
                    format: '<b>{point.name}</b>: {point.percentage:.1f} %',
                    style: {
                        color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                    }
                }
            }
        },
        series: [{
            type: 'pie',
            name: 'Time share',
            data: [
                ['${firstName}',   65.2],
                ['${secondName}',   34.8],
            ]
        }]
    });
});
</script>
</body>
</html>

We will pull the firstName and secondName from the database, but later all this data can be pulled as desired.

ADD THE REST CONTROLLER FOR THE SERVLET
Add the Front End Controller which will use REST service


package my.company.com.FrontEnd;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.ServerAddress;
@Controller
@RequestMapping("/")
public class FrontEndController {
    public static void main(String[] args) {
        HttpClient httpclient = new DefaultHttpClient();
         
        try {
            String url = "http://localhost:8080/FrontEnd/fecontroller/display";
            HttpGet httpGet = new HttpGet(url);
            HttpResponse response = httpclient.execute(httpGet);
            System.out.println("output1:"+EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  
    @RequestMapping(value="display", method = RequestMethod.GET)
    public String welcome(ModelMap model) {
        DB mongoDB = createMongoDB("my.server.com", "", "", "mydb");
        DBCollection testCollection = mongoDB.getCollection("test_collection");
        List dbObjects = findAll(testCollection);
        String firstName = dbObjects.get(0).get("First") + " " + dbObjects.get(0).get("Last");
        String secondName = dbObjects.get(1).get("First") + " " + dbObjects.get(1).get("Last");
         
        model.addAttribute("firstName", firstName);
        model.addAttribute("secondName", secondName);
        return "fecontroller-display";  //Spring uses InternalResourceViewResolver and return back fecontroller-display.jsp
    }
    public static DB createMongoDB(String replicaSetURL, String username, String password, String databaseName) {
        try {
            ArrayList addresses = new ArrayList();
            for (String address: replicaSetURL.split(",")) {
                addresses.add(new ServerAddress(address));
            }
            Mongo mongo = new Mongo(addresses);
            mongo.slaveOk();
            DB mongoDB = mongo.getDB(databaseName);
            mongoDB.authenticate(username, password.toCharArray());
            return mongoDB;
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
     
    public List findAll(DBCollection collection) {
        List objects = new ArrayList();
        DBCursor cursor = collection.find();
        try {
            while(cursor.hasNext()) {
                DBObject object = cursor.next();
                objects.add(object);
            }
        } finally {
            cursor.close();
        }
        return objects;
    }
}

TEST THE SERVLET IN TOMCAT IN ECLIPSE


Open Git Bash and prepare the Front End project
mvn eclipse:eclipse -Dwtpversion=2.0

In the Servers Tab, add the Front End project to Tomcat, Right Click and Start.
You can then open Firefox and view the display at http://localhost:8080/FrontEnd/fecontroller/display

COMMIT THE CODE FOR THE FRONT END PROJECT
From Eclipse, delete this project from the Package Explorer (but don’t delete from your hard drive). Copy the contents to the project folder created above. Then commit this project to the Git central repository, by opening Git Bash from the Client and running the following commands:


Move to the project directory
git status
(Should show all the files that you are about to add for the Back End Project)
git add -A
git commit -m "Adding the Front End project"
git push origin master

This code represents code that is responsible for displaying internal data.

Step 11: Setup Tomcat on the Server to Host the Front End Display
From tomcat.apache.org
Tomcat 7 Installer – http://mirror.symnds.com/software/Apache/tomcat/tomcat-7/v7.0.54/bin/apache-tomcat-7.0.54.exe

After installing the Java jdk, you can use this in the tomcat installation (ie “C:\Program Files\Java\jdk1.7.0_51”).

On the client, Open Git Bash and move to the directory containing the pom.xml file for the Front End project. Enter the command ‘mvn install’ to create the FrontEnd.war file, which will be found in the target directory. Copy this to the Tomcat webapps directory on the Server (ie “C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps”).

From the Services Tab, find Tomcat, stop, start.

Open Firefox and hit the url, this time using the server host name: http://my.server.com:8080/FrontEnd/fecontroller/display

Step 12: Setup Jenkins on the Server
Note: Up to this point, we have not discussed the Maven Repository. These instructions don’t handle setting up a Maven Repository. This is what automatically pulls in certain maven dependencies when you run the ‘mvn compile’ command from the Git Bash. The local and central repositories are handled by the settings.xml file which can be found at “C\apache-maven-3.0.5\conf\settings.xml”. If you cannot run the ‘mvn exec:java’ command below on the Jenkins machine you will have to find another way to compile the code (such as packaging the libraries with the code).

From jenkins-ci.org
Jenkins 1.568 Installer – http://mirrors.jenkins-ci.org/war/latest/jenkins.war

Copy this war file to the Tomcat webapps directory on the Server and restart tomcat

Open Firefox and hit the url: http://my.server.com:8080/jenkins. You may see “Please wait while Jenkins is getting ready to work”

CONFIGURE THE JENKINS USER FOR SSH
From wiki.jenkins-ci.org

For the jenkins user (by default, “Local System account”), create the .ssh directory (for Local System account, use “C:\Windows\SysWOW64\config\systemprofile\.ssh”).

From above, when you cloned the git repo from the Client, it created a known_hosts file in the .ssh folder (‘cd ~/.ssh’). Copy the id_rsa, id_rsa.pub and known_hosts files into the .ssh directory for the jenkins user on the Server. Remember, when Jenkins is running, it will be a Git Client connecting to the Git Server to pull the source code.

CONFIGURE A JENKINS JOB TO RUN THE BACK END CODE
From the jenkins web console, create new jobs, enter “BackEnd” as name, “build a free-style software project”

Select build periodically, enter cron expression “5 8 * * 6” (don’t include quotes) to build every Saturday and 8:05am. This represents having data collected automatically on a regular basis.

Add build step, Execute Windows batch command, enter this script


echo "Removing old project directory"
rm -rf project 
 
echo "Checking out master branch"
git clone git@my.server.com:project.git
cd project/Backend
git log -1
 
echo "Running Backend"
mvn exec:java -Dexec.mainClass="my.company.com.BackEnd.BackEndController"

On the job, click build now. Verify that it ran successfully.

Step 13: Test the whole system
On the client, edit the backend controller to insert “JJJ Andrews” as the first name (these lines for record1 can be found in the main method of BackEndController.java:


        DBObject record1 = new BasicDBObject();
        record1.put("First", "JJJ");
        record1.put("Last", "Andrews");
        testCollection.save(record1);

Save the code and commit via Git Bash


git add -A
git commit -m "Test backend data change"
git push origin master

Although this change would automatically be run on Saturday morning, we will manually run it through Jenkins

Click build now, from the Firefox on the Jenkins terminal.

You should now see “JJJ Andrews”.

image2014-6-20 15-19-26

Creating a New Web App to Handle File Upload

Setup Server
Download Geronimo or Tomcat from geronimo.apache.org or tomcat.apache.org.

For these instructions, I will use the 64 bit Windows (my machine is 64 bit), zip file for Tomcat 7.0.54 which was extracted to the “C:\apache-tomcat-7.0.54” folder so that there was a folder “C:\apache-tomcat-7.0.54\bin”.

I hit some errors here like “Specified JRE does not exist” and “Class not found for an osgi jar file”.

To see the Server Tab, in Eclipse, Window -> Show View -> Other… -> Server -> Servers. Right click Servers Tab -> New -> Server -> Select Tomcat v7.0 Server -> Add -> Browser for the installation directory (ie “C:\apache-tomcat-7.0.54”), for JRE select jdk1.7.0_51 (you need to have Java 7 installed) -> Finish.

Right click the Server and select Start. You should see in the Console Tab a message indicating startup worked (ie “INFO: Server startup in 526 ms”).

Right click the Server and select Stop.

Setup Web App
If Eclipse is setup correctly, you can right click in the Project Explorer -> New -> Project -> Maven -> Maven Project -> Next -> Next -> Choose maven-archetype-webapp -> Next -> Enter Group Id “my.company.com” and Artifact Id “MyApp” -> Finish.

Prepare for wtp by opening Git Bash (or Windows Command Prompt), going to directory with the new pom.xml file (You may right click the FileUploader, click properties to see the location).


mvn eclipse:eclipse -Dwtpversion=2.0

In Eclipse, right click the new project and select Refresh (or hit F5).

Right Click Server and select Add or Remove. Select MyApp and Add. Finish. Right Click Server and select Start. Wait for startup message.

Open Firefox with http://localhost:8080/MyApp/. You should see the Hello World on the screen.

At this point, I had errors in Eclipse “Java compiler level does not match” and “Project configuration is not up-to-date”. I had to right click the error and Quick fix to get rid of the first (change facet version to Java 1.7). I had to right click -> Maven -> Disable Maven Nature to get rid of the second error.

Setup Http Client to Test
Add this dependency to your pom.xml file.


		<!-- HttpClient -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.2.2</version>
		</dependency>

Create a new package, in src/main/resources called “base”. Within that, create a new class called Base, with this code.


package base;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

public class Base {
	public static void main(String[] args) {
		HttpClient httpclient = new DefaultHttpClient();
		
		try {
			String url = "http://localhost:8080/MyApp";
			HttpGet httpGet = new HttpGet(url);
			HttpResponse response = httpclient.execute(httpGet);
			System.out.println("output:"+EntityUtils.toString(response.getEntity()));
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

Right click, the class, Run As, Java Application. If the server is still running, you should see:


output:<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

Setup REST
At this point, I will follow www.mkyong.com, which is a great site for tutorials. If you had trouble with the last step, follow this link to create a web app project in Eclipse using a Maven Archetype.

I will modify his work slightly to keep existing tests working:
1. Open Firefox with http://localhost:8080/MyApp/
2. Running Base.java class

Step 1: Add POM dependencies
I only added one spring dependency.


 		<!-- org.springframework.web.servlet -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>3.0.5.RELEASE</version>
		</dependency>

Step 2: Define a new servlet in web.xml
My default archetype project used Web App 2.3 and this is upgraded to Web App 2.5. Although the DispatcherServlet would automatically load dispatcher-servlet without the init-param, I add this explicitly for ease of maintenance. I also left out the context-param and listener tags to clarify what was needed.


<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<display-name>Archetype Created Web Application</display-name>

	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/dispatcher/*</url-pattern>
	</servlet-mapping>
</web-app>

Step 3: Add the Servlet Beans
In the WEB-INF folder, create a new file called “dispatcher-servlet.xml” and add the following. This bean will load the classes in the dispatcher package and use the web pages in the WEB-INF/pages folder.


<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:component-scan base-package="dispatcher" />

	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/pages/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

</beans>

Step 4: Add the Message web page
In the WEB-INF/pages folder, add a file “message.jsp” with the following html. This page will be used by the Dispatcher class to substitute the message.


<html>
<body>
<h2>Message Page</h2>

<h4>Message : ${message}</h1>	
</body>
</html>

Step 5: Add the Dispatcher Class
Create a package in src/main/java called dispatcher. Then, add the Dispatcher class:


package dispatcher;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
@RequestMapping("/")
public class Dispatcher {
	public static void main(String[] args) {
		HttpClient httpclient = new DefaultHttpClient();
		
		try {
			String url = "http://localhost:8080/MyApp/dispatcher/welcome";
			HttpGet httpGet = new HttpGet(url);
			HttpResponse response = httpclient.execute(httpGet);
			System.out.println("output1:"+EntityUtils.toString(response.getEntity()));
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
		try {
			String url = "http://localhost:8080/MyApp/dispatcher/welcome/myExtraName";
			HttpGet httpGet = new HttpGet(url);
			HttpResponse response = httpclient.execute(httpGet);
			System.out.println("output2:"+EntityUtils.toString(response.getEntity()));
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
 
	@RequestMapping(value="welcome", method = RequestMethod.GET)
	public String welcome(ModelMap model) {
		model.addAttribute("message", "Maven Web Project + Spring 3 MVC - welcome()");
		return "message";  //Spring uses InternalResourceViewResolver and return back message.jsp
	}
 
	@RequestMapping(value="welcome/{name}", method = RequestMethod.GET)
	public String welcomeName(@PathVariable String name, ModelMap model) {
		model.addAttribute("message", "Maven Web Project + Spring 3 MVC - " + name);
		return "message";
	}
}

To test, restart the server:


From Git Bash, run 'mvn eclipse:eclipse -Dwtpversion=2.0'
From Eclipse, right click the project->Refresh (or F5)
From Eclipse Server Tab, right click the Server->Stop
From Eclipse Server Tab, right click the Server->Clean
From Eclipse Server Tab, right click the Server->Start

You should see this in the output (pay attention to the number of slashes)


Jun 18, 2014 12:25:30 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/welcome/{name}] onto handler 'dispatcher'
Jun 18, 2014 12:25:30 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/welcome/{name}.*] onto handler 'dispatcher'
Jun 18, 2014 12:25:30 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/welcome/{name}/] onto handler 'dispatcher'
Jun 18, 2014 12:25:30 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/welcome] onto handler 'dispatcher'
Jun 18, 2014 12:25:30 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/welcome.*] onto handler 'dispatcher'
Jun 18, 2014 12:25:30 PM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/welcome/] onto handler 'dispatcher'

Open Firefox and check the Dispatcher page:
http://localhost:8080/MyApp/dispatcher/welcome

Right click the Dispatcher class->Run As->Java Application
You should see this code


output1:

Message Page

Message : Maven Web Project + Spring 3 MVC - welcome()

output2:

Message Page

Message : Maven Web Project + Spring 3 MVC - myExtraName

Note: Make sure the server is ready before running tests. Something like “initialization completed in 117 ms” should appear in the console.

Add Code to Upload a File
These instructions were written so the four previous tests should still work.

Step 1: Add the pom.xml dependency


		<!-- MultipartEntity -->
		<dependency>
  			<groupId>org.apache.httpcomponents</groupId>
  			<artifactId>httpmime</artifactId>
  			<version>4.0.1</version>
		</dependency>
		<!-- File Upload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.2.2</version>
		</dependency>
		<!-- DeferredFileOutputStream -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>1.3.1</version>
		</dependency>

Step 2: Define the Loader servlet in web.xml


	<servlet>
		<servlet-name>loader</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/loader-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>loader</servlet-name>
		<url-pattern>/loader/*</url-pattern>
	</servlet-mapping>

Step 3: Define the Loader beans
In the WEB-INF folder, create an xml file “loader-servlet.xml” with the following bean definitions:


<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:component-scan base-package="loader" />
	
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/pages/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
	
	<context:annotation-config />
 
 	<bean
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
	<bean id="annotationHandlerMapping"
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- setting maximum upload size -->
		<property name="maxUploadSize" value="52428800" />
	</bean>
</beans>

Step 4: Define the Loader Class
In src/main/java create a package called loader, within that create a class named “Loader”. Add the following java code to that class:


package loader;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

@Controller
@RequestMapping("/")
public class Loader {
	public static void main(String[] args) throws UnsupportedEncodingException {
		HttpClient httpclient = new DefaultHttpClient();

		try {
			String uploadFilePath = "c:\\uploadSource\\test.txt";
			String url = "http://localhost:8080/MyApp/loader/upload";
			HttpPost httpPost = new HttpPost(url);

			MultipartEntity reqEntity = new MultipartEntity();
			reqEntity.addPart("file", new FileBody(new File(uploadFilePath)));

			reqEntity.addPart( "folder", new StringBody( "", "text/plain", 
	                Charset.forName( "UTF-8" )));

			httpPost.setEntity(reqEntity);
			HttpResponse response = httpclient.execute(httpPost);
			System.out.println("output:"+EntityUtils.toString(response.getEntity()));
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}

	@RequestMapping(value="upload", method = RequestMethod.POST)
    public String handleFileUpload(
            @RequestParam(value="file") MultipartFile file,
            @RequestParam(value="folder") String folder,
            ModelMap model){
		String fileLocation = "c:\\uploadDestination\\" + folder + "\\" + file.getOriginalFilename();
		
		String message = null;
        try {
            byte[] bytes = file.getBytes();
            BufferedOutputStream stream =
                    new BufferedOutputStream(new FileOutputStream(new File(fileLocation)));
            stream.write(bytes);
            stream.close();
        	message = "Upload succeeded";
        } catch (Exception e) {
        	message = "Upload failed";
        	e.printStackTrace();
        }
		model.addAttribute("message", message);
		return "message";  //Spring uses InternalResourceViewResolver and return back message.jsp
    }
}

We will test this uploader with some test files. Add a file in your C Drive, with the location “C:\uploadSource\test.txt”. Add some characters to the file and save it.

Then, create a dummy upload directory, “C:\uploadDestination”.

To test, restart the server:


From Git Bash, run 'mvn eclipse:eclipse -Dwtpversion=2.0'
From Eclipse, right click the project->Refresh (or F5)
From Eclipse Server Tab, right click the Server->Stop
From Eclipse Server Tab, right click the Server->Clean
From Eclipse Server Tab, right click the Server->Start

Right click the Loader class, Run As, Java Application. You should see the following output:


output:<html>
<body>
<h2>Message Page</h2>

<h4>Message : Upload succeeded</h1>	
</body>
</html>

In addition, if the POST was successful, you should see the copied “test.txt” file in the “C:\uploadDestination” directory.

Good luck and have fun!