LuxCore
Framework web para Java
Arranca solo, sin contenedor de servlets y sin una sola dependencia externa. 297 KB en cinco módulos que se toman por separado.
$ ./lux correr
@Route("/api/tareas") public class TareaController { @Inject Tareas tareas; @Get public Object listar(@Query(value = "pagina", orElse = "1") int pagina) { return tareas.findPage(pagina, 20); } @Get("/{id}") public Object ver(@Path("id") long id) { Tarea t = tareas.findById(id); if (t == null) throw new HttpException(404, "no existe"); return t; } @Post public Object crear(@Body @Valid Tarea tarea) { return Result.created(tareas.insert(tarea)); } @Delete("/{id}") public Object borrar(@Path("id") long id) { return tareas.deleteById(id) == 0 ? Result.status(404, "no existe") : Result.noContent(); } }
// El record es la entidad, la validación y el mapeo. No hay tres clases. @Table("tareas") public record Tarea( @Id long id, @Required @Length(min = 3, max = 120) String titulo, @OneOf({"baja", "media", "alta"}) String prioridad, @Column("hecha") boolean completada) {} @Service public class Tareas extends Repository<Tarea, Long> { public Tareas() { super(Tarea.class); } public List<Tarea> pendientes() { return findBy("hecha = ?", false); } public void completar(long id) { Tx.run(() -> db().update("tareas", Row.of("hecha", true), "id = ?", id)); } }
// Una línea para lo simple… Lux.run(8080, TareaController.class); // …y todo declarado para lo serio. Lux.app() .loadConfig() .views(Templates.fromClasspath("plantillas")) .fallback(StaticFiles.fromClasspath("estaticos", "/estaticos")) .authenticator(ctx -> sesiones.verificar(ctx.header("Authorization"))) .use(SecurityHeaders.standard()) .use(Cors.allowing("https://app.pe")) .use(Csrf.enabled().exempt("/api/")) .use(RateLimit.perMinute(300)) .use(AccessLog.combined()) .use(metricas) .controllers(TareaController.class, AdminController.class) .routes(r -> r.get("/salud", ctx -> "ok") .get("/lux/metrics", metricas.endpoint())) .start() .await();
Por qué existe
LuxCore nace de JxMVC, un framework MVC que funciona y está en producción — pero que necesita Tomcat para arrancar. Quitar el contenedor no era un capricho: era el 94 % del tiempo de arranque y el 98 % del peso desplegado.
| Métrica | JxMVC sobre Tomcat | LuxCore | Diferencia |
|---|---|---|---|
| Arranque | 698 ms | 106 ms | 6,6× |
| Desplegado | 253 KB + ~15 MB | 297 KB | 51× |
| Imagen de contenedor | 274 MB | 110 MB | 2,5× |
| Dependencias en ejecución | Jakarta EE 10 | ninguna | — |
| Pruebas | 347 | 1 227 | 2,7× |
Y no hay que saltar de golpe: lux-adapter-servlet despliega una aplicación
LuxCore dentro de Tomcat, así que la migración es reversible.
Qué trae
HTTP/1.1 con un hilo virtual por conexión. TLS, keep-alive, chunked, multipart, gzip, cookies, sesiones y archivos estáticos.
Plantillas {var}, comodines y una regla sin excepciones. Lo literal
gana a lo variable y las rutas duplicadas fallan al arrancar, no en producción.
JDBC directo sin ORM, con pool, transacciones y repositorios. Verificado contra PostgreSQL 16, MySQL 8 y H2 con la misma batería.
Plantillas compiladas con herencia, bucles e inclusión. El escapado HTML es el comportamiento por defecto, no una opción que se olvida.
CORS, CSRF, rate limiting, validación declarativa, sanitizado y cabeceras de seguridad. Probado con clientes hostiles y entradas malformadas.
Tareas en segundo plano sobre hilos virtuales, programación por intervalo y cron de cinco campos. Una tarea que falla no derriba el planificador.
Cliente HTTP con reintentos y eventos servidos — que es como transmiten las APIs de IA, así que consumirlas es una línea.
Entrar con Google, Microsoft o GitHub, con PKCE y verificación de firma del
id_token. Contraseñas con PBKDF2 y coste embebido.
Métricas por ruta con percentiles, en JSON o formato Prometheus, y log de acceso combinado o compacto.
Lo que todavía no
El servidor HTTP tiene días de vida. Una auditoría encontró una inyección CRLF a las pocas horas de escribirlo, y la primera aplicación real destapó otros cuatro fallos. Todos corregidos y cubiertos — el punto es que aparecieron.
Sirve hoy para un proyecto interno, un prototipo o una herramienta de equipo. Ya corre en Linux, ya está medido contra sus cinco rivales y los gana en casi todo. Lo que falta no se arregla programando: dejarlo semanas recibiendo tráfico real. Está todo detallado, sin adornos, en Estado.
Empezar
Módulos y artefactos
Los cinco JAR con su tamaño y huella, coordenadas de Maven y qué necesita cada uno.
De cero a corriendo
Cuatro órdenes, con la guía paso a paso en terminal.
Escribir una aplicación
Rutas, parámetros, respuestas, inyección, validación y errores.
Servidor, vistas, datos
Qué trae cada pieza y cómo tomarlas por separado.