Un entorno mal preparado es la causa número uno de frustración cuando se empieza con Spring Boot: errores de compilación que parecen del framework pero son de versión de Java, dependencias que no se descargan, o un IDE que marca en rojo un proyecto perfectamente válido. Esta lección te guía para dejar la máquina lista de forma verificable: instalar y comprobar el JDK 21, entender la elección de Maven y su wrapper, escoger IDE, disponer de herramientas para probar la API y tener Docker preparado para los módulos avanzados. Terminaremos con un checklist que puedes ejecutar tal cual.
Contenido
- El JDK 21: instalación y verificación
- Gestionar varias versiones de Java con SDKMAN!
- Maven frente a Gradle, y por qué este curso usa Maven
- El wrapper de Maven (
mvnw) - Elegir un IDE: IntelliJ IDEA, Eclipse/STS y VS Code
- Herramientas para probar la API
- Docker: requisito para los módulos posteriores
- Checklist final de verificación
- Errores Comunes y Consejos
- Ejercicios
- El JDK 21: instalación y verificación
Spring Boot 3 exige Java 17 o superior. Usaremos Java 21, la versión LTS (soporte a largo plazo) más reciente y ampliamente adoptada en producción.
Necesitas un JDK (Java Development Kit), no solo un JRE: el JDK incluye el compilador javac, sin el cual Maven no puede construir nada.
Distribuciones disponibles
Todas implementan el mismo estándar; la diferencia está en el soporte y el empaquetado.
| Distribución | Proveedor | Notas |
|---|---|---|
| Eclipse Temurin | Adoptium | La opción por defecto recomendada: gratuita, sin registro, multiplataforma |
| Amazon Corretto | AWS | Buena si despliegas en AWS; soporte largo |
| Azul Zulu | Azul Systems | Amplia cobertura de plataformas |
| Oracle JDK | Oracle | Licencia con condiciones; innecesario para aprender |
| OpenJDK de la distro | Debian, Ubuntu, Fedora | Cómodo en Linux, versión atada a la distribución |
Linux
En distribuciones basadas en Debian o Ubuntu:
# Actualizar índices e instalar el JDK 21 desde los repositorios
sudo apt update
sudo apt install openjdk-21-jdk
# Comprobar la instalación
java -version
javac -versionEn Fedora o derivadas de Red Hat:
macOS
Con Homebrew:
brew install --cask temurin@21
# Comprobar
java -version
# Ver todos los JDK instalados en el sistema
/usr/libexec/java_home -VWindows
Descarga el instalador .msi de Eclipse Temurin 21 desde adoptium.net y, durante la instalación, marca la opción "Set JAVA_HOME variable". Después, en PowerShell:
Interpretar la salida
Una instalación correcta produce algo así:
$ java -version
openjdk version "21.0.5" 2024-10-15 LTS
OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.5+11 (build 21.0.5+11-LTS, mixed mode)Fíjate en tres cosas:
21.0.5: la versión mayor es 21. Es lo único crítico.64-Bit Server VM: es una JVM de 64 bits, la que quieres.javac -versiondebe existir y coincidir. Sijavaresponde perojavacda "comando no encontrado", has instalado un JRE o falta el paquete-devel/-jdk.
La variable JAVA_HOME
Maven y muchos IDEs localizan el JDK a través de JAVA_HOME. Comprobarla:
# Linux / macOS
echo $JAVA_HOME
# Debería imprimir algo como /usr/lib/jvm/java-21-openjdk-amd64
# Si está vacía, fíjala en tu ~/.bashrc o ~/.zshrc
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
export PATH="$JAVA_HOME/bin:$PATH"
- Gestionar varias versiones de Java con SDKMAN!
Es habitual mantener proyectos con Java 8, 17 y 21 a la vez. SDKMAN! permite cambiar de versión con un comando, sin tocar variables del sistema. Funciona en Linux y macOS (en Windows, a través de WSL o Git Bash).
# Instalar SDKMAN!
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
# Ver las versiones de Java disponibles
sdk list java
# Instalar Temurin 21
sdk install java 21.0.5-tem
# Usar esa versión solo en la terminal actual
sdk use java 21.0.5-tem
# Fijarla como predeterminada del sistema
sdk default java 21.0.5-tem
# Comprobar cuál está activa
sdk current javaUn detalle muy útil: SDKMAN! reconoce un fichero .sdkmanrc en la raíz del proyecto.
Con sdk env dentro de esa carpeta, la terminal cambia automáticamente a las versiones declaradas. Es la forma más limpia de garantizar que todo el equipo compila con lo mismo.
SDKMAN! también instala Maven, Gradle y otras herramientas:
- Maven frente a Gradle, y por qué este curso usa Maven
Ambas son herramientas de construcción: descargan dependencias, compilan, ejecutan pruebas y empaquetan. Spring Boot soporta las dos con la misma calidad.
| Criterio | Maven | Gradle |
|---|---|---|
| Fichero de construcción | pom.xml (XML declarativo) |
build.gradle / build.gradle.kts (Groovy o Kotlin) |
| Curva de aprendizaje | Baja: estructura rígida y predecible | Media-alta: es un lenguaje de programación |
| Verbosidad | Alta | Baja |
| Velocidad de compilación | Buena | Mejor: caché de tareas y compilación incremental |
| Flexibilidad | Limitada, por convención | Muy alta, scripts arbitrarios |
| Documentación y ejemplos | Mayoritaria en el mundo Spring | Abundante, pero menos frecuente en tutoriales |
| Uso típico | Aplicaciones empresariales | Android, proyectos grandes o multi-módulo |
Este curso usa Maven por tres razones prácticas:
- El
pom.xmles declarativo y explícito: se lee de arriba abajo y no esconde lógica. Al aprender, eso importa más que la velocidad. - La inmensa mayoría de la documentación de Spring y de las respuestas que encontrarás usan Maven.
- Es la opción por defecto de Spring Initializr, la herramienta con la que crearás el proyecto en la lección 01-03.
Si tu empresa usa Gradle, todo lo que aprendas aquí se traslada casi literalmente: cambian la sintaxis del fichero de construcción y los nombres de las tareas, no los conceptos.
Comprobar Maven
Salida esperada:
Apache Maven 3.9.9
Maven home: /home/usuario/.sdkman/candidates/maven/current
Java version: 21.0.5, vendor: Eclipse AdoptiumObserva la última línea: Maven reporta qué JDK está usando. Si dice Java version: 17, Maven no está viendo tu JDK 21 aunque java -version sí lo diga; revisa JAVA_HOME.
- El wrapper de Maven (
mvnw)
mvnw)Aquí viene una buena noticia: no necesitas instalar Maven para seguir este curso.
Spring Initializr genera en el proyecto un wrapper: dos scripts (mvnw para Linux/macOS y mvnw.cmd para Windows) y una carpeta .mvn/wrapper con la configuración. La primera vez que lo ejecutas, el wrapper descarga la versión exacta de Maven que el proyecto declara y la usa.
# En lugar de: mvn clean package
./mvnw clean package
# En Windows (PowerShell o CMD)
mvnw.cmd clean packageVentajas, y son importantes:
- Reproducibilidad: todo el equipo y el servidor de integración continua usan la misma versión de Maven, sin coordinarse.
- Cero instalación: alguien clona el repositorio y construye sin instalar nada más que el JDK.
- Versionado: la versión de Maven se actualiza cambiando un fichero y se revisa como cualquier otro cambio de código.
La versión concreta vive aquí:
# .mvn/wrapper/maven-wrapper.properties
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zipEn este curso siempre usaremos ./mvnw. Si tienes Maven instalado, mvn funcionará igual, pero acostúmbrate al wrapper: es la convención profesional.
Un detalle habitual en Linux/macOS: si al clonar un repositorio ./mvnw da "permiso denegado", falta el bit de ejecución.
- Elegir un IDE: IntelliJ IDEA, Eclipse/STS y VS Code
Puedes seguir el curso con cualquiera de los tres. Esto es lo que aporta cada uno:
| IDE | Edición gratuita | Puntos fuertes | Inconvenientes |
|---|---|---|---|
| IntelliJ IDEA | Community (suficiente para el curso) | Mejor autocompletado y refactorización de Java del mercado; excelente depurador | El soporte específico de Spring (navegación de beans, autocompletado de application.properties) solo está en Ultimate |
| Eclipse / Spring Tool Suite (STS) | Sí, todo gratuito | STS es Eclipse con herramientas Spring ya incluidas: panel de beans, arranque de aplicaciones Boot, edición asistida de propiedades | Interfaz menos pulida; consume bastante memoria |
| VS Code + Extension Pack for Java | Sí | Ligero, arranca rápido, mismo editor para frontend y backend; extensión "Spring Boot Extension Pack" muy completa | Menos potente en refactorizaciones grandes |
Qué instalar en cada caso
IntelliJ IDEA Community: descárgalo de jetbrains.com o instálalo con la Toolbox App. Reconoce proyectos Maven automáticamente al abrir la carpeta que contiene el pom.xml.
Spring Tool Suite: descarga STS 4 desde spring.io/tools. Se distribuye como un JAR autoejecutable que despliega el IDE. Para importar el proyecto: File → Import → Existing Maven Projects.
VS Code: instala estas dos extensiones desde el Marketplace.
# Desde la línea de comandos, si tienes el comando "code" disponible
code --install-extension vscjava.vscode-java-pack
code --install-extension vmware.vscode-boot-dev-pack- Extension Pack for Java: compilador, depurador, soporte Maven, ejecutor de pruebas.
- Spring Boot Extension Pack: autocompletado en
application.properties, panel de Spring Boot Dashboard para arrancar y parar aplicaciones, navegación entre endpoints.
Configuración recomendada, sea cual sea el IDE
- Comprueba que el IDE usa el JDK 21, no uno interno más antiguo. En IntelliJ: File → Project Structure → SDK. En VS Code: la variable
java.configuration.runtimes. - Activa la construcción automática y el formateo al guardar.
- Configura la codificación en UTF-8 para todo el proyecto. Los nombres de las estaciones de Ribalta llevan tildes, y una codificación mal fijada produce "Parque del RÃo".
- Herramientas para probar la API
Vas a construir una API REST, así que necesitas algo con lo que llamarla. Conviene conocer varias opciones:
curl
Está en prácticamente cualquier sistema y es el lenguaje común de la documentación.
# Petición GET simple
curl http://localhost:8080/api/v1/estaciones
# Ver también las cabeceras de respuesta y el código de estado
curl -i http://localhost:8080/api/v1/estaciones
# Petición POST con cuerpo JSON
curl -X POST http://localhost:8080/api/v1/estaciones \
-H "Content-Type: application/json" \
-d '{"nombre":"Plaza Mayor","capacidad":24}'Las opciones que más usarás: -i (incluir cabeceras), -X (método HTTP), -H (cabecera), -d (cuerpo), -s (silencioso).
HTTPie
Sintaxis más legible y coloreado del JSON de salida. Muy cómodo para explorar.
# Instalación
sudo apt install httpie # Debian/Ubuntu
brew install httpie # macOS
# GET
http :8080/api/v1/estaciones
# POST: los pares clave=valor se convierten en JSON automáticamente
http POST :8080/api/v1/estaciones nombre="Plaza Mayor" capacidad:=24Detalle importante: nombre="Plaza Mayor" genera una cadena, mientras que capacidad:=24 (con :=) genera un número. Es un error frecuente enviar "24" cuando la API espera un entero.
Postman
Aplicación gráfica. Su valor está en organizar colecciones de peticiones guardadas, usar variables de entorno ({{baseUrl}}), gestionar tokens de autenticación y compartir todo con el equipo. Muy útil a partir del módulo 5, cuando aparezcan los tokens JWT.
Ficheros .http
Es mi recomendación para este curso. Son ficheros de texto plano, versionables en Git, que IntelliJ (nativo) y VS Code (extensión REST Client) ejecutan directamente desde el editor.
### Listar todas las estaciones de Ribalta
GET http://localhost:8080/api/v1/estaciones
Accept: application/json
### Consultar una estación concreta
GET http://localhost:8080/api/v1/estaciones/1
Accept: application/json
### Dar de alta una estación nueva
POST http://localhost:8080/api/v1/estaciones
Content-Type: application/json
{
"nombre": "Parque del Río",
"direccion": "Paseo Fluvial 12",
"capacidad": 18
}Cada bloque separado por ### es una petición independiente con su propio botón de ejecución. Crea el fichero api-ciclourbana.http en la raíz del proyecto y ve añadiendo ahí cada endpoint que construyas: acabarás con documentación viva y ejecutable de toda la API.
- Docker: requisito para los módulos posteriores
En los módulos 1 a 3 no necesitas Docker. A partir del módulo 4 sí conviene tenerlo, y es imprescindible en los módulos 6, 7 y 8:
- Módulo 4: levantar un PostgreSQL real sin instalarlo en tu máquina.
- Módulo 6: Testcontainers arranca bases de datos efímeras para las pruebas de integración.
- Módulos 7 y 8: empaquetar CicloUrbana como imagen y desplegarla.
Instalación
- Linux: instala Docker Engine siguiendo la guía oficial de tu distribución y añade tu usuario al grupo
dockerpara no necesitarsudo. - macOS y Windows: instala Docker Desktop. En Windows, activa la integración con WSL 2, que es donde funcionará mejor.
# En Linux, tras instalar
sudo usermod -aG docker $USER
# Cierra sesión y vuelve a entrar para que el cambio surta efectoVerificación
docker --version
docker compose version
# Prueba real: descarga y ejecuta una imagen mínima
docker run --rm hello-worldUn ensayo de lo que harás en el módulo 4, solo para comprobar que todo funciona:
# Arrancar un PostgreSQL temporal para CicloUrbana
docker run --name ciclourbana-db \
-e POSTGRES_DB=ciclourbana \
-e POSTGRES_USER=ciclo \
-e POSTGRES_PASSWORD=secreto \
-p 5432:5432 \
-d postgres:16
# Comprobar que está en marcha
docker ps
# Detenerlo y eliminarlo cuando termines
docker stop ciclourbana-db && docker rm ciclourbana-db
- Checklist final de verificación
Guarda este script como verificar-entorno.sh y ejecútalo. Si todas las líneas responden, tu entorno está listo.
#!/usr/bin/env bash
echo "=== Verificación del entorno para CicloUrbana ==="
echo "--- 1. JDK (se espera 21) ---"
java -version 2>&1 | head -1
javac -version 2>&1
echo "--- 2. JAVA_HOME ---"
echo "JAVA_HOME=${JAVA_HOME:-NO DEFINIDA}"
echo "--- 3. Maven (opcional: usaremos ./mvnw) ---"
mvn -version 2>/dev/null | head -1 || echo "Maven no instalado (correcto si usas el wrapper)"
echo "--- 4. Herramientas HTTP ---"
curl --version 2>/dev/null | head -1 || echo "curl NO disponible"
http --version 2>/dev/null || echo "HTTPie no instalado (opcional)"
echo "--- 5. Docker (necesario desde el módulo 4) ---"
docker --version 2>/dev/null || echo "Docker no instalado (aún no es obligatorio)"
echo "--- 6. Git ---"
git --version 2>/dev/null || echo "Git NO disponible"
echo "=== Fin de la verificación ==="Ejecución:
Tabla de lo que debe cumplirse antes de pasar a la lección 01-03:
| Requisito | Cómo se comprueba | ¿Obligatorio ya? |
|---|---|---|
| JDK 21 instalado | java -version muestra 21.x |
Sí |
| Compilador disponible | javac -version muestra 21.x |
Sí |
JAVA_HOME apuntando al JDK 21 |
echo $JAVA_HOME |
Sí |
| IDE instalado y usando el JDK 21 | Configuración del proyecto | Sí |
| Cliente HTTP | curl --version |
Sí |
| Conexión a internet | Maven descargará dependencias | Sí |
| Git | git --version |
Recomendado |
| Docker | docker run --rm hello-world |
Desde el módulo 4 |
Errores Comunes y Consejos
- Tener instalado un JRE en lugar de un JDK. El síntoma es claro:
javafunciona perojavacno existe, y Maven falla con "No compiler is provided in this environment". Instala el paquete con sufijo-jdko-devel. JAVA_HOMEapuntando a otra versión.java -versiondice 21 pero Maven compila con 17. Fíate siempre de la líneaJava version:que imprimemvn -version, porque es la que realmente usa la construcción.- Usar
mvnen lugar de./mvnw. Funciona, pero introduce una variable no controlada: la versión de Maven de tu máquina. En equipo, esto acaba en un "a mí me compila". - Olvidar
chmod +x mvnwtras clonar. Error muy frecuente en Linux y macOS. - La primera construcción tarda muchísimo. Es normal: Maven descarga cientos de artefactos a
~/.m2/repository. Las siguientes usan esa caché local y son rápidas. No canceles el proceso a medias, porque puedes dejar ficheros corruptos en la caché. - Consejo — trabajar sin conexión. Si la caché queda inconsistente, borra la carpeta problemática dentro de
~/.m2/repositoryy vuelve a construir. Borrar todo~/.m2funciona, pero obliga a descargarlo todo otra vez. - Consejo — codificación UTF-8. Fíjala en el IDE y en el sistema. Ribalta tiene estaciones como "Parque del Río" y verás las tildes rotas al primer descuido.
Ejercicios
Ejercicio 1
Prepara tu máquina y documenta el resultado: instala el JDK 21, comprueba java -version, javac -version y JAVA_HOME, e indica qué distribución has elegido y por qué.
Ejercicio 2
Tu equipo mantiene un sistema antiguo con Java 17 y quiere empezar CicloUrbana con Java 21 en el mismo portátil. Explica cómo lo resolverías con SDKMAN! y escribe los comandos concretos, incluyendo cómo dejar fijada la versión por proyecto sin cambiar la del sistema.
Ejercicio 3
Crea un fichero api-ciclourbana.http con tres peticiones a endpoints que aún no existen: listar estaciones, obtener la estación con id 1 y crear la estación "Estación Norte" con capacidad 30. Escribe además el comando curl equivalente a la tercera.
Soluciones
Solución 1
En una máquina Ubuntu:
sudo apt update
sudo apt install openjdk-21-jdk
java -version
# openjdk version "21.0.5" 2024-10-15 LTS
javac -version
# javac 21.0.5
echo $JAVA_HOME
# (vacío) → hay que definirlo
# Averiguar la ruta real del JDK
readlink -f $(which javac)
# /usr/lib/jvm/java-21-openjdk-amd64/bin/javac
# Añadir al ~/.bashrc
echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64' >> ~/.bashrc
echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
echo $JAVA_HOME
# /usr/lib/jvm/java-21-openjdk-amd64Elección justificada: el OpenJDK de los repositorios es cómodo en Linux porque se actualiza con el sistema. Si necesitas una versión concreta y reproducible entre máquinas, es preferible Temurin vía SDKMAN!.
Solución 2
# 1. Instalar SDKMAN! si no lo tienes
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
# 2. Instalar las dos versiones que necesita el equipo
sdk install java 17.0.13-tem
sdk install java 21.0.5-tem
# 3. Mantener 17 como versión por defecto del sistema (el proyecto antiguo)
sdk default java 17.0.13-temPara que CicloUrbana use 21 sin cambiar la versión global, se declara en la raíz del proyecto:
Y en cada sesión de terminal dentro del proyecto:
cd ciclourbana
sdk env # activa las versiones del .sdkmanrc
java -version # 21.0.5
cd ..
java -version # vuelve a 17.0.13 (la global)El fichero .sdkmanrc se versiona en Git, así que cualquier miembro del equipo obtiene la misma configuración al clonar. Con sdk env install se instalan de golpe las versiones que falten.
Solución 3
### 1. Listar todas las estaciones de la red de Ribalta
GET http://localhost:8080/api/v1/estaciones
Accept: application/json
### 2. Detalle de la estación con id 1
GET http://localhost:8080/api/v1/estaciones/1
Accept: application/json
### 3. Alta de la estación "Estación Norte"
POST http://localhost:8080/api/v1/estaciones
Content-Type: application/json
Accept: application/json
{
"nombre": "Estación Norte",
"direccion": "Avenida de la Estación 3",
"capacidad": 30
}El equivalente en curl de la tercera petición:
curl -i -X POST http://localhost:8080/api/v1/estaciones \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"nombre": "Estación Norte",
"direccion": "Avenida de la Estación 3",
"capacidad": 30
}'Nota sobre las cabeceras: Content-Type describe lo que envías; Accept declara lo que quieres recibir. Confundirlas es una fuente clásica de respuestas 415 y 406, que veremos en el módulo 3.
Conclusión
Ya tienes el entorno preparado y, más importante, verificado: JDK 21 con JAVA_HOME correcto, un IDE que apunta a ese JDK, un cliente HTTP para probar la API y Docker listo para cuando lo necesites. Has visto también por qué el curso usa Maven y por qué siempre invocaremos ./mvnw en lugar de mvn: reproducibilidad para ti y para todo el equipo.
En la siguiente lección, Creando tu Primera Aplicación Spring Boot, generarás el proyecto ciclourbana con Spring Initializr, escribirás tu primer endpoint GET /api/v1/estaciones con las estaciones de Ribalta, lo ejecutarás con ./mvnw spring-boot:run y lo empaquetarás en un JAR ejecutable.
Curso de Spring Boot
Módulo 1: Introducción a Spring Boot
- ¿Qué es Spring Boot?
- Configuración de tu Entorno de Desarrollo
- Creando tu Primera Aplicación Spring Boot
- Entendiendo la Estructura del Proyecto
- El Arranque y el Ciclo de Vida de la Aplicación
Módulo 2: Conceptos Básicos de Spring Boot
- Anotaciones de Spring Boot
- Inyección de Dependencias en Spring Boot
- Ámbito y Ciclo de Vida de los Beans
- Configuración de Spring Boot
- Propiedades de Spring Boot
- Autoconfiguración y Starters por Dentro
Módulo 3: Construyendo Servicios Web RESTful
- Introducción a los Servicios Web RESTful
- Creando Controladores REST
- Manejo de Métodos HTTP
- Validación de Datos de Entrada
- DTOs y Mapeo entre Capas
- Manejo de Excepciones en REST
- Documentar la API con OpenAPI
Módulo 4: Acceso a Datos con Spring Boot
- Introducción a Spring Data JPA
- Configuración de Fuentes de Datos
- Creación de Entidades JPA
- Relaciones entre Entidades
- Uso de Repositorios de Spring Data
- Métodos de Consulta en Spring Data JPA
- Transacciones y Gestión de la Persistencia
- Migraciones de Esquema con Flyway
Módulo 5: Seguridad en Spring Boot
- Introducción a Spring Security
- Configuración de Spring Security
- Autenticación y Autorización de Usuarios
- Implementación de Autenticación JWT
- Seguridad a Nivel de Método y Endurecimiento de la API
Módulo 6: Pruebas en Spring Boot
- Introducción a las Pruebas
- Pruebas Unitarias con JUnit
- Simulación con Mockito
- Pruebas de Integración
- Pruebas con Testcontainers
Módulo 7: Funciones Avanzadas de Spring Boot
- Spring Boot Actuator
- Perfiles de Spring Boot
- Tareas Programadas y Ejecución Asíncrona
- Spring Boot con Docker
- Spring Boot y Microservicios
- Comunicación entre Servicios y Tolerancia a Fallos
Módulo 8: Despliegue de Aplicaciones Spring Boot
- Introducción al Despliegue
- Desplegando en Heroku
- Desplegando en AWS
- Desplegando en Kubernetes
- Integración y Entrega Continua
Módulo 9: Rendimiento y Monitoreo
- Ajuste de Rendimiento
- Caché con Spring Cache
- Monitoreo con Spring Boot Actuator
- Uso de Prometheus y Grafana
- Gestión de Registros y Logs
- Trazabilidad Distribuida
