Spring REST+Angular JS

Okay, in this tutorial we will replace the NodeJS back end by Spring MVC. So, lets start.

Step 1. Create a web project with maven

Select the archtype as shown below and follow the steps.

maven

Step 2. Project structure

After completion of Step 1, we will have this project structure.

ps

Step 3. Populate pom.xml

Lets configure the pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.anupam</groupId>
	<artifactId>AngularSpring</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>AngularSpring Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.3.7.Final</version>
		</dependency>
		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.33</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.6.3</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.6.3</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.6.3</version>
		</dependency>
		<!-- <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> 
			<version>1.9.13</version> </dependency> -->
		<!-- Testing -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.2.2.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>2.0.31-beta</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>AngularSpring</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

pom.xml is straightforward with the comments added.

Step 4. Create the Spring bean config file [webapp/WEB-INF/spring/app-config.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
	<!-- Annotation scan -->
	<context:annotation-config />
	<context:component-scan base-package="com.anupam.*" />
	<!-- MVC -->
	<mvc:annotation-driven />
</beans>

Step 5. Create the hibernate config [webapp/WEB-INF/spring/hibernate-config.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/attendance" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
	<!-- Configuration for Hibernate/JPA -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="myDataSource" />
		<property name="packagesToScan">
			<list>
				<value>com.anupam.vo</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="connection.pool_size">30</prop>
				<prop key="connection.autoReconnect">true</prop>
				<prop key="connection.autoReconnectForPools">true</prop>
				<prop key="connection.is-connection-validation-required">true</prop>
				<prop key="hibernate.hbm2ddl.auto">validate</prop>
				<prop key="hibernate.show_sql">false</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.connection.release_mode">after_transaction</prop>
			</props>
		</property>
	</bean>
	<!-- Transaction -->
	<tx:annotation-driven transaction-manager="txManager" />
	<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref bean="sessionFactory" />
		</property>
	</bean>
</beans>

Step 6. Create web.xml [webapp/web.xml]

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
	<servlet>
		<servlet-name>myspring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/app-config.xml,/WEB-INF/spring/hibernate-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>myspring</servlet-name>
		<url-pattern>/post/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
</web-app>

Step 7. Create the controller [com.anupam.controller.PostController]

package com.anupam.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.anupam.dao.PostDAO;
import com.anupam.dao.UserDAO;
import com.anupam.uivo.PostUiVO;
import com.anupam.vo.TbPostVO;
import com.anupam.vo.TbUserVO;

@Controller
public class PostController
{
    @Autowired
    private PostDAO postDAO;

    @Autowired
    private UserDAO userDAO;

    @RequestMapping("/hello")
    @ResponseBody
    public TbUserVO sayHello()
    {
	TbUserVO user = new TbUserVO();
	user.setFirstName("Anupam");
	user.setLastName("Gogoi");
	return user;
    }

    @RequestMapping(path = "/list", method = RequestMethod.GET)
    @ResponseBody
    public List&lt;PostUiVO&gt; getPostByUser()
    {
	List&lt;PostUiVO&gt; listPost = new ArrayList&lt;&gt;();
	try
	{
	    List&lt;TbPostVO&gt; list = postDAO.getPostByUser(1);
	    if (list != null &amp;&amp; !list.isEmpty())
	    {
		for (TbPostVO p : list)
		{
		    listPost.add(new PostUiVO(p.getPostID(), p.getScrap(), p.getDate(), p.getUserVO().getEmail()));
		}
	    }
	}
	catch (Exception e)
	{
	    e.printStackTrace();
	}

	return listPost;
    }

    @RequestMapping(path = "/save", method = RequestMethod.POST)
    @ResponseBody
    public List&lt;PostUiVO&gt; savePost(
	    @RequestBody Map&lt;String, Object&gt; values) throws Exception
    {
	System.out.println("Received " + values.get("scrap"));
	String scrap = values.get("scrap").toString();
	Date date = new SimpleDateFormat("yyyy-MM-dd").parse(values.get("date").toString());

	TbPostVO postVO = new TbPostVO();
	postVO.setScrap(scrap);
	postVO.setDate(date);
	postVO.setUserVO(userDAO.getUserByID(1));
	postDAO.savePost(postVO);
	return getPostByUser();
    }

    @RequestMapping(path = "/remove/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public List&lt;PostUiVO&gt; deletePost(
	    @PathVariable("id") Integer postID) throws Exception
    {
	postDAO.deletePost(postDAO.getPostByID(postID));
	return getPostByUser();
    }
}

Step 8. Create the DAOs

com.anupam.dao.PostDAO

package com.anupam.dao;

import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.anupam.vo.TbPostVO;

public interface PostDAO
{
    @Transactional(readOnly=true)
    public List&lt;TbPostVO&gt; getPostByUser(Integer userID) throws Exception;
    
    @Transactional(readOnly=false)
    public void savePost(TbPostVO postVO)throws Exception;
    
    @Transactional(readOnly=false)
    public void deletePost(TbPostVO postVO) throws Exception;
    
    @Transactional(readOnly=true)
    public TbPostVO getPostByID(Integer postID)throws Exception;
    
}

com.anupam.dao.PostDAOImpl

package com.anupam.dao;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.anupam.vo.TbPostVO;

@Repository
public class PostDAOImpl implements PostDAO
{
    @Autowired
    private SessionFactory sf;

    @SuppressWarnings("unchecked")
    @Override
    public List&lt;TbPostVO&gt; getPostByUser(Integer userID) throws Exception
    {
	String hql = "FROM TbPostVO p WHERE p.userVO.userID = :userID";
	Query query = sf.getCurrentSession().createQuery(hql);
	query.setParameter("userID", userID);
	return query.list();
    }

    @Override
    public void savePost(TbPostVO postVO) throws Exception
    {
	sf.getCurrentSession().save(postVO);
    }

    @Override
    public void deletePost(TbPostVO postVO) throws Exception
    {
	sf.getCurrentSession().delete(postVO);

    }

    @Override
    public TbPostVO getPostByID(Integer postID) throws Exception
    {
	String hql = "FROm TbPostVO where postID = " + postID;
	return (TbPostVO) sf.getCurrentSession().createQuery(hql).uniqueResult();
    }

}

com.anupam.dao.UserDAO

package com.anupam.dao;

import org.springframework.transaction.annotation.Transactional;

import com.anupam.vo.TbUserVO;

public interface UserDAO
{
    @Transactional(readOnly=true)
    public TbUserVO getUserByID(Integer userID)throws Exception;
}

com.anupam.dao.UserDAOImpl

package com.anupam.dao;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.anupam.vo.TbUserVO;

@Repository
public class UserDAOImpl implements UserDAO
{
    @Autowired
    private SessionFactory sf;

    @Override
    public TbUserVO getUserByID(Integer userID) throws Exception
    {
	String str = "FROM TbUserVO where userID = " + userID;
	return (TbUserVO) sf.getCurrentSession().createQuery(str).uniqueResult();

    }

}

Step 9. Create UiVO [com.anupam.uivo.PostUiVO]

package com.anupam.uivo;

import java.io.Serializable;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonProperty;

public class PostUiVO implements Serializable
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private Integer postID;
    private String scrap;
    private Date date;
    private String userPosted;

    public PostUiVO()
    {
	super();
    }

    public PostUiVO(Integer postID, String scrap, Date date, String userPosted)
    {
	super();
	this.postID = postID;
	this.scrap = scrap;
	this.date = date;
	this.userPosted = userPosted;
    }

    public Integer getPostID()
    {
	return postID;
    }

    public void setPostID(Integer postID)
    {
	this.postID = postID;
    }

    public String getScrap()
    {
	return scrap;
    }

    public void setScrap(String scrap)
    {
	this.scrap = scrap;
    }

    public Date getDate()
    {
	return date;
    }

    public void setDate(Date date)
    {
	this.date = date;
    }

    public String getUserPosted()
    {
	return userPosted;
    }

    public void setUserPosted(String userPosted)
    {
	this.userPosted = userPosted;
    }

}

Step 10. Create VOs

com.anupam.vo.TbPostVO

package com.anupam.vo;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "TB_POSTS")
public class TbPostVO implements Serializable
{

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "postID", columnDefinition = "int")
    private Integer postID;

    @Basic
    @Column(name = "scrap")
    private String scrap;

    @Basic
    @Temporal(TemporalType.DATE)
    @Column(name = "date")
    private Date date;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "userID")
    private TbUserVO userVO;

    public Integer getPostID()
    {
	return postID;
    }

    public void setPostID(Integer postID)
    {
	this.postID = postID;
    }

    public String getScrap()
    {
	return scrap;
    }

    public void setScrap(String scrap)
    {
	this.scrap = scrap;
    }

    public Date getDate()
    {
	return date;
    }

    public void setDate(Date date)
    {
	this.date = date;
    }

    public TbUserVO getUserVO()
    {
	return userVO;
    }

    public void setUserVO(TbUserVO userVO)
    {
	this.userVO = userVO;
    }

}

com.anupam.vo.TbUserVO

package com.anupam.vo;

import java.io.Serializable;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "TB_USER")
public class TbUserVO implements Serializable
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "userID", columnDefinition = "int")
    private Integer userID;

    @Basic
    @Column(name = "firstName")
    private String firstName;

    @Basic
    @Column(name = "lastName")
    private String lastName;

    @Basic
    @Column(name = "login")
    private String login;

    @Basic
    @Column(name = "password")
    private String password;

    @Basic
    @Column(name = "email")
    private String email;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "userVO")
    private List&lt;TbPostVO&gt; listPost;

    public Integer getUserID()
    {
	return userID;
    }

    public void setUserID(Integer userID)
    {
	this.userID = userID;
    }

    public String getFirstName()
    {
	return firstName;
    }

    public void setFirstName(String firstName)
    {
	this.firstName = firstName;
    }

    public String getLastName()
    {
	return lastName;
    }

    public void setLastName(String lastName)
    {
	this.lastName = lastName;
    }

    public String getLogin()
    {
	return login;
    }

    public void setLogin(String login)
    {
	this.login = login;
    }

    public String getPassword()
    {
	return password;
    }

    public void setPassword(String password)
    {
	this.password = password;
    }

    public String getEmail()
    {
	return email;
    }

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

    public List&lt;TbPostVO&gt; getListPost()
    {
	return listPost;
    }

    public void setListPost(List&lt;TbPostVO&gt; listPost)
    {
	this.listPost = listPost;
    }

}

Step 11. The java scripts

webapp/js/index.app.js

 var indexApp = angular.module("indexApp", []);

webapp/js/index.controller.js

indexApp.controller('index.controller', function($scope, $http)
{
	// Initial data.
	$scope.form = {
		scrap : 'Your first post.'
	};

	
	var loadPosts = $http.get('post/list').success(function(data)
	{
		$scope.posts = data;
	});

	// Post data.
	$scope.doSubmit = function()
	{
		var formData = {
		scrap : $scope.form.scrap,
		date : '2015-10-10'
		};

		var request = $http.post('post/save', formData).success(function(data)
		{
			$scope.posts = data;
		});

	};
	// Delete.
	$scope.doDelete=function(id)
	{
		$http.delete('post/remove/' + id).success(function(data)
				{
			$scope.posts = data;
				});
	
	};
});

webapp/index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="ISO-8859-1">
		<title>Post it.</title>
		<script id="a" src="js/angular.min.js"></script>
		<script id="b" src="js/index.app.js"></script>
		<script id="c" src="js/index.controller.ng.js"></script>
	</head>
	<body ng-app="indexApp" ng-controller="index.controller"
		style="height: 134px; margin-left: 100px; margin-top: 20px; margin-right: 100px;">
		<div style="width: 80%">
			<h1 align="center">Post anything.</h1>
			<img id="monkey" src="/img/monkey.gif" style="width: 83px;" />
		</div>
		<div align="center" style="width: 100%; background-color: #E2E5F4">
			<form ng-submit="doSubmit()">
				<textarea ng-model="form.scrap"
					style="width: 30%; height: 100px; vertical-align: middle;"></textarea>
				<input type="submit" value="Post" />
				<input type="button" value="Log Out" ng-click="doLogOut()" />
			</form>
		</div>
		</br>
		<div style="width: 100%">
			<table border="1" style="width: 100%">
				<tr>
					<th style="width: 70%">Scrap</th>
					<th style="width: 10%">User</th>
					<th style="width: 10%">Date</th>
					<th style="width: 10%">Action</th>
				</tr>
				<tr ng-repeat="x in posts">
					<td style="width: 10%">
						<p>{{ x.scrap}}</p>
					</td>
					<td style="width: 10%">
						<p>{{ x.firstName}}</p>
					</td>
					<td style="width: 10%">
						<p>{{ x.date}}</p>
					</td>
					<td style="width: 10%"><input type="button" value="Delete"
						ng-click="doDelete(x.postID)" /></td>
				</tr>
			</table>
		</div>
	</body>
</html>

And that’s all. Run the program and you can have a REST application backed by Spring and AngularJS in the frontend.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s