Creando Api REST
Creando Api REST
PRACTICA DE LABORATORIO
Creando una API REST
OBJETIVO
• Construir una API REST sencilla en java con el fin de conocer su funcionamiento básico.
• Crear un cliente desktop que consuma esta API REST.
Una API REST es una aplicación web en el lado del back-end. Tiene una serie de rutas y métodos que
interactúan con la base de datos y hacen lógica. Por ejemplo, un método que autentique un usuario, otro
En Netbeans 12 o superior, ir al menú File / New Project / Web Application (ver Figura 1). Luego clic
en Next.
Luego colocamos el nombre al proyecto, Grupo Id y Paquete acorde a la Figura 2. Luego clic en Next.
package co.unicauca.products;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* Clase que indice el Path base desde el cual estará respondiendo la API Rest.
* Este path corresponde a la URL a partir de la cual se expondrá nuestros
* servicios. Para lograr esto, será necesario crear una clase que extienda de
* “Application”, esta clase puede llamarse como sea y puede colocarse en
* cualquier paquete.
*
* @author Libardo, Julio
*/
@ApplicationPath("product-service")
public class AppConfiguration extends Application {
package co.unicauca.products.domain.entity;
/**
* Representa un producto de la tienda
*
* @author Libardo, Julio
*/
public class Product {
public Product() {
}
@Override
public String toString() {
return "Product{" + "id=" + id + ", name=" + name + ", price=" + price +
'}';
}
Ahora creamos las clases de la capa de acceso a datos. Se creará la Interface del
Repositorio y dos implementación concretas mediante arreglos.
package co.unicauca.products.access;
import co.unicauca.products.domain.entity.Product;
import java.util.List;
/**
* Interface de los servicios del repositorio
*
* @author Libardo, Julio
*/
public interface IProductRepository {
import co.unicauca.products.domain.entity.Product;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.inject.Default;
/**
* Implementación por defecto. El framewok contenedor de CDI (Contexts and
* Dependency Injection) carga la implementación por defecto.
*
* @author Libardo, Julio
*/
@Default
public class IProductRepositoryImplArrays implements IProductRepository {
/**
* Por simplicidad los datos se cargan en un array.
*/
public static List<Product> products;
public IProductRepositoryImplArrays() {
if (products == null){
products = new ArrayList<>();
initialize();
}
}
@Override
public List<Product> findAll() {
return products;
}
@Override
public Product findById(Integer id) {
@Override
public boolean create(Product newProduct) {
Product prod = this.findById(newProduct.getId());
if (prod != null) {
//Ya existe
return false;
}
products.add(newProduct);
return true;
}
@Override
public boolean update(Product product) {
Product prod = this.findById(product.getId());
if (prod != null) {
prod.setName(product.getName());
prod.setPrice(product.getPrice());
return true;
}
return false;
}
@Override
public boolean delete(Integer id) {
int i = 0;
for (Product prod : products) {
if (prod.getId() == id) {
products.remove(i++);
return true;
}
}
return false;
}
import co.unicauca.products.domain.entity.Product;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Alternative;
public IProductRepositoryImplArrays2() {
if (products == null){
products = new ArrayList<>();
initialize();
}
}
@Override
public List<Product> findAll() {
return products;
}
@Override
public Product findById(Integer id) {
for (Product prod : products) {
if (prod.getId() == id) {
return prod;
}
}
return null;
}
@Override
public boolean create(Product newProduct) {
Product prod = this.findById(newProduct.getId());
if (prod != null) {
//Ya existe
return false;
}
products.add(newProduct);
return true;
}
@Override
public boolean delete(Integer id) {
int i = 0;
for (Product prod : products) {
if (prod.getId() == id) {
products.remove(i++);
return true;
}
}
return false;
}
Ahora la clase ProductService que es una Fachada de acceso al negocio por parte de la
presentación. Se utiliza inyección de dependencias mediante el el framework de
JavaEE
package co.unicauca.products.domain.service;
import co.unicauca.products.access.IProductRepository;
import co.unicauca.products.domain.entity.Product;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
/**
* Fachada de acceso al negocio por parte de la presentación. Usa el repositorio
* por defecto. Si no se pone @Default tambien funciona, pues inyecta la
* implementaició por defecto
*
* @author Libardo, Julio
*/
@RequestScoped
public class ProductService {
/**
* Inyecta una implementación del repositorio
*/
@Inject
@Default
IProductRepository repo;
Finalmente la clase que contiene nuestros servicios web REST Full. La anotación @Path indica la
URL en la cual responderá los servicios. Esta anotación se puede poner a nivel de clase y método. En
este ejemplo todos los servicios comparten el mismo Path, la acción se hacer mediante la anotació GET
(consultar), POST (agregar), PUT (editar), DELETE (eliminar):
package co.unicauca.products.presentation.rest;
import co.unicauca.products.domain.service.ProductService;
import co.unicauca.products.domain.entity.Product;
import java.util.List;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* API REST de los servicios web. Es muy simple por ahora, en otra versión se
* hará una API más robusta. Son nuestros servicios web. La anotación @Path
* indica la URL en la cual responderá los servicios. Esta anotación se puede
/**
* Se inyecta la única implementación que hay de ProductService
*/
@Inject
private ProductService service;
public ProductController() {
/*
Su uso desde consola mediante client url:
curl -X GET http://localhost:8080/Simple-API-REST/product-service/products/
*/
@GET
@Produces({MediaType.APPLICATION_JSON})
public List<Product> findAll() {
return service.findAll();
}
/*
Su uso desde consola mediante client url:
curl -X GET http://localhost:8080/Simple-API-REST/product-
service/products/1
*/
@GET
@Path("{id}")
@Produces({MediaType.APPLICATION_JSON})
public Product findById(@PathParam("id") int id) {
return service.findById(id);
}
/*
Su uso desde consola mediante client url:
curl -X POST \
http://localhost:8080/Simple-API-REST/product-service/products/ \
-H 'Content-Type: application/json' \
-d '{
"id":1,
"name":"Nevera Lg",
"price":6700000
}'
*/
/*
Su uso desde consola mediante client url:
curl -X PUT \
http://localhost:8080/Simple-API-REST/product-service/products/\
-H 'Content-Type: application/json' \
-d '{
"name":"Nevera Lg REF. JDK3-34-343",
"price":2450000
}'
*/
@PUT
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public String update(Product prod) {
if (service.update(prod)) {
return "{\"ok\":\"true\", \"mensaje\":\"Producto
modificado\",\"errores\":\"\"}";
} else {
return "{\"ok\":\"false\", \"mensaje\":\"No se pudo modificar el
producto\",\"errores\":\"Id no existe\"}";
}
}
/*
Su uso desde consola mediante client url:
curl -X DELETE http://localhost:8080/Simple-API-REST/product-
service/products/
*/
@DELETE
@Path("{id}")
public String remove(@PathParam("id") Integer id) {
if (service.delete(id)) {
return "{\"ok\":\"true\", \"mensaje\":\"Producto
borrado\",\"errores\":\"\"}";
} else {
return "{\"ok\":\"false\", \"mensaje\":\"No se pudo borrar el
producto\",\"errores\":\"Id no existe\"}";
}
}
}
El archivo “beans.xml”
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
Ahora se debe desplegar la aplicación, para ello, clic derecho en el proyecto / Run. Se debe abrir el
navegador tal como lo muestra la Figura 7.
Ahora se va a crear una sencilla aplicación desktop en java que consuman los servicios web creados en
la sección anterior.
El primer paso es crear el proyecto, clic en el menú File / New Project / Java with Maven/Java
Application y seguir los pasos del asistente. El nombre del proyecto será Cliente-Rest (ver Figura 9):
package co.unicauca.cliente;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;
/**
* Jersey REST client generated for REST resource:ProductController
* [products]<br>
* USAGE:
* <pre>
* NewJerseyClient client = new NewJerseyClient();
* Object response = client.XXX(...);
* // do whatever with response
* client.close();
* </pre>
*
* @author libardo
public NewJerseyClient() {
client = javax.ws.rs.client.ClientBuilder.newClient();
webTarget = client.target(BASE_URI).path("products");
}
Finalmente, se crea una clase ClienteMain que utilice los métodos de la clase
NewJerseyClient.
package co.unicauca.cliente;
/**
*
* @author Libardo, Julio
*/
public class ClienteMain {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// CREANDO UN ESTUDIANTE
NewJerseyClient jersey = new NewJerseyClient();
String rta = jersey.create_JSON(new Product(5, "Nevera Lg", 4000000d));
System.out.println("Rta " + rta);
// BUSCANDO UN PRODUCTO
Product product = jersey.findById(Product.class, "1");
System.out.println(product.getId());
System.out.println(product.getName());
System.out.println(product.getPrice());
}
Esta aplicación cliente también necesita la clase Product. Se puede copiar/pegar la misma del proyecto
Simple-API-REST.
FIN!