Spring Boot con Spring Data MongoDB
35 minIntermedio

Una API de pedidos con Spring Boot 4 y un repositorio de Spring Data que guarda en TeselaDB con TLS.
Spring Data MongoDB se conecta a la base a través del driver oficial de Java, así que tus documentos y tus repositorios funcionan con TeselaDB sin cambios. Aquí montas una API de pedidos y la conectas al clúster con TLS.
Lo que vas a construir
Una aplicación de Spring Boot 4 con un documento Order, un repositorio con una consulta derivada y un controlador con
POST /orders, GET /orders/{id} y GET /orders?customer=.
Requisitos
- Java 21 o posterior.
- Docker y
mongosh, para arrancar TeselaDB con TLS y usuarios en tu máquina.
Prepara el entorno
docker run -d --name teseladb -p 27017:27017 viuzi/teseladb:latest \
start --dbpath /data --bind_ip 0.0.0.0
until docker logs teseladb 2>&1 | grep -q '^ready'; do sleep 1; done
ROOT_PASSWORD=$(docker exec teseladb cat /data/root-credentials.txt | sed -n 's/^password=//p')
docker cp teseladb:/data/pki/ca.pem ./ca.pem
export TESELADB_URI="mongodb://root:$ROOT_PASSWORD@127.0.0.1:27017/?tls=true&tlsCAFile=./ca.pem&authSource=admin"
mongosh "$TESELADB_URI" --quiet --eval 'db.runCommand({ ping: 1 }).ok'
mongosh "$TESELADB_URI"El contenedor arranca un nodo en modo seguro y su primer arranque crea la autoridad de certificación y el usuario root
con una contraseña al azar. Las órdenes siguientes esperan a la línea ready, sacan esa contraseña y la CA y dejan en
TESELADB_URI una cadena con TLS como root. Cuando mongosh responde 1, la última línea abre la sesión de root
desde la que crearás el usuario de la aplicación.
1. Un usuario para la aplicación
db.getSiblingDB("admin").createUser({
user: "shop-api",
pwd: passwordPrompt(),
roles: [{ role: "readWrite", db: "shop" }],
});La aplicación no usa root, sino un usuario que solo lee y escribe en shop. Después, en una terminal nueva desde la
misma carpeta donde quedó ca.pem, deja su cadena en TESELADB_URI sustituyendo <contraseña> por la que acabas de
escribir. Lleva tls=true y authSource=admin, pero no tlsCAFile, porque la CA le llega a la aplicación por un
paquete SSL de Spring Boot:
export TESELADB_URI="mongodb://shop-api:<contraseña>@127.0.0.1:27017/shop?tls=true&authSource=admin"2. Crea el proyecto
Genera un proyecto Maven para Java 21 con los módulos web y Spring Data MongoDB desde start.spring.io, descomprímelo en
la carpeta orders y copia dentro la CA, que la aplicación lee desde su carpeta de trabajo:
curl -s https://start.spring.io/starter.zip -d dependencies=web,data-mongodb -d type=maven-project \
-d javaVersion=21 -d groupId=com.example -d artifactId=orders -o orders.zip
unzip orders.zip -d orders && cd orders
cp ../ca.pem .3. Conéctalo a TeselaDB
En src/main/resources/application.properties. La CA del clúster va en un paquete SSL de Spring Boot, que el cliente
de MongoDB usa como almacén de confianza. En Spring Boot 3, la propiedad de la cadena es spring.data.mongodb.uri:
spring.mongodb.uri=${TESELADB_URI}
spring.ssl.bundle.pem.teseladb.truststore.certificate=file:./ca.pem
spring.mongodb.ssl.bundle=teseladb4. Escribe el documento, el repositorio y el controlador
En src/main/java/com/example/orders/. Spring Data genera la consulta de findByCustomer a partir de su nombre:
package com.example.orders;
import java.time.Instant;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document("orders")
public record Order(@Id String id, String customer, double total, Instant createdAt) {}package com.example.orders;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface OrderRepository extends MongoRepository<Order, String> {
List<Order> findByCustomer(String customer);
}package com.example.orders;
import java.time.Instant;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/orders")
public class OrderController {
private final OrderRepository orders;
public OrderController(OrderRepository orders) {
this.orders = orders;
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Order create(@RequestBody Order order) {
return orders.save(new Order(null, order.customer(), order.total(), Instant.now()));
}
@GetMapping("/{id}")
public ResponseEntity<Order> read(@PathVariable String id) {
return ResponseEntity.of(orders.findById(id));
}
@GetMapping
public List<Order> byCustomer(@RequestParam String customer) {
return orders.findByCustomer(customer);
}
}Probarlo
Arranca la aplicación con ./mvnw spring-boot:run. Después, en otra terminal, crea un pedido de Ana con un total de 30
y búscalo por su cliente con la ruta GET /orders?customer=, que lanza la consulta derivada de findByCustomer del repositorio:
./mvnw spring-boot:run
curl -s -X POST localhost:8080/orders -H "content-type: application/json" -d '{"customer":"Ana","total":30}'
curl -s "localhost:8080/orders?customer=Ana"La segunda orden devuelve una lista con el pedido de Ana, con su id y su fecha de creación.
Limpiar
db.getSiblingDB("shop").orders.deleteMany({ customer: "Ana" });Para la aplicación con Ctrl+C y ejecuta esta orden en mongosh para borrar los pedidos de prueba, todos con Ana como
cliente. Al final borra también el contenedor con la orden de abajo: el nodo guarda los datos dentro, sin volumen, así
que con él desaparecen el usuario y los pedidos y queda libre el puerto 27017.
docker rm -f teseladb