I tried Angular tutorial + SpringBoot + PostgreSQL

Angular + SpringBoot + PostgreSQL

Introduction

Frontend: Angular (TypeScript) Backend: Spring Boot (Java) DB: PostgreSQL

With reference to this article, I tried to make what the title says. Angular tutorial + I tried Spring Boot

Prerequisites

You have created a project with Spring Initializer Created with Maven Project Dependencies include postgreSQL Driver and Lombok.

The name is appropriate

environment

This article is done on Mac, but it works fine on Windows. (7 has been confirmed, but 10 does not know)

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.2
BuildVersion:   19C57

% osascript -e 'version of app "IntelliJ IDEA"'   
2019.3.1

% java --version
java 11.0.4 2019-07-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.4+10-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.4+10-LTS, mixed mode)

 % postgres --version
postgres (PostgreSQL) 12.1

% ng --version
Angular CLI: 8.3.4
Node: 11.12.0
OS: darwin x64
Angular: 
... 

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.803.4
@angular-devkit/core         8.3.4
@angular-devkit/schematics   8.3.4
@schematics/angular          8.3.4
@schematics/update           0.803.4
rxjs                         6.4.0

PostgreSQL We will proceed on the assumption that PostgreSQL is already installed. This time I'm using a schema.

Schema creation & table creation

CREATE SCHEMA tutorial
CREATE TABLE tutorial.heroes(
    id INT,
    name VARCHAR(64)
)

Insert mock data

INSERT INTO tutorial.heroes VALUES
(1, 'captain America'),
(2, 'Ironman'),
(3, 'Hulk'),
(4, 'Thor Odinson'),
(5, 'Black Widow'),
(6, 'Hawkeye'),
(7, 'Wijon'),
(8, 'Scarlet witch'),
(9, 'Falcon'),
(10, 'War machine'),
(11, 'Captain Marvel');

Now PostgreSQL is ready.

Angular We will proceed on the assumption that all Angular Tutorial has been completed.

Service class

Change the service class heroUrl to the URL of the REST API.

hero.service.ts


...
//Abbreviation

export class HeroService {
// private heroesUrl = 'api/heroes';  //Web API URL
  private heroesUrl = 'http://localhost:8080'; // <=Add here

  httpOptions = {
    headers: new HttpHeaders({ "Content-Type": "application/json" })
  };

  constructor(
    private http: HttpClient,
    private messageService: MessageService
  ) {}

//Abbreviation
...

app.module.ts

Because I actually hit the API instead of mocking to get the data Comment out the HttpClientInMemoryWebApiModule that behaves like an API server.

app.module.ts


@NgModule({
  declarations: [
    AppComponent,
    HeroesComponent,
    HeroDetailComponent,
    MessagesComponent,
    DashboardComponent,
    HeroSearchComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule
    // HttpClientInMemoryWebApiModule.forRoot(
    //   InMemoryDataService, { dataEncapsulation: false }
    // )
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

Hero component

heroes.component.ts


add(name: string): void {
    name = name.trim();
    //↓ Add 1 to the last element as the ID of the new hero
    let id = this.heroes.slice(-1)[0].id + 1;
    if (!name) { return; }
    //Add id and pass arguments as Hero
    this.heroService.addHero({ name, id } as Hero)
      .subscribe(hero => {
        this.heroes.push(hero);
      });
  }

This concludes the Angular changes.

Backend side (Java)

Hero class Create a hero class to define the hero type. Since I am using Lombok, I don't need setters and getters. (In Intellij you need to put lombok in Plugin)

Hero.java


package tutorial.tutorial.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@AllArgsConstructor
@Data
@NoArgsConstructor
@ToString
public class Hero {
    private Integer id;
    private String name;
}

HeroDAO class Create a DAO class to access the database. Create all CRUD processing.

HeroDAO.java


package tutorial.tutorial.model;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class HeroDAO {

    /**
     *Method to establish DB connection information
     *
     * @return conn connection information
     */
    public Connection getConnection() throws ClassNotFoundException, SQLException {
        //Prepare variables to store Connection information
        Connection conn = null;
        //Initialization
        Class.forName("org.postgresql.Driver");
        //Enter DB information
        conn = DriverManager.getConnection("jdbc:postgresql://localhost/postgres?currentSchema=tutorial", "postgres", "postgres");
        //Disable autocommit
        conn.setAutoCommit(false);
        //Returns connection information
        return conn;
    }

    /**
     *Method to get and return all Hero
     *
     * @return heroes Hero type list
     */
    public List<Hero> findAll() throws ClassNotFoundException, SQLException {
        //Variable preparation for storing Connection information
        Connection conn = null;
        //For storing instances of dto class
        List<Hero> heroes = new ArrayList<>();


        //Connect to database
        try {
            conn = getConnection();
            //Object creation for executing SQL statements
            Statement pstmt = conn.createStatement();
            //Issuing a SELECT statement
            String sql = "SELECT * FROM tutorial.heroes";
            //Get the execution result of SQL statement (value received from DB)
            ResultSet rs = pstmt.executeQuery(sql);

            //Repeat the value received from DB for each record
            while (rs.next()) {
                // Hero(DTO)Instantiate a class
                Hero dto = new Hero();
                //Set the column id value
                dto.setId(rs.getInt("id"));
                //Set the value of column name
                dto.setName(rs.getString("name"));
                //Store instance in List
                heroes.add(dto);
                //Go to the next record processing with a while statement(if there is)
            }
            //Error catch statement
        } catch (SQLException e) {
            e.printStackTrace();
            //Processing to be executed regardless of whether an exception occurs
        } finally {
            //If the contents of conn are included, disconnect the db connection
            if (conn != null) {
                conn.close();
            }
        }
        //Returns a List of instances of the DTO class
        return heroes;
    }


    /**
     *Method to get and return Hero that matches id received by argument
     *
     * @param id
     * @return selectedHero
     */
    public Hero findOneHero(int id) throws ClassNotFoundException, SQLException {
        Connection conn = null;
        Hero selectedHero = new Hero();

        //Connect to database
        try {
            conn = getConnection();
            //Issuing a SELECT statement
            String sql = "SELECT * FROM tutorial.heroes WHERE id = ?";

            //Object creation for executing SQL statements
            PreparedStatement pstmt = conn.prepareStatement(sql);

            //Set the id received as an argument in the placeholder.
            pstmt.setInt(1, id);

            //Get the execution result of SQL statement (value received from DB)
            ResultSet rs = pstmt.executeQuery();

            //Set the value received from DB to dto.
            while (rs.next()) {
                // Hero(DTO)Instantiate a class
                Hero dto = new Hero();
                //Set the column id value
                dto.setId(rs.getInt("id"));
                //Set the value of column name
                dto.setName(rs.getString("name"));
                //
                selectedHero = dto;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return selectedHero;
    }

    /**
     *Method to update Hero that matches id received in argument
     *
     * @param hero
     */
    public void updateHero(Hero hero) throws ClassNotFoundException, SQLException {
        Connection conn = null;
        try {
            conn = getConnection();
            String sql = "UPDATE tutorial.heroes SET name = ? WHERE id = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, hero.getName());
            pstmt.setInt(2, hero.getId());
            pstmt.executeUpdate();
            conn.commit();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
    }

    /**
     *Method to delete Hero that matches id received by argument
     *
     * @param id id of the hero you want to erase
     */
    public void deleteHero(int id) throws ClassNotFoundException, SQLException {
        Connection conn = null;
        try {
            conn = getConnection();
            String sql = "DELETE FROM tutorial.heroes WHERE id = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);
            pstmt.executeUpdate();
            conn.commit();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
    }

    /**
     *Method to INSERT new Hero with id and name received as arguments
     *
     * @param hero
     */
    public void createHero(Hero hero) throws ClassNotFoundException, SQLException {
        Connection conn = null;
        try {
            conn = getConnection();
            String sql = "INSERT INTO tutorial.heroes VALUES(?, ?)";

            //Object creation for executing SQL statements
            PreparedStatement pstmt = conn.prepareStatement(sql);

            //Set the id received as an argument in the placeholder.
            pstmt.setInt(1, hero.getId());
            pstmt.setString(2, hero.getName());

            //Get the execution result of SQL statement (value received from DB)
            pstmt.executeUpdate();
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
    }
}

HeroController class

Create a REST API. I created the following five. --GetHeroes returns all heroes --getHero to return the hero associated with id --Create a new hero create --Delete delete hero --Update hero information update

The data received according to the tutorial is set to Hero.

HeroContoller.java


package tutorial.tutorial.controller;

import org.springframework.web.bind.annotation.*;
import tutorial.tutorial.model.*;
import java.sql.SQLException;
import java.util.*;

@RestController
public class HeroController {

    /**
     *Method to receive all heroes from DAO class
     *
     * @return heroList 
     */
    @GetMapping("/")
    public List<Hero> getHeroes() throws SQLException, ClassNotFoundException {
        HeroDAO dao = new HeroDAO();
        List<Hero> heroes = dao.findAll();
        List<Hero> heroList = new ArrayList<>();
        heroList.addAll(heroes);
        return heroList;
    }

    /**
     *Method to receive hero associated with id from DAO class
     *
     * @param id
     * @return hero
     */
    @GetMapping("/{id}")
    public Hero getHero(@PathVariable Integer id) throws SQLException, ClassNotFoundException {
        HeroDAO dao = new HeroDAO();
        Hero hero = dao.findOneHero(id);
        return hero;
    }

    /**
     *Method to INSERT with received id and name in DAO class
     *
     * @param newHero
     * @return hero
     */
    @PostMapping("/")
    public Hero create(@RequestBody Hero newHero) throws SQLException, ClassNotFoundException {
        HeroDAO dao = new HeroDAO();
        dao.createHero(newHero);
        return newHero;
    }


    /**
     *Method to DELETE hero associated with id in DAO class
     *
     * @param id
     */
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Integer id) throws SQLException, ClassNotFoundException {
        HeroDAO dao = new HeroDAO();
        dao.deleteHero(id);
    }

    /**
     *Method to UPDATE hero associated with id in DAO class
     *
     * @param updatedHero
     */
    @PutMapping("/")
    public Hero update(@RequestBody Hero updatedHero) throws SQLException, ClassNotFoundException {
        HeroDAO dao = new HeroDAO();
        dao.updateHero(updatedHero);
        return updatedHero;
    }

}

CORS compatible

For security reasons, ajax etc. can only get resources from the same origin by SOP. Since the port numbers are different between Angular and Spring Boot this time, it is necessary to enable CORS in order to release the SOP only between trusted origins.

WebConfig.java


package tutorial.tutorial.config;

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.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/*")
                //Specify the port number to allow(Angular side)
                .allowedOrigins("http://localhost:3000")
                //List of allowed methods
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                //Allow headers
                .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "Accept")
                .allowCredentials(false).maxAge(3600);
    }
}

Execute

Let's run TutorialApplication and Angular. You can confirm that the API is called and the DB is being operated.

Summary

In order to understand what the web application looks like, I made an exchange using Angular, which is closely related to Ionic, as the front end, Spring Boot as the back end, and PostgreSQL as the database. ..

Recommended Posts

I tried Angular tutorial + SpringBoot + PostgreSQL
[I tried] Spring tutorial
I tried the Docker tutorial!
I tried the VueJS tutorial!
I tried UPSERT with PostgreSQL.
I tried using OnlineConverter with SpringBoot + JODConverter
I started Angular
I tried Spring.
I tried tomcat
I tried youtubeDataApi.
I tried refactoring ①
I tried FizzBuzz.
I tried JHipster 5.1
I tried running Autoware
I tried using Gson
I tried QUARKUS immediately
I tried using TestNG
I tried Spring Batch
I tried using Galasa
I tried node-jt400 (Programs)
I tried node-jt400 (execute)
I tried node-jt400 (Transactions)
I tried node-jt400 (Environment construction)
I tried DI with Ruby
I tried node-jt400 (IFS write)
I tried node-jt400 (SQL Update)
I tried using azure cloud-init
I tried Spring State machine
I tried Drools (Java, InputStream)
I tried Rails beginner [Chapter 1]
I tried using Apache Wicket
I tried node-jt400 (SQL query)
I tried using Java REPL
I tried source code analysis
I tried the FizzBuzz problem
I tried node-jt400 (SQL stream)
I tried node-jt400 (IFS read)
I tried putting XcodeGen + SwiftPM
I tried Rails beginner [Chapter 2]
I tried BIND with Docker
I tried to verify yum-cron
I tried Jets (ruby serverless)
I tried metaprogramming in Java
Rails Tutorial Extension: I tried to create an RSS feed function