Jakarta EE frente a .NET
El cierre del tema y lo que más se pregunta: cómo se construye un proyecto en cada plataforma, qué pieza de una se corresponde con qué pieza de la otra, en qué se diferencian de verdad y qué equivalencias de detalle conviene tener memorizadas.
Las herramientas de construcción comparadas
Las dos plataformas resuelven el mismo problema, crear el proyecto, compilarlo, resolver sus dependencias y empaquetarlo, pero lo reparten de forma distinta. En Java una sola herramienta, Maven, hace los tres papeles. En .NET los papeles están separados en tres piezas que se usan juntas.
| Trabajo | En Java | En .NET |
|---|---|---|
| Crear el proyecto y su estructura | Maven con un arquetipo | La herramienta de línea de comandos dotnet |
| Compilar y ejecutar | Maven, que llama por debajo al compilador | La misma herramienta dotnet |
| Definir tareas de compilación y empaquetado | Los complementos de Maven | MSBuild |
| Gestionar dependencias | Maven, sobre su repositorio | NuGet, sobre el suyo |
| Repositorio público de referencia | El repositorio central de Maven | El repositorio central de NuGet |
| Lo que se descarga | Un .jar | Un ensamblado |
La idea de fondo es la misma en las dos: se declara qué biblioteca y qué versión hacen falta, y la herramienta la descarga de un repositorio público y la deja donde el compilador la encuentre. Nadie copia bibliotecas a mano ni las guarda en el control de versiones.
# .NET: crear, añadir dependencia, compilar y ejecutar
dotnet new webapp -o PortalDelOpositor
dotnet add package Newtonsoft.Json --version 13.0.3
dotnet build
dotnet run
# Java: lo equivalente con Maven
mvn archetype:generate -DgroupId=com.llegandoalcorte -DartifactId=portal
# la dependencia se declara en el pom.xml, no por línea de comandos
mvn packagePara el examen
En Java: Maven crea, compila y gestiona dependencias
En .NET: el trabajo se reparte entre la herramienta dotnet, MSBuild y NuGet
Pieza a pieza: qué se corresponde con qué
AMPLIADO (ninguno de los documentos de partida hace esta comparación completa, y es la forma habitual de preguntar el tema: dada una pieza de una plataforma, cuál es su equivalente en la otra).
| Papel | Java y Jakarta EE | .NET |
|---|---|---|
| Motor de ejecución | JVM | CLR |
| Código intermedio | Bytecode, en ficheros .class | CIL |
| Kit de desarrollo | JDK | SDK de .NET |
| Biblioteca empaquetada | Fichero .jar | Ensamblado, en .dll o .exe |
| Dónde se buscan las bibliotecas | El classpath | El GAC en .NET Framework; en el .NET moderno, junto a la propia aplicación |
| Compilación a nativo en ejecución | Compilador JIT | Compilador JIT |
| Liberación de memoria | Recolector de basura | Recolector de basura |
| Raíz de la jerarquía de tipos | java.lang.Object | System.Object |
| Acceso a datos de bajo nivel | JDBC | ADO.NET |
| Correspondencia entre objetos y tablas | JPA, con Hibernate o EclipseLink | Entity Framework, o NHibernate |
| Consulta sobre objetos | JPQL | LINQ |
| Componente que recibe la petición | Servlet | Controlador de ASP.NET |
| Generación de la vista | Jakarta Pages y Jakarta Faces | Razor |
| Servicios web SOAP | JAX-WS | Servicios .asmx, y WCF |
| Servicios web REST | JAX-RS | ASP.NET Web API |
| Dónde se ejecuta la aplicación | Un servidor de aplicaciones: WildFly, GlassFish, TomEE, WebLogic | IIS con el motor de ASP.NET, o Kestrel en el .NET moderno |
| Construcción y dependencias | Maven o Gradle | La herramienta dotnet, MSBuild y NuGet |
Si hay que memorizar una sola fila, que sea la de los servicios web: JAX-WS con SOAP y JAX-RS con ASP.NET Web API. Emparejar JAX-RS con ASP.NET MVC es un error extendido, y las preguntas lo aprovechan.
Para el examen
JVM y bytecode: CLR y CIL
.jar: ensamblado
JDBC y JPA: ADO.NET y Entity Framework
JPQL y servlet: LINQ y controlador de ASP.NET
La fila decisiva: JAX-RS se empareja con ASP.NET Web API, no con ASP.NET MVC
Las diferencias que no son de nombre
Debajo de la tabla de equivalencias hay cuatro diferencias de concepto que explican por qué las dos plataformas se sienten distintas al trabajar con ellas.
- Especificación frente a producto. Jakarta EE es un conjunto de especificaciones que implementan varios fabricantes, así que se elige servidor y se puede cambiar. .NET nació como el producto de una sola empresa, y aunque hoy sea de código abierto y admita distintos entornos de despliegue, la cadena de herramientas es una sola. Lo primero da capacidad de elección; lo segundo da coherencia.
- Multiplataforma. Java lo fue desde el primer día, y ese era su argumento de venta. .NET estuvo atado a Windows durante casi quince años y solo es multiplataforma desde la reescritura de 2016.
- Multilenguaje. .NET se diseñó desde el principio para varios lenguajes sobre un sistema de tipos común, y por eso C#, VB.NET y F# conviven sin pasarelas. La máquina virtual de Java también aloja hoy otros lenguajes, como Kotlin, Scala o Groovy, pero eso llegó después y no era el propósito original.
- Modelo de despliegue. En el modelo clásico de Jakarta EE la aplicación se empaqueta y se despliega dentro de un servidor que ya está instalado. En el .NET moderno, y también en el Java moderno de estilo Spring Boot, la aplicación lleva su propio servidor dentro y se arranca como un programa cualquiera.
Hay además una asimetría de nomenclatura que conviene tener clara para no responder de más. En el lado de Java hay que distinguir la edición estándar de la empresarial: Java SE es el lenguaje, la máquina virtual y la API básica, y Jakarta EE son las especificaciones de servidor que se añaden encima. En .NET no existe esa división: la plataforma trae de serie tanto lo básico como lo empresarial, y lo que se elige es qué paquetes se añaden al proyecto.
Para el examen
Jakarta EE: una especificación con varios fabricantes
.NET: un producto con una sola cadena de herramientas
Multiplataforma: Java desde el principio; .NET solo desde 2016
Multilenguaje: .NET nació así, sobre un sistema de tipos común
Equivalencias de detalle entre los lenguajes
Bajando al nivel de la sintaxis, hay un puñado de correspondencias que caen en las preguntas más finas del tema.
| Idea | En Java | En .NET |
|---|---|---|
| Agrupar tipos | Paquete, declarado con package | Espacio de nombres (namespace) |
| Traer tipos de otro grupo | import | Imports en VB.NET, using en C# |
| Metainformación sobre el código | Anotaciones | Atributos |
| Crear el objeto | Constructor con el nombre de la clase | Constructor New |
| Aviso previo a la liberación | finalize(), obsoleto y desaconsejado | Finalize |
| Liberar recursos automáticamente | try-with-resources, sobre AutoCloseable | Using, sobre IDisposable |
| Método que no devuelve valor | Método con retorno void | Procedimiento (Sub) |
| Método que devuelve valor | Método con tipo de retorno | Función (Function) |
Sobre el paso de argumentos, el reparto no coincide del todo y por eso se pregunta. En Java los tipos primitivos van por valor y todo lo demás por referencia. En .NET la frontera la marca el sistema de tipos: los tipos por valor son los primitivos y las estructuras, mientras que las cadenas, los arrays, las clases y los delegados van por referencia.
Dos detalles más, propios de VB.NET y heredados de su historia. El primero: un número no pasa por su cuenta a texto, ni el texto a número, así que hay que llamar expresamente a la función de conversión que corresponda. El segundo: dos tipos del Visual Basic clásico desaparecieron al pasar a .NET, y sus sustitutos entran en el examen. El tipo monetario Currency quedó sustituido por Decimal, y el tipo comodín Variant por Object.
Para el examen
Paquete e import: espacio de nombres y using
Anotaciones: atributos
try-with-resources sobre AutoCloseable: Using sobre IDisposable
En VB.NET: Currency pasó a Decimal y Variant a Object
Detalle fino: ADO.NET desconectado y los subcomandos de dotnet
ADO.NET admite dos formas de trabajar. En la conectada, la aplicación mantiene abierta la conexión y va leyendo el resultado sobre la marcha, como con un cursor. En la desconectada, se vuelca el resultado en una estructura en memoria, se cierra la conexión y se trabaja con esa copia.
| Pieza | Papel en el modo desconectado |
|---|---|
| DataSet | El almacén en memoria, que puede contener varias tablas y las relaciones entre ellas. Es una base de datos en miniatura |
| DataAdapter | El puente: rellena el almacén desde la base de datos y devuelve después los cambios |
El modo desconectado fue muy usado en las aplicaciones de escritorio de su época, pero hoy se considera superado: consume mucha memoria y su papel lo cubren mejor los objetos que devuelve un ORM. Conviene reconocerlo porque aparece en preguntas de repaso, no porque se vaya a programar así.
| Orden | Qué hace |
|---|---|
| dotnet new | Crea un proyecto del tipo indicado (consola, aplicación web, biblioteca de clases) con su árbol de ficheros |
| dotnet add | Añade o actualiza un paquete o una referencia del proyecto |
| dotnet build | Compila el proyecto y sus dependencias |
| dotnet run | Compila y ejecuta |
Para el examen
DataSet: guarda las tablas en memoria
DataAdapter: hace de puente con la base de datos
Subcomandos de dotnet: new, add, build y run