Skip to main content

How to expose Rest API's with Spring boot.

 How to expose Rest API's with Spring boot.


This will show how we can develop a spring boot project and expose Rest API.s

Three main dependencies I use here are

Web, JPA and HSQL

You can go to https://start.spring.io/ and setup either a Gradle or Maven Project. Adding the required dependencies. 

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>


<dependency>

<groupId>org.hsqldb</groupId>

<artifactId>hsqldb</artifactId>

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>



Above are the main dependencies.





The above structure is followed to separate the layers of the back end development.

Controllers, Repositories, Models, Services and DTO's  are separately packaged.

One important configuration you will need is the DB config. In this case I m using in memory HSQL db.

(Note - So no need to set up a separate Db server for this sample.   And also keep in mind that this in memory db refreshes with server restart and you will loose all the data. ).


spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.datasource.url=jdbc:hsqldb:mem:testdb;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create

 This configuration is what you need to add in your application.properties file. 

Controller

package com.example.demo.controller;

import com.example.demo.dto.UserDTO;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
UserService userService;

@GetMapping("/")
public List<UserDTO> getUsers(){

List<User> userList = userService.getAllUsers();
List<UserDTO> userDTOList = new ArrayList<>();

for(User u: userList){
UserDTO userDTO = new UserDTO(u.getId(), u.getName(), u.getAge());
userDTOList.add(userDTO);
}

return userDTOList;
}

@GetMapping("/{id}")
public UserDTO getUserById(@PathVariable String id){

try {
User user = userService.getUserById(Integer.valueOf(id));
return new UserDTO(user.getId(), user.getName(), user.getAge());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@PostMapping("/")
public UserDTO saveUser(@RequestBody UserDTO userDTO){

User savedUser = userService.saveUser(userDTO);
return new UserDTO(savedUser.getId(), savedUser.getName(),savedUser.getAge());
}

@PutMapping("/{id}")
public UserDTO updateUser(@PathVariable String id, @RequestBody UserDTO userDTO) {

try {
User user = userService.getUserById(Integer.valueOf(id));
if(user != null){
user.setName(userDTO.getName());
user.setAge(userDTO.getAge());
User savedUser = userService.saveUser(user);

return new UserDTO(savedUser.getId(), savedUser.getName(), savedUser.getAge());
}else{
throw new RuntimeException("User not found for id " + id);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;

}

@DeleteMapping("/{id}")
public String deleteUser(@PathVariable String id){
try {
userService.deleteUser(Integer.valueOf(id));
return "Delete Success";
} catch (Exception e) {
return "Delete Failed";
}
}

}


The controller exposes the rest end points to the outside world.  This contains GET, POST,PUT and DELETE and points.

According to the Rest resource naming guide the above is how you should plan the URL's.


GET All.  /user/

GET UserbyId.  /user/{id}

POST /user/     to create a new

PUT.  /user/{id}.   -  update the record with the id, with the content of the request body

DELETE. /user/{id}. 


Here we use UserDTO to pass data to and from the controller. (This keeps the model classes separated).

So even if we make a change in the DB level or Model classes, we do not have to change the other logic unless it makes an impact.

public class UserDTO {

private Integer id;
private String name;
private String age;

public UserDTO(Integer id, String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}

public UserDTO() {
}


This should have the getters and setters as well for all three fields.

@Entity(name = "user")
public class User {

@Id
private Integer id;
private String name;
private String age;

public User(Integer id, String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}

public User() {
}

The entity class maps to the database. 

import com.example.demo.model.User;
import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User, Integer> {


}

Reposiroty layer users spring JPA. 



@Service
public class UserService {

@Autowired
private UserRepository userRepository;

public User getUserById(int userId) throws Exception {
User user = userRepository.findById(userId).orElseThrow( () -> new Exception("User not found for Id" + userId));
return user;
}

public List<User> getAllUsers(){
List<User> userList = new ArrayList<>();
userRepository.findAll().forEach(userList::add);
return userList;
}

public User saveUser(UserDTO userDTO){
User savedUser = userRepository.save(new User(userDTO.getId(), userDTO.getName(), userDTO.getAge()));
return savedUser;
}

public User saveUser(User user){
return userRepository.save(user);
}

public void deleteUser(int userId) throws Exception {
try{
userRepository.deleteById(userId);
}catch (Exception e){
throw new Exception(e);
}
}


}


Service layer handles the business logic.

@SpringBootApplication
public class DemoApplication {

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}

Main Application class boots the server.


GitHub link of this repo - https://github.com/binery-code/spring-boot-rest-sample

Detailed explanation video on Youtube - Will be available soon.






















Comments

Post a Comment