Saltear al contenido principal

Varios tipos de medios en microservicios Java con RESTEasy

[ad_1]

Hoy vamos a hablar de microservicios en Java. Si bien es cierto que Java EE tiene una plataforma robusta para escribir, implementar y administrar microservicios a nivel empresarial, en este artículo crearé un microservicio RESTful que sea lo más delgado posible.

No se preocupe, no reinventaremos la rueda empaquetando nuestros propios datos o algo así. ¡Usaremos JBoss RESTEasy para solucionar este problema! El objetivo de mantener las cosas ligeras es mostrar lo simple que puede ser establecer una interfaz RESTful frente a un microservicio Java nuevo o existente.

Al mismo tiempo, ilustraré la flexibilidad de dicho servicio al admitir varios tipos de medios, JSON y XML, y desplegarlo en Apache Tomcat en lugar de JBoss Enterprise Application Platform (EAP). Cada herramienta tiene su lugar, pero creo que es útil explorar primero las tecnologías a través de la lente del principio KISS y luego decidir qué tipo de características arquitectónicas adicionales perseguir, dependiendo de los objetivos y requisitos a largo plazo del software.

El ejemplo de código de este artículo está disponible en GitHub, con ramas «inicial» y «final». A continuación se describe mi entorno, aunque su kilometraje puede variar:

Tecnicamente hablando …

Un microservicio es un servicio pequeño y conciso que tiene como objetivo «hacer algo bien». Es bastante común interactuar con microservicios a través de algún tipo de interfaz. Si se puede acceder a esta interfaz a través de la web (mediante HTTP), entonces es un servicio web. Algunos servicios web son RESTful y otros no. Es importante tener en cuenta que no todos los microservicios son servicios web, no todos los servicios web son RESTful y no todos los servicios web RESTful son microservicios.

¡no todos los servicios web son RESTful y no todos los servicios web RESTful son microservicios!

REST y XML … ¿juntos?

Si nunca ha encontrado un servicio web RESTful que ofrezca contenido utilizando uno de los muchos tipos de medios distintos de JSON, podría pensar que estas dos cosas no encajan. Pero recuerde que REST es un estilo arquitectónico para definir API y que la popularidad de REST y JSON ha crecido en paralelo (no por casualidad, claro). Los servicios web RESTful que aceptan y proporcionan XML pueden ser de gran utilidad para organizaciones que ya tienen sistemas interconectados que dependen de este tipo de contenido o para consumidores que simplemente tienen más experiencia con XML. Por supuesto, JSON normalmente sería la primera opción porque los cuerpos de los mensajes son más pequeños, pero a veces XML es simplemente una «venta» más fácil. Tener un microservicio RESTful que pueda hacer ambas cosas es aún mejor; no solo es conciso y escalable desde el punto de vista de la implementación, sino que también es lo suficientemente flexible para admitir diferentes tipos de contenido para aplicaciones que desean consumirlo.

¿Por qué RESTEasy?

RESTEasy es un marco JBoss para ayudarlo a construir servicios web RESTful. Con RESTEasy, es posible construir un servicio web RESTful que sirva XML y JSON dependiendo de solo cuatro bibliotecas:

  • resteasy-jaxrs, que implementa JAX-RS 2.0 (API de Java para servicios web RESTful)
  • proveedor resteasy-jaxb, cuyo enlace JAXB nos ayuda a admitir XML
  • resteasy-jettison-proveedor, que usa Jettison para convertir XML a JSON
  • resteasy-servlet-initializer, para la implementación en un contenedor Servlet 3.0 (en Tomcat)

Para empezar, creamos un proyecto de servicio web con un pom.xml similar a este:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.lyndseypadget</groupId>
	<artifactId>resteasy</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>resteasy</name>
	<repositories>
		<repository>
			<id>org.jboss.resteasy</id>
			<url>http://repository.jboss.org/maven2/</url>
		</repository>
	</repositories>
	<dependencies>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxrs</artifactId>
			<version>3.1.4.Final</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jaxb-provider</artifactId>
			<version>3.1.4.Final</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-jettison-provider</artifactId>
			<version>3.1.4.Final</version>
		</dependency>
		<dependency>
			<groupId>org.jboss.resteasy</groupId>
			<artifactId>resteasy-servlet-initializer</artifactId>
			<version>3.1.4.Final</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
		<finalName>resteasy</finalName>
	</build>
</project>

Juntas, estas bibliotecas tienen aproximadamente 830 KB. Por supuesto, estas son nuestras dependencias directas y la construcción del proyecto con Maven también traerá un puñado de dependencias transitivas.

dependencias directas y la construcción del proyecto con Maven también traerá un puñado de dependencias transitivas.

A partir de ahora, construiré este proyecto en «modo Maven» (es decir, clases en src / main / java, usando comandos de compilación de Maven, etc.), pero también puede descargar los archivos RESTEasy jars directamente desde la página de descarga si lo prefiere no usar Maven. Si sigue este camino, no se alarme por esta ventana emergente en el sitio web de RESTEasy: JBoss simplemente está tratando de llevarlo por un camino más «comercial». Puede hacer clic en «Continuar descarga» y seguir su camino.

JBoss simplemente está tratando de llevarlo por un camino más

El diseño del proyecto

Este servicio será sumamente sencillo para ilustrar algunos conceptos básicos. Necesitarás cinco clases, organizadas así:

Necesitarás cinco clases, organizadas así:

FruitApplication es el punto de entrada para el microservicio. FruitService proporciona el punto final principal (/ fruits) y también sirve como enrutador. La manzana y la fruta son los modelos; La fruta tiene algunas características abstractas y Apple las va a ampliar de forma concreta.

Como puedes imaginar, FruitComparator nos ayuda a comparar frutas. Si no está familiarizado con los comparadores de Java, puede aprender sobre la igualdad y la comparación de objetos en este artículo, donde estoy usando Strings. Aunque FruitComparator no es un modelo, prefiero mantener los comparadores cerca del tipo de objeto que pretende comparar.

Los modelos

Comencemos con la clase de frutas:

package com.lyndseypadget.resteasy.model;

import javax.xml.bind.annotation.XmlElement;

public abstract class Fruit {
    private String id;
    private String variety;

    @XmlElement
    public String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }

    @XmlElement
    public String getVariety() {
        return variety;
    }
    
    public void setVariety(String variety) {
        this.variety = variety;
    }
}

Y la clase de Apple que la extiende:

package com.lyndseypadget.resteasy.model;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "apple")
public class Apple extends Fruit {
    
    private String color;

    @XmlElement
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
}

Este código no es particularmente sorprendente aquí, es un ejemplo simple de herencia de Java. Sin embargo, las partes importantes son las anotaciones @XmlElement y @XmlRootElement, que definen cómo se verá la estructura de la manzana XML:

<apple>
	<id>1</id>
	<variety>Golden delicious</variety>
	<color>yellow</color>
</apple>

También está sucediendo algo más aquí que es más sutil, ya que no se proporciona ningún constructor explícitamente: Java usa un constructor implícito y predeterminado sin arg. Este constructor sin argumentos es realmente necesario para que funcione la magia JAXB (este artículo explica por qué sucede y cómo puede solucionarlo con XMLAdapter, si es necesario).

Ahora tenemos nuestro objeto, una manzana, definido. Tiene tres propiedades: id, variedad y color.

El servicio

La clase FruitService sirve como el punto final principal (/ fruits) que usaremos para interactuar con el microservicio. En ese caso, definí la primera ruta, / frutas / manzanas, directamente en esta clase usando la anotación @Path. A medida que crezca su microservicio RESTful, es probable que desee definir cada punto final (es decir, / manzanas, / plátanos, / naranjas) en su propia clase.

package com.lyndseypadget.resteasy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.lyndseypadget.resteasy.model.Apple;
import com.lyndseypadget.resteasy.model.FruitComparator;

@Path("/fruits")
public class FruitService {

	private static Map<String, Apple> apples = new TreeMap<String, Apple>();
	private static Comparator comparator = new FruitComparator();

	@GET
	@Path("/apples")
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	public List getApples() {
		List retVal = new ArrayList(apples.values());
		Collections.sort(retVal, comparator);
		return retVal;
	}
}

El mapa de manzanas nos ayuda a rastrear nuestras manzanas por id, simulando así algún tipo de capa de persistencia. El método getApples devuelve los valores de ese mapa. La ruta GET / manzanas se define con las anotaciones @GET y @Path y puede producir contenido del tipo de medio XML o JSON.

Este método debe devolver un objeto List y usamos el comparador para ordenar esa lista por la propiedad de variedad.

FruitComparator se ve así:

package com.lyndseypadget.resteasy.model;

import java.util.Comparator;

public class FruitComparator implements Comparator {
	public int compare(F f1, F f2) {
		return f1.getVariety().compareTo(f2.getVariety());
	}
}

Tenga en cuenta que si quisiéramos ordenar por una propiedad específica de Apple, como el color, tendríamos que crear una implementación que se vea diferente de Comparator y nombrarla AppleComparator.

La aplicación

A partir de la versión 3.1.x de RESTEasy, deberá definir una clase que amplíe Application. La documentación de muestra de RESTEasy sugiere que se trata de un solo registro, como por ejemplo:

package com.lyndseypadget.resteasy;

import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

public class FruitApplication extends Application
{
   HashSet singletons = new HashSet();

   public FruitApplication()
   {
      singletons.add(new FruitService());
   }

   @Override
   public Set<Class> getClasses()
   {
      HashSet<Class> set = new HashSet<Class>();
      return set;
   }

   @Override
   public Set getSingletons()
   {
      return singletons;  
   }
}

No necesitaremos hacer mucho con esta clase para el propósito de este ejemplo, pero necesitaremos conectarla a nuestro archivo web.xml, que se describe en la sección “Un poco de cableado del servicio web” más adelante.

Estructuración de colecciones de objetos

Como está escrito, la llamada GET / manzanas devolverá datos como este:

<?xml...
[ad_2]


Varios tipos de medios en microservicios Java con RESTEasy

Esta entrada tiene 0 comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Volver arriba