Spring JPA + PostgreSQL + AngularJS example | Spring Boot

In this tutorial, JavaSampleApproach shows you a Spring Boot example that uses Spring JPA to interact with PostgreSQL and AngularJS as a front-end technology to make request and receive response.

Related Posts:
How to use Spring JPA with PostgreSQL | Spring Boot
How to integrate Http Angularjs with Spring MVC | Spring Boot
Angular 4 + Spring JPA + PostgreSQL example | Angular 4 Http Client – Spring Boot RestApi Server

I. Overview

1. Goal

spring-jpa-postgresql-angularjs-structure

We’ll build a Spring Boot Application in that:
REST Service provides interface for interacting with Customer Database (PostgreSQL) using Spring JPA.
– By using AngularJS to make HTTP request to REST Service and receive response, UI can save Customer Data (id, firstName, lastName), retrieves and displays:
+ All Customers in database.
+ Customer Data by customerId.
+ Customers List by lastName.

2. Technology

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.4.RELEASE
– Spring Boot: 1.5.4.RELEASE

3. Project Structure

spring-jpa-postgresql-angularjs-project-structure

Our Application has 2 main parts: REST Service & UI
REST Service:
+ Customer Class corresponds to entity and table customer, it should be implemented Serializable.
+ CustomerRepository is an interface extends CrudRepository, will be autowired in CustomerController for implementing repository methods and custom finder methods.
+ CustomerController is a REST Controller which has request mapping methods for RESTful requests such as:
/postcustomer, /findall, /customer/{id}, /findByLastName.
+ Configuration for Spring Datasource and Spring JPA properties in application.properties.
+ Response class defines structure for returned data of HTTP GET.

To understand deeply the code about JPA that uses in this example, please visit:
How to use Spring JPA with PostgreSQL | Spring Boot

UI: uses AngularJS for HTTP POST/GET requests:
+ home.jsp contains elements for POST/GET request and display results.
+ controller() and $http.get()/$http.post() methods in angular.js Javascript file.
+ WebController maps url to home.jsp page.

Simpler example that uses AngularJS HTTP POST/GET:
How to integrate Http Angularjs with Spring MVC | Spring Boot

– Configuration for JSP page and static resources in application.properties
– Dependencies for Spring JPA, WEB MVC, PostgreSQL, Tomcat in pom.xml

To know how to make application work with JSP page and static resources, please visit:
How to start with JSP page and static resource in Spring Boot

II. Practice

1. Create Spring Boot project

– Using Spring Tool Suite/Eclipse to create Project (WAR packaging), ServletInitializer and SpringBootApplication class will be created automatically.
– Add Dependencies to pom.xml file:


	org.springframework.boot
	spring-boot-starter-data-jpa



	org.springframework.boot
	spring-boot-starter-web



	org.postgresql
	postgresql
	runtime



	org.springframework.boot
	spring-boot-starter-tomcat
	provided



	org.apache.tomcat.embed
	tomcat-embed-jasper
	provided

2. Create Data Model Class
package com.javasampleapproach.angularjpapostgresql.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "customer")
public class Customer implements Serializable {

	private static final long serialVersionUID = -3009157732242241606L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

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

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

	protected Customer() {
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	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 Customer(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}

	@Override
	public String toString() {
		return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
	}
}
3. Create Message Model Class
package com.javasampleapproach.angularjpapostgresql.message;

public class Response {
	private String status;
	private Object data;

	public Response() {

	}

	public Response(String status, Object data) {
		this.status = status;
		this.data = data;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
}
4. Create Repository Class
package com.javasampleapproach.angularjpapostgresql.repo;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

import com.javasampleapproach.angularjpapostgresql.model.Customer;

public interface CustomerRepository extends CrudRepository {
	List findByLastName(String lastName);
}
5. Create Controller Classes
package com.javasampleapproach.angularjpapostgresql.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
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.RestController;

import com.javasampleapproach.angularjpapostgresql.message.Response;
import com.javasampleapproach.angularjpapostgresql.model.Customer;
import com.javasampleapproach.angularjpapostgresql.repo.CustomerRepository;

@RestController
public class CustomerController {

	@Autowired
	CustomerRepository repository;

	@RequestMapping(value = "/postcustomer", method = RequestMethod.POST)
	public void postCustomer(@RequestBody Customer customer) {

		repository.save(new Customer(customer.getFirstName(), customer.getLastName()));
	}

	@RequestMapping("/findall")
	public Response findAll() {

		Iterable customers = repository.findAll();

		return new Response("Done", customers);
	}

	@RequestMapping("/customer/{id}")
	public Response findCustomerById(@PathVariable("id") long id) {

		Customer customer = repository.findOne(id);

		return new Response("Done", customer);
	}

	@RequestMapping("/findbylastname")
	public Response findByLastName(@RequestParam("lastName") String lastName) {

		List customers = repository.findByLastName(lastName);

		return new Response("Done", customers);
	}
}
package com.javasampleapproach.angularjpapostgresql.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class WebController {

	@RequestMapping("/")
	ModelAndView home(ModelAndView modelAndView) {

		modelAndView.setViewName("home");

		return modelAndView;
	}
}
6. Configuration for Datasource, JPA, JSP page, resources

Add these lines to application.properties file (assume that you use testdb database with username postgres and password 123:

spring.datasource.url=jdbc:postgresql://localhost/testdb
spring.datasource.username=postgres
spring.datasource.password=123
spring.jpa.generate-ddl=true

spring.mvc.view.prefix = /WEB-INF/jsps/
spring.mvc.view.suffix = .jsp
7. Add JSP Page and Javascript File

Under src/main/webapp/WEB-INF/jsps folder, add:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>




Spring Boot Example







	

AngularJS - Spring JPA - PostgreSQL

{{postResultMessage}}

All Customers

  • Customer {{$index}}
    Id: {{customer.id}}
    First Name: {{customer.firstName}}
    Last Name: {{customer.lastName}}

{{getResultMessage}}

Customer by ID


Id: {{customer.data.id}}
First Name: {{customer.data.firstName}}
Last Name: {{customer.data.lastName}}

{{getResultMessage}}

Customers by LastName


  • Customer {{$index}}
    Id: {{customer.id}}
    First Name: {{customer.firstName}}
    Last Name: {{customer.lastName}}

{{getResultMessage}}

Under src/main/webapp/js folder, add:

var app = angular.module('app', []);

app.controller('postController', function($scope, $http, $location) {
	$scope.submitForm = function(){
		var url = $location.absUrl() + "postcustomer";
		
		var config = {
                headers : {
                    'Content-Type': 'application/json;charset=utf-8;'
                }
        }
		
		var data = {
            firstName: $scope.firstname,
            lastName: $scope.lastname
        };
		
		
		$http.post(url, data, config).then(function (response) {
			$scope.postResultMessage = "Sucessful!";
		}, function (response) {
			$scope.postResultMessage = "Fail!";
		});
		
		$scope.firstname = "";
		$scope.lastname = "";
	}
});

app.controller('getallcustomersController', function($scope, $http, $location) {
	
	$scope.showAllCustomers = false;

	$scope.getAllCustomers = function() {
		var url = $location.absUrl() + "findall";

		var config = {
			headers : {
				'Content-Type' : 'application/json;charset=utf-8;'
			}
		}

		$http.get(url, config).then(function(response) {

			if (response.data.status == "Done") {
				$scope.allcustomers = response.data;
				$scope.showAllCustomers = true;

			} else {
				$scope.getResultMessage = "get All Customers Data Error!";
			}

		}, function(response) {
			$scope.getResultMessage = "Fail!";
		});

	}
});

app.controller('getcustomerController', function($scope, $http, $location) {
	
	$scope.showCustomer = false;
	
	$scope.getCustomer = function() {
		var url = $location.absUrl() + "customer/" + $scope.customerId;

		var config = {
			headers : {
				'Content-Type' : 'application/json;charset=utf-8;'
			}
		}

		$http.get(url, config).then(function(response) {

			if (response.data.status == "Done") {
				$scope.customer = response.data;
				$scope.showCustomer = true;

			} else {
				$scope.getResultMessage = "Customer Data Error!";
			}

		}, function(response) {
			$scope.getResultMessage = "Fail!";
		});

	}
});

app.controller('getcustomersbylastnameController', function($scope, $http, $location) {
	
	$scope.showCustomersByLastName = false;
	
	$scope.getCustomersByLastName = function() {
		var url = $location.absUrl() + "findbylastname";

		var config = {
			headers : {	'Content-Type' : 'application/json;charset=utf-8;' },
		
			params: { 'lastName' : $scope.customerLastName }
		}

		$http.get(url, config).then(function(response) {

			if (response.data.status == "Done") {
				$scope.allcustomersbylastname = response.data;
				$scope.showCustomersByLastName = true;

			} else {
				$scope.getResultMessage = "Customer Data Error!";
			}

		}, function(response) {
			$scope.getResultMessage = "Fail!";
		});

	}
});
8. Run & Check Result

– Config maven build:
clean install
– Run project with mode Spring Boot App.
– Open Browser, enter URL:
http://localhost:8080/
spring-jpa-postgresql-angularjs-demo

– Fill Form to Post Customer Data & press Submit button.
Then press Get All Customers button:
spring-jpa-postgresql-angularjs-save-customers

– Open pgAdmin III to check database:
spring-jpa-postgresql-angularjs-postgersql-db

– Find Customer by Id:
spring-jpa-postgresql-angularjs-customer-by-id

– Find Customers by Last Name:
spring-jpa-postgresql-angularjs-customer-by-last-name

III. Source Code

SpringJPAPostgreSQLAngularJS

12 thoughts on “Spring JPA + PostgreSQL + AngularJS example | Spring Boot”

  1. Can you post a sample JSON example to test the REST API part alone? An example for postCustomer (create user operation) would be great for understanding.

  2. On running above code. I got error “Consider defining a bean named ‘entityManagerFactory’ in your configuration.”. Can anyone suggest me. How to resolve this..

    2017-10-25 09:02:46.065  INFO 12128 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
    2017-10-25 09:02:46.124  WARN 12128 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerController': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customerRepository': Cannot create inner bean '(inner bean)#24f43aa3' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#24f43aa3': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
    2017-10-25 09:02:46.127  INFO 12128 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
    2017-10-25 09:02:46.168  INFO 12128 --- [           main] utoConfigurationReportLoggingInitializer : 
    
    Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
    2017-10-25 09:02:46.221 ERROR 12128 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 
    
    ***************************
    APPLICATION FAILED TO START
    ***************************
    
    Description:
    
    Field repository in com.javasampleapproach.angularjpapostgresql.controller.CustomerController required a bean named 'entityManagerFactory' that could not be found.
    
    
    Action:
    
    Consider defining a bean named 'entityManagerFactory' in your configuration.
    
    1. Hi,

      I had checked the sourcecode again.
      It works fine With SpringToolSuite and mvn commandline mvn spring-boot:run

      2017-10-25 14:21:22.437  WARN 12152 --- [           main] org.hibernate.orm.deprecation            : HHH90000014: Found use of deprecated [org.hibernate.id.SequenceGenerator] sequence-based id generator; use org.hibernate.id.enhanced.SequenceStyleGenerator instead.  See Hibernate Domain Model Mapping Guide for details.
      2017-10-25 14:21:22.620  INFO 12152 --- [           main] org.hibernate.tool.hbm2ddl.SchemaUpdate  : HHH000228: Running hbm2ddl schema update
      2017-10-25 14:21:22.683  INFO 12152 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
      2017-10-25 14:21:23.152  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3d552a9f: startup date [Wed Oct 25 14:21:19 ICT 2017]; root of context hierarchy
      2017-10-25 14:21:23.232  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/findall]}" onto public com.javasampleapproach.angularjpapostgresql.message.Response com.javasampleapproach.angularjpapostgresql.controller.CustomerController.findAll()
      2017-10-25 14:21:23.234  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/postcustomer],methods=[POST]}" onto public void com.javasampleapproach.angularjpapostgresql.controller.CustomerController.postCustomer(com.javasampleapproach.angularjpapostgresql.model.Customer)
      2017-10-25 14:21:23.235  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/customer/{id}]}" onto public com.javasampleapproach.angularjpapostgresql.message.Response com.javasampleapproach.angularjpapostgresql.controller.CustomerController.findCustomerById(long)
      2017-10-25 14:21:23.236  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/findbylastname]}" onto public com.javasampleapproach.angularjpapostgresql.message.Response com.javasampleapproach.angularjpapostgresql.controller.CustomerController.findByLastName(java.lang.String)
      2017-10-25 14:21:23.237  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto org.springframework.web.servlet.ModelAndView com.javasampleapproach.angularjpapostgresql.controller.WebController.home(org.springframework.web.servlet.ModelAndView)
      2017-10-25 14:21:23.240  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
      2017-10-25 14:21:23.241  INFO 12152 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
      2017-10-25 14:21:23.271  INFO 12152 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
      2017-10-25 14:21:23.271  INFO 12152 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
      2017-10-25 14:21:23.306  INFO 12152 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
      2017-10-25 14:21:23.480  INFO 12152 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
      2017-10-25 14:21:23.551  INFO 12152 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
      2017-10-25 14:21:23.556  INFO 12152 --- [           main] .SpringJpaPostgreSqlAngularJsApplication : Started SpringJpaPostgreSqlAngularJsApplication in 4.218 seconds (JVM running for 7.897)
      

      With SpringBoot project, entityManagerFactory will be auto-configured when having JPA dependency: spring-boot-starter-data-jpa in class path.

      So, please double check your environment and try it again with our sourcecode.

      Regards,
      JSA

      1. Hello ,

        After lot of difficulties ,I got solution for this.
        I have to delete all duplicated jars(but version is different) from repository.
        ex.hibernate-entitymanager-5.0.2.Final,jboss->jandex and so on..

        Now its perfectly running

        Thankyou

  3. A tutorial written in 2017 shouldn’t use AngularJS 1.x … That’s basically useless to any developer and basically ignored all the important developments made in Angular.

  4. Hello,

    I have a problem. When i went to this url : http://localhost:8889/, i got this :

    Whitelabel Error Page

    This application has no explicit mapping for /error, so you are seeing this as a fallback.
    Fri Jan 26 12:17:07 CET 2018
    There was an unexpected error (type=Not Found, status=404).
    No message available

    I followed ur example and in my WebController.java i respected your code and your project structure.

    Do you know how to solve this please?

    Best Regards,
    Mohamed FOFANA

    1. For fix this.

      as console, and you must have install maven:

      mvn clean install
      and

      mvn spring-boot:run

      and it works.

      Best,

  5. Ah i forgot to tell you something, i tested the other requestmapping in theCustomerController.java like /findall and its works. That’s so strange…

Leave a Reply

Your email address will not be published. Required fields are marked *