Antes de empezar

1

Pasos para aprender Java Spring

2

¿Java sigue siendo gratuito?

3

Instalación de ambiente de desarrollo: Linux Ubuntu

4

Instalación de ambiente de desarrollo: macOS

5

Instalación de ambiente de desarrollo: Windows

Introducción a Spring boot

6

¿Qué es y qué usaremos de Spring?

7

Conocer qué es una aplicación autocontenida

8

Crear nuestra aplicación con Spring Initializr

9

Hola mundo con Spring Boot

10

Configurar Spring Boot

11

Crear la estructura del proyecto

Spring Data

12

¿Qué es JPA?

13

Conocer qué es Spring Data

14

Conectar la base de datos a nuestra aplicación

15

Mapear las tablas como clases

16

Crear Entity cuando su clave primaria es compuesta

17

Mapear relaciones entre clases

18

Usar la interface CrudRepository

19

Query Methods

Construyendo nuestra API

20

Implementar la anotación @Repository

21

¿Qué es el patrón Data Mapper y qué resuelve?

22

Orientar nuestra API al dominio con MapStruct

23

Orientar nuestro repositorio a términos del dominio

24

Inyección de dependencias

25

Implementar la anotación @Service

26

Implementar la anotación @RestController

27

Exponer nuestra API

Mejorando nuestra API

28

Controlar las respuestas HTTP

29

Crear el dominio de compras

30

Mapear el dominio de compras

31

Crear el repositorio de compras

32

Probando nuestros servicios de compras

33

Documentar nuestra API con Swagger

Spring Security

34

Configurar la seguridad de nuestra API con Spring Security

35

Generar un JWT

36

Autenticación con JWT

37

Autorización con JWT

Despliegue de nuestra aplicación

38

Desplegar nuestra API desde la ventana de comandos

39

Desplegar nuestra base de datos con Heroku

40

Desplegar nuestra API con Heroku

41

Conclusiones y despedida del curso

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso de Java Spring

Curso de Java Spring

Alejandro Ramírez

Alejandro Ramírez

Controlar las respuestas HTTP

28/41
Recursos

Aportes 14

Preguntas 10

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Desde la versión 5 de Spring existe el siguiente método static en ResponseEntity.

ResponseEntity.of(productService.getProduct(productId))

Uno puede usar la anterior línea como alternativa a las líneas 26, 27 y 28.

HttpStatus with cat
https://http.cat/

porque un not found en vez de un no content???

En el método delete, si no quieren usar if y else, también pueden usar el operador ternario:

@DeleteMapping("/delete/{id}")
public ResponseEntity delete(@PathVariable("id") int productId) {
    return new ResponseEntity(this.productService.delete(productId)
            ? HttpStatus.OK
            : HttpStatus.NOT_FOUND);
}

Me funcionan todos los métodos excepto el getByCategory, cuando no encuentra los productos de una categoría retorna Status 200 OK.
Aquí dejo el código:

	@GetMapping("/category/{categoryId}")
	public ResponseEntity<List<Product>> getByCategory(@PathVariable("categoryId") int categoryId){
		return productService.getByCategory(categoryId)
				.map(products -> new ResponseEntity<>(products,HttpStatus.OK))
				.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
	}```

Justo hice una consulta en la clase anterior, pero después de terminar la clase me parece que tiene mucho sentido diferenciar la creación de la actualización del producto.

 @PutMapping()
    public ResponseEntity<Product> create(@RequestBody Product product) {
        return new ResponseEntity<>(productService.save(product), HttpStatus.CREATED);
    }

    @PostMapping()
    public ResponseEntity<Product> update(@RequestBody Product product) {
        return new ResponseEntity<>(productService.save(product), HttpStatus.OK);
    }

¿Alguien ha notado que cuando se hace un request que devuelve una lista y esta no tiene elementos, igual devuelve status 200?

Por ejemplo si haces un request a /products/category/583 (la categoría 583 no existe) igual devuelve status 200 y debería devolver 404

Una forma un poco más elegante de definir el delete:

@DeleteMapping("/{id}")
public ResponseEntity delete(@PathVariable("id") int productId) {
    return productService.delete(productId) ?
            new ResponseEntity<>(HttpStatus.NO_CONTENT) :
            new ResponseEntity<>(HttpStatus.NOT_FOUND);
}

Las peticiones en spring cómo funcionan? cada petición es única y se atiende de forma personalizada, pero Spring puede atender múltiples de peticiones únicas al mismo tiempo ?, espero pueda darme a entender

Una observacion, cuando se consulta a la base de datos y se desea obtener una lista de producto por categoria y la categoria no existe entonces se devuelve una lista vacía, entonces, al hacer el map or else nunca entra al or else porque En el Optional si está presenta la lista, solo que está vacía, entonces aunque la categoria no exista siempre devolverá estatus OK -> 200.

Yo lo hice asi:

    @GetMapping("/category/{id}")
    public ResponseEntity<List<Product>> getByCategory(@PathVariable("id") int categoryId){
    	
    	List<Product> products = productService.getByCategory(categoryId).orElse(null);
    	
        return products != null && !products.isEmpty() ?
        				new ResponseEntity<>(products, HttpStatus.OK)
        				: new ResponseEntity<List<Product>>(HttpStatus.NOT_FOUND);
    }

De esta manera puede quedar algo mas limpio el delete.

@DeleteMapping("/delete/{id}")
    public ResponseEntity delete(@PathVariable("id") int id){
        ResponseEntity response = productService.delete(id) ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
        return  response;
    }

ResponseEntity esta muy completo y puedes usarlo de varias formas, explora escribiendo ResponseEntity. + ctrl

return ResponseEntity.of(Optional.ofNullable(productService.getAll()));
        
return ResponseEntity.ok().body(productService.getAll());
        
return ResponseEntity.status(HttpStatus.OK).body(productService.getAll());
        
return new ResponseEntity<>(productService.getAll(), HttpStatus.OK);

En lo personal me gusta más esta ya que te responde un HttpStatus y el body

return ResponseEntity.status(HttpStatus.OK).body(productService.getAll());

Para el endpoint DELETE se puede evitar el condicional ELSE.

Si se cumple la condición, se retornará OK, si no se cumple, se retornará NOT_FOUND sin problemas.

if (productService.delete(productId)) return new ResponseEntity<>(HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);

Yo cree el metodo para actualizar pero aún no estoy muy convencido de si esta bien. Me podrían dar feedback

@PutMapping(value = "/update/{productId}")
public ResponseEntity<Product> update(@PathVariable("productId") long productId, @RequestBody Product product){
    if (productService.getProduct(productId) == null){
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }else{
        return new ResponseEntity<>(productService.update(product), HttpStatus.OK);
    }
}