🖍️
Developer Note
  • Welcome
  • Git
    • Eslint & Prettier & Stylelint & Husky
  • Programming Language
    • JavaScript
      • Script Async vs Defer
      • Module
      • Const VS Let VS Var
      • Promise
      • Event Loop
      • Execution Context
      • Hoisting
      • Closure
      • Event Buddling and Capturing
      • Garbage Collection
      • This
      • Routing
      • Debounce and Throttle
      • Web Component
      • Iterator
      • Syntax
      • String
      • Array
      • Object
      • Proxy & Reflect
      • ProtoType
      • Class
      • Immutability
      • Typeof & Instanceof
      • Npm (Node package manager)
    • TypeScript
      • Utility Type
      • Type vs Interface
      • Any vs Unknown vs Never
      • Void and undefined
      • Strict Mode
      • Namespace
      • Enum
      • Module
      • Generic
    • Python
      • Local Development
      • Uv
      • Asyncio & Event loop
      • Context Manager
      • Iterator & Generator
      • Fast API
      • Pydantic & Data Class
    • Java
      • Compilation and Execution
      • Data Type
      • Enumeration
      • Data Structure
      • Try Catch
      • InputStream and OutputStream
      • Concurrent
      • Unicode Block
      • Build Tools
      • Servlet
      • Java 8
  • Coding Pattern
    • MVC vs MVVM
    • OOP vs Functional
    • Error Handling
    • MVC vs Flux
    • Imperative vs Declarative
    • Design Pattern
  • Web Communication
    • REST API
      • Web Hook
      • CORS issue
    • HTTPS
    • GraphQL
      • REST API vs GraphQL
      • Implementation (NodeJS + React)
    • Server-Sent Event
    • Web Socket
    • IP
    • Domain Name System (DNS)
  • Frontend
    • Progressive Web App (PWA)
    • Single Page & Multiple Page Application
    • Search Engine Optimiaztion (SEO)
    • Web bundling & Micro-frontend
      • Webpack
        • Using Webpack to build React Application
        • Using Webpack to build react library
      • Vite
      • Using rollup to build react library
      • Implementing micro frontend
    • Web Security
      • CSRF & Nonce
      • XSS
      • Click hijacking
    • Cypress
    • CSS
      • Core
        • Box Model
        • Inline vs Block
        • Flexbox & Grid
        • Pseudo Class
        • Position
      • Tailwind CSS
        • Shadcn
      • CSS In JS
        • Material UI
    • React
      • Core
        • Component Pattern
        • React Lazy & Suspense
        • React Portal
        • Error Boundary
        • Rendering Methods
        • Environment Variable
        • Conditional CSS
        • Memo
        • Forward Reference
        • High Order Component (HOC) & Custom Hook
        • TypeScript
      • State Management
        • Redux
        • Recoil
        • Zustand
      • Routing
        • React Router Dom
      • Data Fetching
        • Axios & Hook
        • React Query
        • Orval
      • Table
        • React Table
      • Form & Validation
        • React Hook Form
        • Zod
      • NextJS
        • Page Router
        • App Router
      • React Native
    • Angular
    • Svelte
      • Svelte Kit
  • Backend
    • Cache
      • Browser Cache
      • Web Browser Storage
      • Proxy
      • Redis
    • Rate limit
    • Monitoring
      • Logging
      • Distributed Tracing
    • Load Test
    • Encryption
    • Authentication
      • Password Protection
      • Cookie & Session
      • JSON Web Token
      • SSO
        • OAuth 2.0
        • OpenID Connect (OIDC)
        • SAML
    • Payment
      • Pre-built
      • Custom
    • File Handling
      • Upload & Download (Front-end)
      • Stream & Buffer
    • Microservice
      • API Gateway
      • Service Discovery
      • Load Balancer
      • Circuit Breaker
      • Message Broker
      • BulkHead & Zipkin
    • Elastic Search
    • Database
      • SQL
        • Group By vs Distinct
        • Index
        • N + 1 problem
        • Normalization
        • Foreign Key
        • Relationship
        • Union & Join
        • User Defined Type
      • NOSQL (MongoDB)
      • Transaction
      • Sharding
      • Lock (Concurrency Control)
    • NodeJS
      • NodeJS vs Java Spring
      • ExpressJS
      • NestJS
        • Swagger
        • Class Validator & Validation Pipe
        • Passport (Authentication)
      • Path Module
      • Database Connection
        • Integrating with MYSQL
        • Sequalize
        • Integrating with MongoDB
        • Prisma
        • MikroORM
        • Mongoose
      • Streaming
      • Worker Thread
      • Passport JS
      • JSON Web Token
      • Socket IO
      • Bull MQ
      • Pino (Logging)
      • Yeoman
    • Spring
      • Spring MVC
      • Spring REST
      • Spring Actuator
      • Aspect Oriented Programming (AOP)
      • Controller Advice
      • Filter
      • Interceptor
      • Concurrent
      • Spring Security
      • Spring Boot
      • Spring Cloud
        • Resilience 4j
      • Quartz vs Spring Batch
      • JPA and Hibernate
      • HATEOS
      • Swagger
      • Unit Test (Java Spring)
      • Unit Test (Spring boot)
  • DevOp
    • Docker
    • Kubernetes
      • Helm
    • Nginx
    • File System
    • Cloud
      • AWS
        • EC2 (Virtual Machine)
        • Network
        • IAM
          • Role-Service Binding
        • Database
        • Route 53
        • S3
        • Message Queue
        • Application Service
        • Serverless Framework
        • Data Analysis
        • Machine Learning
        • Monitoring
        • Security
      • Azure
        • Identity
        • Compute Resource
        • Networking
        • Storage
        • Monitoring
      • Google Cloud
        • IAM
          • Workload Identity Federation
        • Compute Engine
        • VPC Network
        • Storage
        • Kubernetes Engine
        • App Engine
        • Cloud function
        • Cloud Run
        • Infra as Code
        • Pub/Sub
    • Deployment Strategy
    • Jenkins
    • Examples
      • Deploy NextJS on GCP
      • Deploy Spring on Azure
      • Deploy React on Azure
  • Domain Knowledge
    • Web 3
      • Blockchain
      • Cryptocurrency
    • AI
      • Prompt
      • Chain & Agent
      • LangChain
      • Chunking
      • Search
      • Side Products
Powered by GitBook
On this page
  • Introduction
  • What is REST?
  • Request
  • Response
  • Terminology
  • Serialization
  • Deserialization
  • Data Binding
  • Pre-Action
  • Situation 1
  • Situation 2
  • Situation 3
  • Exception Handling
  • Custom Exception
  • Error POJO
  • Exception Handler
  • Controller
  • Result

Was this helpful?

  1. Backend
  2. Spring

Spring REST

Introduction

What is REST?

  • Compared to traditional MVC framework, an application will be separated into different parts so as to facilitate the maintenance and different parts of application can also be coded by different framework, such as nodeJS Express, java spring

  • In order to build the communication between each parts, the api url will be called by using Http

  • Each api call should be stateless

  • The common data format will be Json, Xml

Request

  • Http Method (Get, Post, Put, Delete)

  • Header (For additional information)

  • Body (passed in Json format)

Response

  • Status Code and Protocol

  • Header

  • Body(the return value)

Terminology

  • Data Binding separate into 2 parts

Serialization

  • Convert Object into Stream (JSON is one of the form of the stream to be transfer through http call)

Deserialization

  • Convert Stream into Object

Data Binding

Pre-Action

  • Install the dependency of FastXML Jackson

 <!-- Add Jackson for JSON converters -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.5</version>
    </dependency>
  • It is a dependency that bind the json into java POJO, otherwise, application/json format will not be accepted by api end point

Situation 1

Data

{
    "name": "Tom",
    "age" : 18
}

Modal

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Student {
    private String name;
    private Integer age;
    ...
}

Situation 2

  • Json may contain another another json which have not a constant format

  • Json only contain value in string or number format, if we want convert the string into date in POJO, we need to do custom serialization and deserialization

Data

{
    theName:"Tom",
    createDate: "2020/03/02",
    rawData:{
        ...
    }
}

Modal

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Record{
    @JsonProperty("theName")
    private String name;
    private Object rawData;
    @JsonSerialize(using = CustomDateSerializer.class)
    @JsonDeserialize(using = CustomDateDeserializer.class)
    private LocalDate createDate;
    ...
}

Custom Serializer and Deserializer

public class CustomDateSerializer extends JsonSerializer<LocalDate> {

    private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
    // replace the method of serializer by converting localdate back to string
    @Override
    public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        try{
            jsonGenerator.writeString(localDate.format(formatter));
        }
        catch(Exception e){
            throw new IOException("Wrong Date Format");
        }
    }
}
public class CustomDateDeserializer extends JsonDeserializer<LocalDate> {
    private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    // replace the method of default deserializer by turning the string into localdate format
    public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        String dateStr = jsonParser.getText();
        try{}
        catch (Exception e){
            throw new IOException("Wrong Format");
        }
        return LocalDate.parse(dateStr, formatter);
    }
}

Controller

 @PostMapping(value = "/record")
  public Student postStudent(@RequestBody Record student){
      return record;
  }
//  output
//  {
//    "name" : "Tom",
//    "createDate": "02-03-2020",
//    "rawData": {
//       ... 
//     } 
//   }

Situation 3

  • Sometimes, we may need to json in string format

  • we need to make good use of object mapper from Jackson to handle that

Modal

public class Student
{
    private String name;

    private HashMap<String,String> address;

    private List<String> hobbies;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HashMap<String, String> getAddress() {
        return address;
    }

    public void setAddress(HashMap<String, String> address) {
        this.address = address;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", hobbies=" + hobbies +
                '}';
    }
}

Main

 public static void main( String[] args ) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            String json = "" +
                    "{" +
                        "\"name\" : \"Sam\", " +
                        "\"address\" : {\"room\": \"107\"}," +
                        "\"hobbies\" : [\"Football\", \"Basketball\"],"+
                        "\"gg\": \"test\""+
                    "}";
            Student student = objectMapper.readValue(json, Student.class);
            System.out.println(student.getName());
            System.out.println(student.getAddress().get("room"));
            List<String> hobbyList = student.getHobbies();
            hobbyList.stream().forEach(hobby->{
                System.out.println(hobby);
            });
            String studentJson = objectMapper.writeValueAsString(student);
            System.out.println(student);
            System.out.println(studentJson);
        }
        catch (Exception e){
            System.out.println("msg: " +e.getMessage());
        }
    }
    
// Output:
// Sam
// 107
// Football
// Basketball
// Student{name='Sam', address={room=107}, hobbies=[Football, Basketball]}
// {"name":"Sam","address":{"room":"107"},"hobbies":["Football","Basketball"]}

Exception Handling

  • In some of the case, such as: the object cannot be found by using id entered by user

  • The error json should be returned in order to notice the user

Custom Exception

public class StudentNotFoundException extends RuntimeException{

    public StudentNotFoundException(String message) {
        super(message);
    }
}

Error POJO

public class ErrorResponse {
    private Integer status;
    private String message;
    private Long timeStamp;
    ...
}

Exception Handler


// This annotation is made from aop , the advice type may be around
// in order to monitor the method of the controller
@ControllerAdvice
public class RestExceptionHandler {
    // handle 2 custom types of exception
    @ExceptionHandler({StudentNotFoundException.class, DateNotMatchException.class})
    public ResponseEntity<ErrorResponse> handleException(Exception exception){
        ErrorResponse error = new ErrorResponse();
        error.setStatus(HttpStatus.NOT_FOUND.value());
        error.setMessage(exception.getMessage());
        error.setTimeStamp(System.currentTimeMillis());
        return new ResponseEntity<>(error ,HttpStatus.NOT_FOUND);
    }
}

Controller

@GetMapping("/student/{studentid}")
public ResponseEntity<Student> getStudent(@PathVariable Integer studentid, HttpServletRequest request){
    if(studentid >= studentList.size() || studentid < 0){
        throw new StudentNotFoundException("Student Not Found");
    }
    return new ResponseEntity<>(studentList.get(studentid), HttpStatus.ACCEPTED);
}

Result

PreviousSpring MVCNextSpring Actuator

Last updated 2 years ago

Was this helpful?