miércoles, 6 de noviembre de 2019

Cliente Standalone de JAX-RS (o cualquier endpoint RESTful)

  No hay comentarios.


Si tenemos una aplicación standalone (puede ser un JavaFX, de línea de comandos, batch, etc) que necesite consumir un endpoint hecho en RESTful, por lo general usaríamos algo como esto:

public class RestClient {
  
    private static final String REST_URI 
      = "http://localhost:8082/spring-jersey/resources/employees";
  
    private Client client = ClientBuilder.newClient();
 
    public Employee getJsonEmployee(int id) {
        return client
          .target(REST_URI)
          .path(String.valueOf(id))
          .request(MediaType.APPLICATION_JSON)
          .get(Employee.class);
    }
    //...
}

(Tomado de https://www.baeldung.com/jersey-jax-rs-client)

Lo cual no está mal, pero creo que debería ser lo más transparente posible. ¿Cómo es eso?
Si ven en la línea 13 del código anterior, significa que hay que decirle que haga un GET a la petición, además de pasarle el tipo de respuesta y otras cosas más. La cuestión se volvería algo compleja si queremos hacer otras peticiones como POST, DELETE, etc.

Pues aquí vengo con una solución que encontré revisando la documentación de JAX-RS.

El servidor

Para este ejemplo, he creado un pequeño servidor CRUD en Payara Micro, el cual puedes obtener su código aquí: https://github.com/apuntesdejava/demo-jaxrs-standalone/tree/master/demo-jaxrs-server

El Endpoint principal es este:
@Path("person")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
@ApplicationScoped
public class PersonEndpoint {

    @Inject
    private PersonRepository personRepository;

    @POST
    public Response create(PersonParam param) {
        Person p = personRepository.create(param.getName(), param.getEmail());
        return Response.ok(p).build();
    }

    @GET
    public Response list() {
        List<Person> list = personRepository.findAll();
        return Response.ok(list).build();
    }
    
    @DELETE
    @Path("{id}")
    public Response delete(@PathParam("id")long personId){
        personRepository.delete(personId);
        return Response.ok().build();
    }

}

El cual tiene tres métodos principales:

  • @POST create() para insertar registros
  • @GET list() para leer todos los registros
  • @DELETE delete() para borrar un registro
Una manera para probarlo es ejecutándolo y llamando desde un cliente:

Insertando un registro:

Listando los registros:

Borrando ese registro (en mi caso, el 97)

El Cliente

En el cliente tiene que existir un método que luzca igual que la clase del endpoint servidor para que sea "transparente" la invocación.

@Path("person")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public interface PersonEndpoint {

    @POST
    Response create(PersonParam param);

    @GET
    Response list();

    @DELETE
    @Path("{id}")
    Response delete(@PathParam("id") long personId);
}

Pero esto tiene un tratamiento muy especial: no es una clase, es una interfaz. Aquí es lo divertido ¿cómo es que lo podrá identificar cada petición? Pues esta es la magia del cliente JAX-RS.

Hay varios clientes de JAX-RS, algunos son:

  • RestEasy: https://github.com/resteasy/resteasy-examples/tree/3.6.0.Final/jaxrs-2.0/simple-client
  • Quarkus: https://quarkus.io/guides/rest-client
  • Apache CXF: https://cxf.apache.org/
Aquí usaré el Apache CXF. Independientemente puede usarse cualquier implementación, pero seguirá siendo la misma interfaz. Solo cambia cómo se invoca al Endpoint del Cliente.

Así se construye usando Apache CXF:
        PersonEndpoint client = JAXRSClientFactory.create(
                REST_URI,
                PersonEndpoint.class,
                Arrays.asList(
                        new JacksonJaxbJsonProvider()
                ));

Luego, se llama como si fuera cualquier método "local":
        PersonParam param = new PersonParam("persona 1", "abc@mail.com"); //creo los parámetros
        Response resp = client.create(param); //invoco al endpoint
        LOG.log(Level.INFO, "status:{0}", resp.getStatusInfo().getReasonPhrase()); //muestro la respuesta
        if (resp.getStatus() == Response.Status.OK.getStatusCode()) { //si está ok...
            Person p = resp.readEntity(Person.class); //.. convierto la petición en la entidad que se recibió...
            LOG.log(Level.INFO, "-> registro insertado:{0}", p.toString()); //... y muestro el contenido
        }

Si deseamos listar, también se haría lo mismo:
        resp = client.list(); //invocamos el método de listado
        LOG.log(Level.INFO, "status:{0}", resp.getStatusInfo().getReasonPhrase()); //mostramos el resultado...
        List<Person> list = null;  //preparamos nuestra lista que vamos a recibir
        if (resp.getStatus() == Response.Status.OK.getStatusCode()) { //evaluamos el contenido... si está OK...
            list = resp.readEntity(new GenericType<List<Person>>() {  //... convertimos la petición en el listado
            });
            list.forEach((p) -> { //... y podemos listar el contenido.
                LOG.log(Level.INFO, "id:{0}\tname:{1}\temail:{2}", new Object[]{p.getPersonId(), p.getName(), p.getEmail()});
            });
        }

Código fuente

El código fuente para este proyecto se puede encontrar aquí:


sábado, 12 de octubre de 2019

viernes, 9 de agosto de 2019

Liferay 7.2. Service Layer - Creando entidades y servicios

  No hay comentarios.
Sigamos con Liferay, ahora con el tema Service Layer.

Liferay Service Builder es una herramienta de generación de código que permite, usando un archivo xml, generar una capa completa de servicios. La generación de código incluye definciones de base de datos, código para caché y persistencia, clases de servicios con métodos CURD y la capa de servicios remotos con compatibilidad con JSON y SOAP Web Services.

¡Y todo esto con un solo archivo service.xml !


miércoles, 17 de julio de 2019

lunes, 15 de julio de 2019

viernes, 12 de julio de 2019

Jakarta EE 8 | JSF: Formulario con campo enum y LocalDate

  3 comentarios
Siguiendo con nuestra serie de JSF (en Jakarta EE 8) hoy veremos cómo manejar campos de tipo enum y LocalDate.

Estos campos no son comunes para manejar en un formulario web, donde generalmente se maneja en campos de tipo String.

Veremos que Jakarta EE 8 manipula los de tipo enum de una manera transparente, mientras que los LocalDate necesita de una pequeña ayuda usando un javax.faces.convert.Converter.


jueves, 11 de julio de 2019

martes, 9 de julio de 2019

martes, 11 de junio de 2019

Inicializadores en Java

  No hay comentarios.
La inicialización es el asignar un valor inicial cuando se declara una variable. Esto se puede poner en los atributos de las clases:
//...
public class OrdenCompra{
    private java.util.Date fecha=new java.util.Date();
//...

Este ejemplo clásico, significa que cuando se instancie un nuevo objeto de OrdenCompra se le asignará un valor inicial (la fecha y hora actual) a la propiedad fecha.

De eso estamos de acuerdo todos. Pero un inicializador va más allá de una simple asignación en tiempo de ejecución.

lunes, 10 de junio de 2019

lunes, 29 de abril de 2019

"Punteros a métodos" en Java

  No hay comentarios.
Una de las cosas que extrañaba de C en Java es la capacidad de apuntar a una función. En lugar de invocar a una función directamente, podía hacerlo a través de una variable. Esto es: no importa a qué apunta a esa variable, cuando se invoca con los parámetros correctos, lo ejecutará.

En Java lo más cercano que se podía hacer era usando polimorfismo. A partir de Java 8 apareció lo que veremos en este post.

viernes, 12 de abril de 2019

martes, 12 de marzo de 2019

Conociendo JSF: navegación entre páginas

  No hay comentarios.

Comenzaremos una serie de vídeos para conocer Jakarta EE.

En este vídeo conoceremos:


  • Cómo crear una aplicación JSF usando NetBeans 10
  • Crear páginas JSF
  • Navegación entre las páginas
  • Uso básico de ManagedBeans para guardar información y compartirlas entre páginas.




Si te gustó y te es útil el vídeo, haz clic en "Me gusta". Con eso me ayudas a subir más vídeos de este tipo.

No te olvides de suscribirte a mi canal y darle clic en la campana para que te enteres cuando publico un nuevo vídeo.

Si necesitas asesoría en Java para la Universidad, no dudes en escribirme a asesoria@apuntesdejava.com

miércoles, 20 de febrero de 2019

Instalando Apache NetBeans 10 y configurarlo con Jakarta EE

  No hay comentarios.
En este vídeo cómo instalar el Apache NetBeans 10 y también configuarlo para que funcione con Jakarta EE.





Los archivos descargados son los siguientes:

También deberíamos tener instalado tanto el Java 8, como el JDK 11. El IDE necesita del JDK 11, y los servidores como Payara, Tomcat necesitan de Java 8, es por ello que lo tengo preinstalados.

La instalación de JDK 11 es bastante simple:
  1. Descargar de aquí el .zip https://jdk.java.net/11/
  2. Descomprimir el .zip.. y listo.
Para el Java 8 (si estamos en Windows) se tendría que descargar de la página de oracle (https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) e instalarlo como un software de Windows.

O.. (mejor aún) descargar la distribución de Amazon: Amazon Corretto 8: https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html