Table of Contents

Springboot - 01. Membangun Layanan Restful API

Requirement

  1. Java LTS 17, 21 or later. Pada 2024 versi LTS terakhir versi 21.

  2. Gradle 7.5+ or Maven 3.5+

  3. IntelliJ IDEA

    You can also import the code straight into your IDE:

  4. Project Sebelumnya Springboot – 01. CRUD Restful API  

Membuat Module User

Model

models/User.java

				
					package com.ombagoes.blog.models;

import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.util.Date;

@Getter
@Entity
@Table(name = "users")
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Setter
    @Pattern(regexp = "^[\\w\\s]+$", message = "title only allow AlphaNum Char.")
    private String name;

    @Setter
    @Column(unique = true, nullable = false)
    @Email
    private String email;

    @Setter
    @Column(name= "email_verified_at")
    private String emailVerifiedAt;

    @Setter
    @Column(nullable = false)
    private String password;

    @Setter
    @Column(name= "remember_token")
    private String rememberToken;

    @CreationTimestamp
    @Column(updatable = false, name = "created_at")
    private Date createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private Date updatedAt;

    @PrePersist protected void onCreate() {createdAt = new Date();}
    @PreUpdate protected void onUpdate() {updatedAt = new Date();}

    public User(String name, String email, String password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }
}

				
			
Repository

repositories/UserRepository.java

				
					package com.ombagoes.blog.repositories;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import com.ombagoes.blog.models.User;

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
    List<User> findByEmailContaining(String email);
}

				
			
Controller

controllers/UserController.java

				
					package com.ombagoes.blog.controllers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ombagoes.blog.models.User;
import com.ombagoes.blog.repositories.UserRepository;

import jakarta.validation.Valid;

@RestController
//@RequestMapping("/users")
public class UserController {
    Map<String, Object> map = new HashMap<String, Object>();
    @Autowired
    UserRepository repository;
    

    @GetMapping("/users")
    public ResponseEntity<?> getAllUsers(@RequestParam(required = false) String email) {
        map.clear();
        try {
            List<User> data = new ArrayList<User>();
            if(email==null){
                data.addAll(repository.findAll());
            }else{
                data.addAll(repository.findByEmailContaining(email));
            }
            if (data.isEmpty()) {
                map.put("message", "Data empty");
                map.put("success", false);
                return new ResponseEntity<>(map, HttpStatus.OK);
            }
            map.put("data", data);
            map.put("success", true);
            return new ResponseEntity<>(map, HttpStatus.OK);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
    
    @PostMapping("/register")
    public ResponseEntity<?> create(@Valid @RequestBody User request, BindingResult bindingResult) {
        map.clear();
        if (bindingResult.hasErrors()) {
            List<String> exceptionalErrors= bindingResult
                .getFieldErrors()
                .stream()
                .map(x -> x.getDefaultMessage())
                .collect(Collectors.toList());
            map.put("errors", exceptionalErrors);
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
        }
        try {
            User _data = repository.save(new User(
                request.getName(),                 
                request.getEmail(),
                request.getPassword()
            ));
            map.put("data", _data);
            map.put("success", true);
            return new ResponseEntity<>(_data, HttpStatus.CREATED);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PutMapping("/user/{id}")
    public ResponseEntity<?> update(@PathVariable long id, @RequestBody User request) {
        map.clear();
        try {
            User _data = repository.findById(id).get();
            _data.setName(request.getName());
            _data.setEmail(request.getEmail());
            repository.save(_data);
            map.put("data", _data);
            map.put("success", true);
            return new ResponseEntity<>(_data, HttpStatus.OK);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
        }
    }

    @DeleteMapping("/user/{id}")
    public ResponseEntity<?> deleteUser(@PathVariable long id) {
        map.clear();        
        try {
            Optional<User> row = repository.findById(id);
            if(!row.isPresent()){
                map.put("message", "Data not found");
                map.put("success", false);
                return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
            }
            repository.deleteById(id);
            map.put("success", true);
            repository.deleteById(id);
            map.put("success", true);
            return new ResponseEntity<>(map, HttpStatus.ACCEPTED);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
        }
    }
}

				
			
End Point
  1. GET /users, menampilkan semua data user.
  2. GET /users/john, menampilkan data user berdasarkan filter email `john`.
  3. POST /user/registration, menambahkan data user baru.
  4. PUT /user/{id}, mengubah data user berdasarkan {id}.
  5. DELETE /user/{id}, menghapus data user berdasarkan {id}.

Relation One To One

Selanjutnya kita akan membuat relasi one to one antara table User dengan UserInformation. dengan menggunakan skema sbb :

Model
				
					package com.ombagoes.blog.models;

import java.util.Date;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Pattern;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Entity
@Table(name = "user_information")
@NoArgsConstructor
public class UserInformation {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Setter
    @Pattern(regexp = "^[\\w\\s]+$", message = "title only allow AlphaNum Char.")
    @Column(nullable = false)
    private String fullName;

    @Setter
    @Column(nullable = false)
    private String dateBirth;

    @Setter
    @Column(nullable = false)
    private String placeBirth;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private User user;


    @CreationTimestamp
    @Column(updatable = false, name = "created_at")
    private Date createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private Date updatedAt;

    @PrePersist protected void onCreate() {createdAt = new Date();}
    @PreUpdate protected void onUpdate() {updatedAt = new Date();}
}

				
			
Menambahkan Relasi Pada Model User
				
					public class User {
    ...
    @OneToOne(mappedBy = "user")
    private UserInformation userInformation;
    ...
}
				
			
Repository
				
					package com.ombagoes.blog.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import com.ombagoes.blog.models.UserInformation;

public interface UserInformationRepository extends JpaRepository<UserInformation, Long> {
    
}

				
			
Controller
				
					package com.ombagoes.blog.controllers;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
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 com.ombagoes.blog.models.UserInformation;
import com.ombagoes.blog.repositories.UserInformationRepository;
import jakarta.validation.Valid;

public class UserInformationController {
    Map<String, Object> map = new HashMap<String, Object>();
    @Autowired
    UserInformationRepository repository;
    
    @PostMapping("/user/{id}/information")
    public ResponseEntity<?> create(@Valid @RequestBody UserInformation request, BindingResult bindingResult) {
        map.clear();
        if (bindingResult.hasErrors()) {
            List<String> exceptionalErrors= bindingResult
                .getFieldErrors()
                .stream()
                .map(x -> x.getDefaultMessage())
                .collect(Collectors.toList());
            map.put("errors", exceptionalErrors);
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
        }
        try {
            UserInformation _data = repository.save(new UserInformation(
                request.getFullName(),                 
                request.getDateBirth(),
                request.getPlaceBirth()
            ));
            map.put("data", _data);
            map.put("success", true);
            return new ResponseEntity<>(_data, HttpStatus.CREATED);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PutMapping("/userinformation/{id}")
    public ResponseEntity<?> update(@PathVariable long id, @RequestBody UserInformation request) {
        map.clear();
        try {
            UserInformation _data = repository.findById(id).get();
            _data.setFullName(request.getFullName());
            _data.setDateBirth(request.getDateBirth());
            _data.setDateBirth(request.getPlaceBirth());
            repository.save(_data);
            map.put("data", _data);
            map.put("success", true);
            return new ResponseEntity<>(_data, HttpStatus.OK);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
        }
    }

    @DeleteMapping("/userinformation/{id}")
    public ResponseEntity<?> deleteUser(@PathVariable long id) {
        map.clear();        
        try {
            Optional<UserInformation> row = repository.findById(id);
            if(!row.isPresent()){
                map.put("message", "Data not found");
                map.put("success", false);
                return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
            }
            repository.deleteById(id);
            map.put("success", true);
            repository.deleteById(id);
            map.put("success", true);
            return new ResponseEntity<>(map, HttpStatus.ACCEPTED);
        } catch (Exception e) {
            map.put("message", e.getMessage());
            map.put("success", false);
            return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
        }
    }
}

				
			
End Point
  1. POST user/{id}/information
  2. PUT userinformation/id
  3. DELETE userinformation/id