You are currently viewing Angular 2 and Spring REST Simple CRUD Application

Angular 2 and Spring REST Simple CRUD Application

Angular 2 is one of the Most Popular Front End Web Framework on the internet, Spring MVC is also one of the Most Popular Application Framework on the internet, So today in this article, let’s combine/integrate these two frameworks and build a simple CRUD application.




The goal of the application is to display the list of books, adding a new book, updating the existing book, and deleting a book.

Checkout the new post on Angular 9, Spring boot and Mysql Tutorial

We will use Angular 2 in the front end for building forms, displaying the records and making HTTP calls.
In the backend, using Spring REST we will perform the CRUD operations.

Tools and Technologies Used


  • Spring 4
  • Hibernate 5
  • Angular 2
  • Bootstrap 3
  • MySQL
  • Jackson API 2.8.7
  • Maven 3.3.9
  • Eclipse Oxygen
  • Apache Tomcat 8
  • Visual Studio Code

First let’s create a DB for our application, open your MySQL and add execute the following command,




CREATE DATABASE bookdb;

Let’s start with the backend, Here is the project structure of Spring REST application
I don’t go over in detail about the REST API’s, I believe you all know that the concept of API. Long story short, API’s are nothing but URL’s when we hit those URL’s/Consume those URL’s we will get JSON data that’s it.
So let’s look at how to build such API’s using Spring REST

Since we are using a maven, first let’s add all the dependencies that are required for our application




pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.bushansirgur.spring</groupId>
  <artifactId>spring-mvc-restfull-crud</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <properties>
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </properties>

  <dependencies>
    <!-- Spring MVC Dependency -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.3.10.RELEASE</version>
    </dependency>
    <!-- Spring ORM -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>4.3.10.RELEASE</version>
    </dependency>
    <!-- Hibernate ORM -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.11.Final</version>
    </dependency>
    <!-- Hibernate-C3P0 Integration -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-c3p0</artifactId>
      <version>5.2.11.Final</version>
    </dependency>
    <!-- c3p0 -->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.2</version>
    </dependency>
    <!-- Mysql Connector -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.5</version>
    </dependency>
    <!-- Jackson API for JSON -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.8.7</version>
    </dependency>
    <!-- Servlet Dependency -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>

      <!-- Embedded Apache Tomcat required for testing web application -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Next step is to create a Property file inside the resources folder and specify the database properties
db.properties

# MySQL properties
mysql.driver=com.mysql.cj.jdbc.Driver
mysql.url=jdbc:mysql://localhost:3306/bookdb
mysql.user=root
mysql.password=

# Hibernate properties
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

#C3P0 properties
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.acquire_increment=1
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=150

Once it’s done, let’s configure the spring and hibernate. Inside the config, package create a class called AppConfig and write the following code.

We will annotate this class with @Configuration, @PropertySource, @EnableTransactionManagement and @ComponentScan




@Configuration: It is a replacement to the XML based configuration for configuring spring beans. So instead of an XML file, we write a class and annotate that with @Configuration and define the beans in it using @Bean annotation on the methods.

@PropertySource: Specify the classpath of the property file. Reading values from a property file are far superior to hard coding them in our class files. If we hard code then we need to recompile if we want to change any of them.

@EnableTransactionManagement: It enables the transaction management. @ComponentScans: To scan the multiple packages.

AppConfig.java

package com.bushansirgur.spring.config;

import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import static org.hibernate.cfg.Environment.*;

@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.bushansirgur.spring.dao"),
      @ComponentScan("com.bushansirgur.spring.service") })
public class AppConfig {

   @Autowired
   private Environment env;

   @Bean
   public LocalSessionFactoryBean getSessionFactory() {
      LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();

      Properties props = new Properties();
      // Setting JDBC properties
      props.put(DRIVER, env.getProperty("mysql.driver"));
      props.put(URL, env.getProperty("mysql.url"));
      props.put(USER, env.getProperty("mysql.user"));
      props.put(PASS, env.getProperty("mysql.password"));

      // Setting Hibernate properties
      props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));
      props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));

      // Setting C3P0 properties
      props.put(C3P0_MIN_SIZE, env.getProperty("hibernate.c3p0.min_size"));
      props.put(C3P0_MAX_SIZE, env.getProperty("hibernate.c3p0.max_size"));
      props.put(C3P0_ACQUIRE_INCREMENT, 
            env.getProperty("hibernate.c3p0.acquire_increment"));
      props.put(C3P0_TIMEOUT, env.getProperty("hibernate.c3p0.timeout"));
      props.put(C3P0_MAX_STATEMENTS, env.getProperty("hibernate.c3p0.max_statements"));

      factoryBean.setHibernateProperties(props);
      factoryBean.setPackagesToScan("com.bushansirgur.spring.model");

      return factoryBean;
   }

   @Bean
   public HibernateTransactionManager getTransactionManager() {
      HibernateTransactionManager transactionManager = new HibernateTransactionManager();
      transactionManager.setSessionFactory(getSessionFactory().getObject());
      return transactionManager;
   }
}

Next step is to create MyWebAppInitializer class to initialize the servlet container, instead of using traditional web.xml, we will use java class that will extends AbstractAnnotationConfigDispatcherServletInitializer.
MyWebAppInitializer.java

package com.bushansirgur.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import com.bushansirgur.spring.config.WebConfig;

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] { AppConfig.class };
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

Next step is to create WebConfig class inside the config package, we will annotate this class with @Configuration, @EnableWebMvc, and @ComponentScan





@EnableWebMvc: @EnableWebMvc is used to enable Spring MVC. @EnableWebMvc is equivalent to <mvc:annotation-driven /> in XML.

WebConfig.java

package com.bushansirgur.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.bushansirgur.spring.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {
	
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**");
	}
	
}

Above three files are required for the spring and hibernate configuration.

Now, let’s write the model class, create a Book class inside the model package.

Book.java

package com.bushansirgur.spring.model;

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

@Entity(name = "Book")
public class Book {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   private String title;
   private String author;

   public Long getId() {
      return id;
   }

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

   public String getTitle() {
      return title;
   }

   public void setTitle(String title) {
      this.title = title;
   }

   public String getAuthor() {
      return author;
   }

   public void setAuthor(String author) {
      this.author = author;
   }

	@Override
	public String toString() {
		return "Book [id=" + id + ", title=" + title + ", author=" + author + "]";
	}
   
   
}

Now, let’s create an Interface for DAO, we will create BookDAO interface inside the dao package

BookDao.java

package com.bushansirgur.spring.dao;

import java.util.List;

import com.bushansirgur.spring.model.Book;


public interface BookDao {

   long save(Book book);

   Book get(long id);

   List<Book> list();

   void update(long id, Book book);

   void delete(long id);

}

Now, let’s implement those methods in the BookDaoImp class and annotate this class with @Repository

@Repository: It is an annotation that marks the specific class as a Data Access Object, thus clarifying its role.




BookDaoImp.java

package com.bushansirgur.spring.dao;

import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

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

import com.bushansirgur.spring.model.Book;


@Repository
public class BookDaoImp implements BookDao {

	@Autowired
	   private SessionFactory sessionFactory;

	   @Override
	   public long save(Book book) {
	      sessionFactory.getCurrentSession().save(book);
	      return book.getId();
	   }

	   @Override
	   public Book get(long id) {
	      return sessionFactory.getCurrentSession().get(Book.class, id);
	   }

	   @Override
	   public List<Book> list() {
	      Session session = sessionFactory.getCurrentSession();
	      CriteriaBuilder cb = session.getCriteriaBuilder();
	      CriteriaQuery<Book> cq = cb.createQuery(Book.class);
	      Root<Book> root = cq.from(Book.class);
	      cq.select(root);
	      Query<Book> query = session.createQuery(cq);
	      return query.getResultList();
	   }

	   @Override
	   public void update(long id, Book book) {
	      Session session = sessionFactory.getCurrentSession();
	      Book book2 = session.byId(Book.class).load(id);
	      book2.setTitle(book.getTitle());
	      book2.setAuthor(book.getAuthor());
	      session.flush();
	   }

	   @Override
	   public void delete(long id) {
	      Session session = sessionFactory.getCurrentSession();
	      Book book = session.byId(Book.class).load(id);
	      session.delete(book);
	   }
}

Now, let’s create another Interface for service, we will be creating this service inside the service package

BookService.java

package com.bushansirgur.spring.service;

import java.util.List;

import com.bushansirgur.spring.model.Book;

public interface BookService {

	long save(Book book);

	Book get(long id);

	List<Book> list();

	void update(long id, Book book);

	void delete(long id);
}

Now, let’s implement those methods in the BookServiceImp class and annotate this with @Service

@Service: This tells hibernate it is a Service class where you will have @Transactional etc Service layer related annotations so hibernate treats it as a Service component.

BookServiceImp.java

package com.bushansirgur.spring.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bushansirgur.spring.dao.BookDao;
import com.bushansirgur.spring.model.Book;


@Service
@Transactional(readOnly = true)
public class BookServiceImp implements BookService {

   @Autowired
   private BookDao bookDao;

   @Transactional
   @Override
   public long save(Book book) {
      return bookDao.save(book);
   }

   @Override
   public Book get(long id) {
      return bookDao.get(id);
   }

   @Override
   public List<Book> list() {
      return bookDao.list();
   }

   @Transactional
   @Override
   public void update(long id, Book book) {
      bookDao.update(id, book);
   }

   @Transactional
   @Override
   public void delete(long id) {
      bookDao.delete(id);
   }
}

Finally, we will create a controller BookController inside the controller package and annotate with @RestController, which specifies that this is a REST controller




BookController.java

package com.bushansirgur.spring.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.bushansirgur.spring.model.Book;
import com.bushansirgur.spring.service.BookService;


@CrossOrigin(origins = "*")
@RestController
public class BookController {

   @Autowired
   private BookService bookService;

   /*---Add new book---*/
   @PostMapping("/book")
   public ResponseEntity<?> save(@RequestBody Book book) {
	  System.out.println("the json value of book is :::::: "+book);
      long id = bookService.save(book);
      return ResponseEntity.ok().body("New Book has been saved with ID:" + id);
   }
   
   /*---Get a book by id---*/
   @GetMapping("/book/{id}")
   public ResponseEntity<Book> get(@PathVariable("id") long id) {
      Book book = bookService.get(id);
      return ResponseEntity.ok().body(book);
   }

   /*---get all books---*/
   @GetMapping("/book")
   public ResponseEntity<List<Book>> list() {
      List<Book> books = bookService.list();
      return ResponseEntity.ok().body(books);
   }

   /*---Update a book by id---*/
   @PutMapping("/book/{id}")
   public ResponseEntity<?> update(@PathVariable("id") long id, @RequestBody Book book) {
      bookService.update(id, book);
      return ResponseEntity.ok().body("Book has been updated successfully.");
   }

   /*---Delete a book by id---*/
   @DeleteMapping("/book/{id}")
   public ResponseEntity<?> delete(@PathVariable("id") long id) {
      bookService.delete(id);
      return ResponseEntity.ok().body("Book has been deleted successfully.");
   }
}

That’s it for the backend, now we have 5 REST API’s

HTTP Method CRUD Operation Description
POST Create Create a new resource ( equivalent to SQL INSERT statement)
http://localhost:8037/spring-mvc-restfull-crud-example/book
GET Read Retrieve a resource ( equivalent to SQL SELECT statement)
http://localhost:8037/spring-mvc-restfull-crud-example/book
http://localhost:8037/spring-mvc-restfull-crud-example/book/{ID}
PUT Update Update or modify a resource ( equivalent to SQL UPDATE statement)
http://localhost:8037/spring-mvc-restfull-crud-example/book/{ID}
DELETE Delete Delete a resource ( equivalent to SQL DELETE statement)
http://localhost:8037/spring-mvc-restfull-crud-example/book/{ID}

We will consume these API’s in front end using Angular 2.

Let’s look at the front end application,

Before creating an Angular application make sure to install Node.js and npm on your machine,

First, let’s install angular CLI globally on our machine,

npm install -g @angular/cli

Create a new project,

ng new book-app

What is the purpose of the app.module.ts?
Is it to start up your application, and set the links to your other modules.
1 – Modules are the logic layers of your application. Each module is there to package things logically so that it’s easier for people to understand and maintain your application, made of several modules. For example, if you are doing a rich application, you should have a LoginModule, an AuthenticationModule, etc…
2 – You need to import things in your module so that Angular knows what it is going to use. Basically, your LoginModule will need the Angular FormModule, which might not be needed for the AuthenticationModule
3 – This leads us here: The AppModule, therefore, should only import the others modules it is linked to, and provide the services that will be needed globally. Your future LoginModule won’t need a service to be provided, but the AuthenticationModule, which will have an AuthenticationServicewill most probably do.




What is Angular Router?

Angular Router is an official Angular routing library, written and maintained by the Angular Core Team.
It’s a JavaScript router implementation that’s designed to work with Angular and is packaged as. @angular/router
First of all, Angular Router takes care of the duties of a JavaScript router:

  • it activates all required Angular components to compose a page when a user navigates to a certain URL
  • it lets users navigate from one page to another without page reload
  • it updates the browser’s history so the user can use the back and forward buttons when navigating back and forth between pages.

In addition, Angular Router allows us to:

  • redirect a URL to another URL
  • resolve data before a page is displayed
  • run scripts when a page is activated or deactivated
  • lazy load parts of our application.

Let’s start with,

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';


import { AppComponent } from './app.component';
import { BookService } from './book/book.service';
import { BookComponent } from './book/book.component';
import { AppChildComponent } from './appchild.component';
import { BookListComponent } from './book/bookList.component';
import { PageNotFoundComponent } from './others/pageNotFound.component';
import { HomeComponent } from './book/home.component';


const appRoutes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'books', component: BookListComponent },
  { path: 'addBook', component: BookComponent },
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  declarations: [
    AppComponent, BookComponent, AppChildComponent, BookListComponent, HomeComponent, PageNotFoundComponent
  ],
  imports: [
    BrowserModule, HttpModule, FormsModule,  RouterModule.forRoot(appRoutes)
  ],
  providers: [BookService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Keep in mind: At least one module and component are required to initiate Angular2 App.

Do I need app.component.ts?
Not necessary
. That is just the name of .ts file. It can be any other component. But as said at least one module and component are required to initiate Angular2 App.





app.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent{
}

app.component.html

<div style="padding:5px">
    <ul class="nav nav-tabs">
        <li routerLinkActive="active">
            <a routerLink="home">Home</a>
        </li>
        <li routerLinkActive="active">
            <a routerLink="addBook">Add Book</a>
        </li>
        <li routerLinkActive="active">
            <a routerLink="books">List of Books</a>
        </li>
    </ul>
    <br/>
    <router-outlet></router-outlet>
</div>

Now, create two folders inside the app folder, book and others

Inside the book folder, created these files,

Inside the others folder, create these files,

pageNotFound.component.ts

import { Component } from '@angular/core';

@Component({
    template: `<h1>The page you are looking for does not exist!</h1>`
})
export class PageNotFoundComponent{

}

Basically, there are three types of directives in angular2 according to documentation.

  • Component
  • Structural directives
  • Attribute directives

Component

is also a type of directive with template, styles and logic part which is the most famous type of directive among all in angular2.




  1. To register a component we use @Component meta-data annotation.
  2. A component is a directive which uses shadow DOM to create encapsulated visual behavior called components. Components are typically used to create UI widgets.
  3. A component is used to break up the application into smaller components.
  4. Only one component can be present per DOM element.
  5. @View decorator or templateurl template is mandatory in the component.

home.component.ts

import { Component } from '@angular/core';

@Component({
    template: `<h1>This is home page!</h1>`
})
export class HomeComponent{

}

bookList.component.ts

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { BookService } from './book.service';
import { Book } from './book';
import { Router } from '@angular/router';


@Component({
    selector: 'book-list',
    templateUrl: './bookList.component.html',
    styleUrls: ['./bookList.component.css']
})
export class BookListComponent implements OnInit{
    book = new Book();
    statusMessage: string;
    books: Book[];
    constructor(private _bookService: BookService,
                private _router: Router){}
    
    ngOnInit(): void {
        console.log("calling ngOnInit()::::");
        this.getBooks();
    }

    getBooks(): void{
        console.log("Inside getBooks():::::")
        this._bookService.getAllBooks()
            .subscribe((bookData) => this.books = bookData,
            (error) =>{
                console.log(error);
                this.statusMessage = "Problem with service. Please try again later!";
            }
        );
        console.log("end of getBooks():::::");
    }
}

bookList.component.html

<div class = "container">
    <table class = "table table-striped table-bordered">
        <tr style = "background: lightblue;">
            <th>ID</th>
            <th>TITLE</th>
            <th>AUTHOR</th>
        </tr>
        <tr *ngFor = "let book of books">
            <td>{{book.id}}</td>
            <td>{{book.title}}</td>
            <td>{{book.author}}</td>
        </tr>
        <tr *ngIf = "books && books.length == 0">
            <td colspan = "3">No records found!</td>
        </tr>
    </table>
</div>

bookList.component.css

td{
    text-align: center;
}
th{
    text-align: center;
}

book.ts

export class Book{
    id: string;
    title: string;
    author: string;
    constructor(){
        
    }
}

book.service.ts

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Book } from './book';

@Injectable()
export class BookService{
    
    constructor(private _httpService: Http){}

    getAllBooks(): Observable<Book[]>{
        return this._httpService.get("http://localhost:8037/spring-mvc-restfull-crud-example/book")
                .map((response: Response) => response.json())
                .catch(this.handleError);
    }

    getBookById(bookId: string): Observable<Book>{
        return this._httpService.get("http://localhost:8037/spring-mvc-restfull-crud-example/book/"+bookId)
                .map((response: Response) => response.json())
                .catch(this.handleError);
    }

    addBook(book: Book){
        let body = JSON.parse(JSON.stringify(book));
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        if(book.id){    
            return this._httpService.put("http://localhost:8037/spring-mvc-restfull-crud-example/book/"+book.id, body, options);
        }else{
            return this._httpService.post("http://localhost:8037/spring-mvc-restfull-crud-example/book", body, options);
        }
    }

    deleteBook(bookId: string){
        return this._httpService.delete("http://localhost:8037/spring-mvc-restfull-crud-example/book/"+bookId);
    }

    private handleError(error: Response){
        return Observable.throw(error);
    }
}

book.component.ts




import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {BookService} from './book.service';
import {Book} from './book';

@Component({
    selector: 'app-book',
    templateUrl: './book.component.html',
    styleUrls: ['./book.component.css']
})
export class BookComponent implements OnInit{

    books: Book[];
    statusMessage: string;
    book = new Book();
    
    constructor(private _bookService: BookService,
                private _router: Router){}

    ngOnInit(): void {
        this.getBooks();
    }

    getBooks(): void{
        this._bookService.getAllBooks()
            .subscribe((bookData) => this.books = bookData,
            (error) =>{
                console.log(error);
                this.statusMessage = "Problem with service. Please try again later!";
            }
        );
        
    }

    addBook(): void{
        this._bookService.addBook(this.book)
            .subscribe((response) => {console.log(response); this.getBooks();this.reset();},
            (error) =>{
                console.log(error);
                this.statusMessage = "Problem with service. Please try again later!";
            }
        );   
    }

    private reset(){
        this.book.id = null;
        this.book.title = null;
        this.book.author = null;
    }

    deleteBook(bookId: string){
        console.log("Inside the deleteBook()::::Book id::::"+bookId);
        this._bookService.deleteBook(bookId)
            .subscribe((response) => {console.log(response); this.getBooks();},
            (error) =>{
                console.log(error);
                this.statusMessage = "Problem with service. Please try again later!";
            });
            this.reset();
            console.log("end of deleteBook():::::::");
    }

    getBook(bookId: string){
        this._bookService.getBookById(bookId)
            .subscribe((bookData) => {this.book = bookData; this.getBooks(); }),
            (error) => {
                console.log(error);
                this.statusMessage = "Problem with service. Please try again later!";
            }
        this.reset();    
    }
}

book.component.html

<div class="container">
    <div (bookObj) = 'random($event)'>
        <form class="form-horizontal">
            <input type = "hidden" [(ngModel)] = "book.id" name = "id" /> 
            <div class="form-group">
                <label class="control-label col-sm-2">Book Title</label>
                <div class="col-sm-8">
                    <input type = "text" [(ngModel)] = "book.title" name = "title" class="form-control" />
                </div>    
            </div>
            <div class="form-group">
                <label class="control-label col-sm-2">Book Author</label>
                <div class="col-sm-8">
                        <input type = "text" [(ngModel)] = "book.author" name = "author" class="form-control" />
                </div>    
            </div>
            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-8">
                    <button (click) = "addBook()" class = "btn btn-primary">Add Book</button>
                </div>
            </div>
        </form>
    </div>
    <div>
        <table class = "table table-striped table-bordered">
            <tr style = "background: lightblue;">
                <th>ID</th>
                <th>TITLE</th>
                <th>AUTHOR</th>
                <th>ACTIONS</th>
            </tr>
            <tr *ngFor = "let book of books">
                <td>{{book.id}}</td>
                <td>{{book.title}}</td>
                <td>{{book.author}}</td>
                <td>
                    <button (click) = "getBook(book.id)" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-edit"></span></button>      
                    &nbsp;|&nbsp;
                    <button (click) = "deleteBook(book.id)" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-trash"></span></button>
                </td>
            </tr>
            <tr *ngIf = "books && books.length == 0">
                <td colspan = "4">No records found!</td>
            </tr>
        </table>
    </div>
</div>

book.component.css

td{
    text-align: center;
}
th{
    text-align: center;
}

So now first let’s run the Spring REST application, and then run the Angular application. To run the angular application, navigate to the project directory, and execute the following command,




ng serve --open

At this point, if you navigate to http://localhost:4200 (default URL), you will see this web page. If you see this webpage then congratulations you made it, if not then double check the code.


That’s it for this article, I hope this article helped you in one or the other way, do let me know how this article helped you, I will see you in the next article.




Bushan Sirgur

Hey guys, I am Bushan Sirgur from Banglore, India. Currently, I am working as an Associate project in an IT company.

This Post Has 36 Comments

  1. LFCM

    Great work here though it would be even more helpful if you also explained the database setup.

    1. Bushan Sirgur

      Hello LFCM, I have explained both front and backend. In the first part I have explained about backend using Spring REST and hibernate, that will communicate with the database.

      1. LFCM

        Got that, I mean when you are building this project for the first time how are you creating the tables/data?

        1. Bushan Sirgur

          Oh sorry about that. I forgot to create a DB. I will add that code. We will create the only database. All the tables will be created automatically, that is why we have written hibernate.hbm2ddl.auto=update in the db.properties file. This will create the tables for us and that’s the beauty of hibernate. All we need to do is create a DB that’s it.

          1. LFCM

            All good. I’d also make the suggestion that you give it a try with MySQL 8. It’s a pain and I’m having issues getting the app up and running with it. I think it would be awesome to build this out with HSQL or Postgress. MySQL is so bloated and messed up these days.

      2. Anand

        I have the basic knowledge for these fields how to develop my skill

  2. LFCM

    Here is my stack trace if you are interested….

    14-Jul-2018 00:00:26.382 WARNING [C3P0PooledConnectionPoolManager[identityToken->1hge16c9w1626fc7188ouyk|455a4819]-HelperThread-#2] com.mchange.v2.resourcepool.BasicResourcePool. com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@3e119995 — Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception:
    java.sql.SQLException: Unknown system variable ‘query_cache_size’
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:545)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:115)
    at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
    at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1936)
    at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1422)
    at com.mysql.cj.jdbc.ConnectionImpl.loadServerVariables(ConnectionImpl.java:2831)
    at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:2381)
    at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:1739)
    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:1596)
    at com.mysql.cj.jdbc.ConnectionImpl.(ConnectionImpl.java:633)
    at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:347)
    at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:219)
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:175)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:220)
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:206)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:203)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1138)
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1125)
    at com.mchange.v2.resourcepool.BasicResourcePool.access$700(BasicResourcePool.java:44)
    at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1870)
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696)

  3. Bushan Sirgur

    Hello LFCM,

    Even I don’t use much but I have created that web service with MySQL long back so it is there but in my future videos I will use HSQL or PostgreSQL.
    I am planning make video series on Angular and Spring REST, if you want to know more about it, do subscribe to our YouTube channel @ https://www.youtube.com/b2tech
    Thanks for reaching us.

  4. Deb

    Access to XMLHttpRequest at ‘http://localhost:8080/spring-mvc-restfull-crud-example/book’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

    1. Bushan Sirgur

      Hello deb.joyti77,

      You have to add @CrossOrigin at the class level.

      Thanks and Regards,
      -B2Tech Team

  5. Home Page

    I intended to send you a very small observation to say thanks the moment again on the awesome thoughts you’ve featured in this article. It has been so shockingly generous with you to provide publicly what many individuals would’ve sold for an electronic book to end up making some bucks for themselves, particularly considering the fact that you could have tried it if you ever desired. The thoughts likewise served to become a fantastic way to know that other people have the identical zeal the same as mine to see a good deal more when considering this condition. I’m certain there are millions of more pleasant times in the future for individuals that read through your website.

    1. Bushan Sirgur

      Thank you so much for valuable feedback ? I am happy that you reaching out ?

  6. bhim

    Thakew sir for the clear cut example

    1. Bushan Sirgur

      You’re welcome 🙂 If you like the post, please share it with your friends circle 🙂
      Team B2Tech

  7. kal26

    Hello Bushan, i am the same guy i asked for a query on youtube two days back. It is…

    Hi i did as per the instructions. But in console rather than a json object i am getting this,
    zone.js:3243 XHR finished loading: GET “http://localhost:8080/bookapi/api/book”.
    Can you advise me and tell me where i went wrong? The REST API is working. I checked it with postman, i am getting a ping(response).

  8. kal26

    Hello Bushan, i am getting this issue..
    Hi i did as per the instructions. But in console rather than a json object i am getting this,
    zone.js:3243 XHR finished loading: GET “http://localhost:8080/bookapi/api/book”.
    Can you advise me and tell me where i went wrong?
    REST API is working, so back-end is working. In front end the page is being loaded but the data is not being transmitted to front-end.

    1. Bushan Sirgur

      Hello… Can you please upload your project to GitHub so tht I can view th source code and tell you where it went wrong.. please don’t send project to me..

      1. kal26

        Bushan Hi. Today i checked again but instead of chrome i used an older Mozilla Firefox with firebug in it. In this the JSON object is being shown. But when i am using chrome i am not getting it. Is there a reason why this is happening. Is there some kind of setting i need to do, to get in chrome’s console?

  9. kal26

    Bushan Hi. I figured out the problem, i was not importing the packages correctly. It is working now.

  10. Mayank Chugh

    Hi Bhushan,

    Thanks for your video and such a good explanation.
    I am getting the error below while running tomcat server first time. Please help to guide me to fix the same.

    May 13, 2019 1:57:38 PM org.apache.catalina.core.AprLifecycleListener init
    WARNING: The APR based Apache Tomcat Native library failed to load. The error reported was [D:\Tomcat 9.0\bin\tcnative-1.dll: Can’t load AMD 64-bit .dll on a IA 32-bit platform]
    java.lang.UnsatisfiedLinkError: D:\Tomcat 9.0\bin\tcnative-1.dll: Can’t load AMD 64-bit .dll on a IA 32-bit platform
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(Unknown Source)
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.load0(Unknown Source)
    at java.lang.System.load(Unknown Source)
    at org.apache.tomcat.jni.Library.(Library.java:42)
    at org.apache.tomcat.jni.Library.initialize(Library.java:206)
    at org.apache.catalina.core.AprLifecycleListener.init(AprLifecycleListener.java:198)
    at org.apache.catalina.core.AprLifecycleListener.isAprAvailable(AprLifecycleListener.java:107)
    at org.apache.catalina.connector.Connector.(Connector.java:80)
    at org.apache.catalina.startup.ConnectorCreateRule.begin(ConnectorCreateRule.java:64)
    at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1173)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1431)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:567)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:608)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:306)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:491)

  11. saivinay

    I am getting the following error

    Jun 23, 2019 6:56:46 PM org.apache.tomcat.util.digester.SetPropertiesRule begin
    WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property ‘source’ to ‘org.eclipse.jst.jee.server:bookapi’ did not find a matching property.
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Server version: Apache Tomcat/8.0.36
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Server built: Jun 9 2016 13:55:50 UTC
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Server number: 8.0.36.0
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: OS Name: Windows 10
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: OS Version: 10.0
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Architecture: amd64
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Java Home: C:\Program Files\Java\jdk-11.0.2
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: JVM Version: 11.0.2+9-LTS
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: JVM Vendor: Oracle Corporation
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: CATALINA_BASE: C:\Users\saivi\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: CATALINA_HOME: C:\apache-tomcat-8.0.36
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Command line argument: -Dcatalina.base=C:\Users\saivi\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Command line argument: -Dcatalina.home=C:\apache-tomcat-8.0.36
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Command line argument: -Dwtp.deploy=C:\Users\saivi\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.VersionLoggerListener log
    INFO: Command line argument: -Dfile.encoding=Cp1252
    Jun 23, 2019 6:56:46 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
    INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jdk-11.0.2\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files/Java/jre1.8.0_201/bin/server;C:/Program Files/Java/jre1.8.0_201/bin;C:/Program Files/Java/jre1.8.0_201/lib/amd64;C:\oraclexe\app\oracle\product\11.2.0\server\bin;;C:\oraclexe\app\oracle\product\11.2.0\server\bin;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\PuTTY\;C:\Program Files\Java\jdk-11.0.2\bin;C:\Program Files\Apache Software Foundation\apache-maven\bin;C:\Program Files\Git\cmd;C:\Users\saivi\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Java\jre1.8.0_201\bin;C:\Users\saivi\AppData\Local\Programs\Python\Python37-32;C:\Users\saivi\AppData\Local\Programs\Microsoft VS Code\bin;C:\apache-maven-3.6.1\bin;C:\Users\saivi\Desktop;;.
    Jun 23, 2019 6:56:46 PM org.apache.catalina.core.JreMemoryLeakPreventionListener lifecycleEvent
    SEVERE: Failed to trigger creation of the GC Daemon thread during Tomcat start to prevent possible memory leaks. This is expected on non-Sun JVMs.
    java.lang.ClassNotFoundException: sun.misc.GC
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:315)
    at org.apache.catalina.core.JreMemoryLeakPreventionListener.lifecycleEvent(JreMemoryLeakPreventionListener.java:286)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:394)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:99)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:580)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:603)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:310)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:484)

    Jun 23, 2019 6:56:46 PM org.apache.coyote.AbstractProtocol init
    INFO: Initializing ProtocolHandler [“http-nio-8080”]
    Jun 23, 2019 6:56:46 PM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
    INFO: Using a shared selector for servlet write/read
    Jun 23, 2019 6:56:46 PM org.apache.coyote.AbstractProtocol init
    INFO: Initializing ProtocolHandler [“ajp-nio-8009”]
    Jun 23, 2019 6:56:46 PM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
    INFO: Using a shared selector for servlet write/read
    Jun 23, 2019 6:56:46 PM org.apache.catalina.startup.Catalina load
    INFO: Initialization processed in 869 ms
    Jun 23, 2019 6:56:46 PM org.apache.catalina.core.StandardService startInternal
    INFO: Starting service Catalina
    Jun 23, 2019 6:56:46 PM org.apache.catalina.core.StandardEngine startInternal
    INFO: Starting Servlet Engine: Apache Tomcat/8.0.36
    Jun 23, 2019 6:56:46 PM org.apache.catalina.loader.WebappLoader buildClassPath
    INFO: Unknown loader jdk.internal.loader.ClassLoaders$AppClassLoader@6e5e91e4 class jdk.internal.loader.ClassLoaders$AppClassLoader
    Jun 23, 2019 6:56:46 PM org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
    INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [174] milliseconds.
    Jun 23, 2019 6:56:47 PM org.apache.catalina.loader.WebappLoader buildClassPath
    INFO: Unknown loader jdk.internal.loader.ClassLoaders$AppClassLoader@6e5e91e4 class jdk.internal.loader.ClassLoaders$AppClassLoader
    Jun 23, 2019 6:56:48 PM org.apache.jasper.servlet.TldScanner scanJars
    INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
    Jun 23, 2019 6:56:48 PM org.apache.catalina.core.ApplicationContext log
    INFO: No Spring WebApplicationInitializer types detected on classpath
    Jun 23, 2019 6:56:48 PM org.apache.coyote.AbstractProtocol start
    INFO: Starting ProtocolHandler [“http-nio-8080”]
    Jun 23, 2019 6:56:48 PM org.apache.coyote.AbstractProtocol start
    INFO: Starting ProtocolHandler [“ajp-nio-8009”]
    Jun 23, 2019 6:56:48 PM org.apache.catalina.startup.Catalina start
    INFO: Server startup in 2073 ms

    1. Bushan Sirgur

      This is the first time that I am seeing this type of error. I really don’t know. Better you copy or clone it from my Github repository and try to run it.

      1. saivinay

        i tried it i am able to solve the error if i use tomcat 9 but hibernate not creating tables automatically

      2. Kamaljeet

        Hi Bushan, Could you please make Github link available to this project source code as I am unable to find it?
        Thanks!

  12. Younes

    Access to XMLHttpRequest at ‘http://localhost:8080/spring-mvc-restfull-crud-example/book’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
    I add @CrossOrigin at the class level but not resolved the problem.

  13. yinka

    hi , im following your steps but getting this error:

    Bean instantiation via factory method failed

    Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘getSessionFactory’ defined in com.yinka.spring.config.AppConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.hibernate5.LocalSessionFactoryBean]: Factory method ‘getSessionFactory’ threw exception; nested exception is java.lang.NullPointerException

  14. Muhammad Murad Iqbal

    Many thanks sir Bhushan Sirgur. Appreciate your efforts in education. Also enrolled in your udemy course.

    1. Bushan Sirgur

      Thank you so much for your valuable feedback. Please share this with yur friends and colleagues 🙂

      Team B2Tech

  15. Sam

    Hi
    I am getting the below error.

    The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

  16. Abhishek

    angular-2-and-spring-mvc-simple-crud-application
    when i try to make this application like you . then in angular 8 many of the codes are depricated. so please can you make this crud application in angular 8…

  17. Mohammed Maaz

    I’m unable to set up an application there’s no error in the tomcat as well I created a database but there’s no table created even after building the project.

    Kindly help me out please

    1. Mohammed Maaz

      I followed the steps as mentioned in the Github but nothing seems to work for me.

  18. Kwenyu

    Kindly provide a github link for this if any

Leave a Reply to kal26 Cancel reply