Creating a Hello World REST API
hitarth's Vault // Exported at - 10:14 PM
// REST API
@RestController
public class HelloWorldController {
@RequestMapping(method = RequestMethod.GET, path = "/hello-world")
public String helloWorld() {
return "Hello World";
}
}
another better way of doing this is using the @GetMapping
:
// REST API
@RestController
public class HelloWorldController {
@GetMapping(path = "/hello-world")
public String helloWorld() {
return "Hello World";
}
}
// path parameters
@GetMapping(path = "hello-world/path-variable/{name}")
public HelloWorldBean helloWorldPathVariable(@PathVariable String name) {
return new HelloWorldBean("Path Variable: " + name);
}
Using String.format
:
First we create the User object :
This is a user bean, we want to build a REST API around this user bean. Now, to be able to perform operations on something that is stored in the data base we'll create the DAO Object i.e Data Access Object.
To manage the resources, we'll create another file named UserResorce.java
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
return service.retrieveUser(id);
}
public User retrieveUser( int id) {
// either use for loop to iterate through the list and find by id
// or use functional programming :
Predicate<? super User> predicate = user -> user.getId().equals(id);
return users.stream().filter(predicate).findFirst().get();
}
We'll create a usersCount
variable to add the ID automatially.
UserDaoService.java
package org.example.rest.webservices.restfulwebservices.user;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
@Component // since we want spring to manage it therefore we annotate the class as a component
public class UserDaoService {
private static List<User> users = new ArrayList<>();
private static int usersCount = 0;
static {
users.add(new User(++usersCount, "Adam", LocalDate.now()));
users.add(new User(++usersCount, "Eve", LocalDate.now()));
users.add(new User(++usersCount, "Jim", LocalDate.now()));
}
public List<User> findAll() {
return users;
}
public User retrieveUser(int id) {
// either use for loop to iterate through the list and find by id
// or use functional programming :
Predicate<? super User> predicate = user -> user.getId().equals(id);
return users.stream().filter(predicate).findFirst().get();
}
public User save(User user) {
user.setId(++usersCount);
users.add(user);
return user;
}
}
@PostMapping("/users")
public void createUser(@RequestBody User user) {
service.save(user);
}
public User save(User user) {
user.setId(++usersCount);
users.add(user);
return user;
}
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
service.save(user);
return ResponseEntity.created(null).build(); // returns a status of 201 created, .build() builds the response entity object
}
Returning URI of the newly created user :
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
service.save(user);
// /users/4 => /users /{id} => user.getId()
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}") // to append the id to the current request
.buildAndExpand(user.getId()) // to replace the {id} with the actual id
.toUri(); // to convert it to a proper URI
return ResponseEntity.created(location).build(); // returns a status of 201 created, .build() builds the response entity object
}
public User retrieveUser(int id) {
// either use for loop to iterate through the list and find by id
// or use functional programming :
Predicate<? super User> predicate = user -> user.getId().equals(id);
return users.stream().filter(predicate).findFirst().get();
}
in the code above, if there is no element of a given ID then get()
throws an NoSuchElementException
error. If we want to return null value when no ID exists we can replace that line with : return users.stream().filter(predicate).findFirst().orElse(null);
However this is not good as well because we are still returning something which is null and the status code will be 200. We'll have to fix that :
UserResource.java
package org.example.rest.webservices.restfulwebservices.user;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import java.net.URI;
import java.util.List;
@RestController
public class UserResource {
private UserDaoService service;
public UserResource(UserDaoService service) {
this.service = service;
}
@GetMapping("/users")
public List<User> retrieveAllUsers() {
return service.findAll();
}
@GetMapping("/users/{id}")
public User retrieveUser(@PathVariable int id) {
User retrievedUser = service.retrieveUser(id);
if (retrievedUser == null) {
throw new UserNotFoundException("id: " + id);
}
else {
return retrievedUser;
}
}
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
service.save(user);
// /users/4 => /users /{id} => user.getId()
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}") // to append the id to the current request
.buildAndExpand(user.getId()) // to replace the {id} with the actual id
.toUri(); // to convert it to a proper URI
return ResponseEntity.created(location).build(); // returns a status of 201 created, .build() builds the response entity object
}
}
UserNotFoundException.java
package org.example.rest.webservices.restfulwebservices.user;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.NOT_FOUND) // to return a status of 404 not found, by default it returns 500 internal server error
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message); // pass the message to the super class, which is the RuntimeException
}
}
Video hi dekh lo bhai
If for UserNotFoundException
we wish to return a 400
bad request
then we'll do this
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id) {
User retrievedUser = service.retrieveUser(id);
if (retrievedUser == null) {
throw new UserNotFoundException("id: " + id);
}
else {
service.deleteById(id);
}
}
public void deleteById(int id) {
Predicate<? super User> predicate = user -> user.getId().equals(id);
users.removeIf(predicate);
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
// ErrorDetails errorDetails = new ErrorDetails(LocalDate.now(), ex.getMessage(), request.getDescription(false));
ErrorDetails errorDetails = new ErrorDetails(LocalDate.now(), ex.getFieldError().getDefaultMessage(), request.getDescription(false)); // → to return the message of the validation error
return new ResponseEntity(errorDetails, HttpStatus.BAD_REQUEST);
}
}
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
skipped