Imprimir

Arquitectura REST

REST (Transferencia de Estado Representacional - Representational State Transfer) es un estilo de intercambio de información entre aplicaciones cliente y servidor, en el que se utiliza el protocolo HTTP para el envío y recepción de datos empleando alguno de los formatos de documentos de datos como XML, JSON, etc. Los sistemas que utilizan esta arquitectura se suelen denominar RESTful.

Para ello, la aplicación cliente se comunica con la aplicación servidor empleado alguno de los métodos utilizados por el protocolo HTTP para la petición de datos (también se conoce como "verbos"). En la arquitectura REST se suelen utilizar los siguientes métodos de HTTP:

La idea consiste en que si una aplicación envía una solicitud GET a un servidor con algo como http://servidor.com/productos, el servidor le retornará un documento XML o JSON con la lista de productos. O bien, otro ejemplo podría ser que se enviara una petición PUT a la misma dirección, enviando al servidor los datos actualizados de un determinado producto en formato XML o JSON, y el servidor almacenará los nuevos datos en su base de datos.

Esta arquitectura es utilizada por varios sitios web muy populares como Twitter, Google, PayPal, etc. Gracias a ello, se pueden desarrollar aplicaciones cliente que puedan intercambiar datos con esos sitios web y así poder mostrar en el cliente la información que se encuentra en el servidor de la manera que se desee. Por otro lado, se podrán actualizar los datos en el servidor utilizando una aplicación desarrollada para el cliente. Por ejemplo, utilizando la REST API de Twitter, puedes desarrollar una aplicación de escritorio que obtenga los mensajes del usuario y los muestre de la manera que desees, y también podrías desarrollar la aplicación para que envíe mensajes a Twitter que sean escritos usando el interfaz de tu aplicación. 

Puedes encontrar más información en:

Aquí puedes ver como puedes usar esta arquitectura con algunos sitios web, de manera que puedas obtener y actualizar la información gestionada por esos servicios desde una aplicación que desarrolles tú mismo:

Puedes hacer algunas pruebas de funcionamiento usando la API Console Tool de Twitter: https://dev.twitter.com/rest/tools/console

Servlet Java para atender peticiones REST usando XML

Crea o utiliza un proyecto de tipo Java Web > Web Application y dentro de los paquetes de fuentes (Source Packages) crea una clase Java de tipo Servlet (conviene crear siempre las clases Java dentro de un paquete determinado, por lo que deberás crear un paquete donde alojar la clase Servlet). En el caso de este ejemplo se ha creado una clase llamada RestItems. Al tratarse de un proyecto de ejemplo, se va a gestionar un tipo de información genérica, que se va a denominar Item, que almacenará información de distinto tipo, sin un significado concreto.

La estructura general del Servlet es como la siguiente (donde se han eliminado comentarios y otros elementos que no son relevantes para este caso):

@WebServlet(name = "RestItems", urlPatterns = {"/RestItems"})
public class RestItems extends HttpServlet {
 
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet RestItems</title>");            
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet RestItems at " + request.getContextPath() + "</h1>");
            out.println("</body>");
            out.println("</html>");
        }
    }
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
 
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
 
}

Observa que se han creado los métodos doGet y doPost sobrecargando (override) los mismos métodos de la clase original Servlet. Ten en cuenta que ambos métodos se encuentran ocultos inicialmente dentro de la sección que aparece con el texto:

HttpServlet methods. Click on the + sign on the left to edit the code.

Por tanto, asegúrate de expandir ese bloque para ver su contenido.

Como puedes observar, la única acción que realizan ambos métodos es llamar al método processRequest que realizará todas las operaciones del Servlet. En el código que se genera automáticamente, lo que realiza el método processRequest es generar un documento HTML con un texto de prueba.

Asegúrate de que tienes instalado correctamente el servidor de aplicaciones web Java (Tomcat, Glassfish o similar) ejecutando el Servlet que acabas de crear. Puedes hacerlo usando el menú contextual y eligiendo la opción Run File.

Debe aparecer en el navegador web el texto de prueba que aparecía en el método processRequest.

Métodos doGet, doPost, doPut y doDelete

Como se ha comentado anteriormente, la arquitectura REST hace uso de las peticiones GET, POST, PUT y DELETE por HTTP, y en el código del Servlet que se ha generado ya aparecen los método doGet y doPostque serán los que se ejecuten cuando un cliente haga una llamada al Servlet usando el método GET o POST en cada caso. Por tanto, queda crear los métodos similares para las peticiones que usen PUT y DELETE, es decir, doPut y doDelete. La manera más sencilla de hacerlo es que NetBeans genere automáticamente el código de las cabeceras de ambos métodos de la clase Servlet que hay que sobrecargar, usando el menú Source > Insert Code > Override method (o desde el menú contextual) y marcar los métodos doPut y doDelete.

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        super.doDelete(req, resp); 
        processRequest(req, resp);
    }
 
    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        super.doPut(req, resp); 
        processRequest(req, resp);
    }

Las acciones que deben realizarse en cada caso (GET, POST, PUT, DELETE) serán diferentes en cada caso, aunque con bastantes similitudes, por lo que se va a centralizar todo el código que escribamos dentro del método processRequest, como se sugiere en el código que se ha generado automáticamente al crear el Servlet. Por tanto, en los 2 métodos que se acaban de crear, puedes eliminar la llamada al método original (super.doDelete() y super.doPut()), aunque se podrían dejar, y añade la llamada al método processRequest de manera similar a la que aparece en los método doGet y doPost, aunque observa que el nombre de los parámetros que se han generado en la cabecera del doDelete y doPut son diferentes (req y resp), por lo que hay que usar esos nombres en la llamada a processRequest o bien cambiar los nombres de esos parámetros.

Para que en el método processRequest se pueda diferenciar si se está ejecutando ese método a raíz de una llamada desde doGet, doPost, doPut o doDelete, se puede crear una propiedad en la clase, que almacene un valor diferente en cada caso. Esto requiere añadir una sentencia switchdentro del método processRequest, donde se encaminará la ejecución dependiendo del tipo de llamada que se haya hecho. Observa que se ha incluido dentro de las etiquetas <body></body> para poder mostrar posteriormente algo en pantalla como contenido de la página web que se genera. Puede quedar algo así:

@WebServlet(name = "RestItems", urlPatterns = {"/RestItems"})
public class RestItems extends HttpServlet {
 
    public static final byte PETICION_GET = 0;    // SELECT
    public static final byte PETICION_POST = 1;   // INSERT
    public static final byte PETICION_PUT = 2;    // UPDATE
    public static final byte PETICION_DELETE = 3; // DELETE
 
    private byte tipoPeticion;
 
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet RestItems</title>");            
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Servlet RestItems at " + request.getContextPath() + "</h1>");            

            switch (tipoPeticion) {
                case PETICION_GET:
                    // Escribir aquí las accciones para peticiones por GET
                    break;
                case PETICION_POST:
                    // Escribir aquí las accciones para peticiones por POST
                    break;
                case PETICION_PUT:
                    // Escribir aquí las accciones para peticiones por PUT
                    break;
                case PETICION_DELETE:
                    // Escribir aquí las accciones para peticiones por DELETE
                    break;
                default:
                    break;
            }     
 
            out.println("</body>");
            out.println("</html>");
        } finally {
            out.close();
        }
 
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        tipoPeticion = PETICION_GET;
        processRequest(request, response);
    }
 
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        tipoPeticion = PETICION_POST;
        processRequest(request, response);
    }
 
    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        tipoPeticion = PETICION_DELETE;
        processRequest(req, resp);
    }
 
    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        tipoPeticion = PETICION_PUT;
        processRequest(req, resp);
    }
 
}

Clases entidad (entity classes) o clases POJO

Para poder manipular la información a través de documentos XML, es conveniente crear una clase para cada entidad de información que gestione la aplicación, así como otra clase que permita almacenar una lista de objetos de cada entidad. En el caso del ejemplo que se está elaborando en este artículo, se va a gestionar un tipo de entidad genérico al que se le va a dar el nombre de Item. En un ítem se va a almacenar información de distintos tipos de datos, por ejemplo, una cadena de caracteres (String), un valor numérico, una fecha, etc. Simplemente para que permita conocer el funcionamiento de este tipo de arquitecturas para un caso genérico.

Clase Item

La clase Item, va a tener, por tanto, una estructura como la siguiente. Observa que se han incluido anotaciones para que esta clase pueda ser gestionada por la librería JAXB de Java que facilita la generación y procesado de documentos XML. En caso de que dispongas de una base de datos con una tabla asociada a la clase entidad de los datos que deseas gestionar, puedes crear esta clase automáticamente desde NetBeans usando el asistente New > Entity Classes from Database que encontrarás en el menú contextual del proyecto.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Item {
 
    @XmlElement
    private int id;
    @XmlElement
    private String astring;
    @XmlElement
    private int anumber;
    @XmlElement
    private Date adate;
 
    public Item() {
    }
 
    public Item(int id, String astring, int anumber, Date adate) {
        this.id = id;
        this.astring = astring;
        this.anumber = anumber;
        this.adate = adate;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getAstring() {
        return astring;
    }
 
    public void setAstring(String astring) {
        this.astring = astring;
    }
 
    public int getAnumber() {
        return anumber;
    }
 
    public void setAnumber(int anumber) {
        this.anumber = anumber;
    }
 
    public Date getAdate() {
        return adate;
    }
 
    public void setAdate(Date adate) {
        this.adate = adate;
    }
 
}

Clase Items

La clase Items, que va a permitir crear objetos que contengan una lista de objetos de tipo Item, será como la siguiente:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Items {
 
    // A la etiqueta que identifique el inicio y fin de cada item en el XML, se le va
    //  a llamar 'item' en lugar de 'itemlist'
    @XmlElement(name = "item")
    private List<Item> itemsList;
 
    public Items() {
        itemsList = new ArrayList();
    }
 
    public List<Item> getItemsList() {
        return itemsList;
    }
 
    public void setItemsList(List<Item> itemsList) {
        this.itemsList = itemsList;
    }
 
}

Lista de objetos incluyendo algunos datos de muestra

Continuando con el desarrollo de la clase Servlet, se debe declarar e inicializar un objeto donde se vaya a almacenar la lista de objetos Item que vaya a gestionar la aplicación. En caso de que la aplicación gestionara los datos almacenados en una base de datos, esta lista se cargaría con datos de ese almacén, pero en este ejemplo, por simplificación, no se obtendrán los datos de ninguna base de datos. Por tanto, los datos estarán almacenados en memoria RAM, lo que conlleva que se perderán los cambios al reiniciar la aplicación del servidor.

Para poder realizar algunas pruebas de consulta de los datos, se pueden añadir algunos objetos de tipo Item de muestra. Estos objetos sólo se añadirán a la lista que se encuentra dentro del objeto items en caso de que la lista se encontrara vacía, con el fin de evitar que se añadieran esos objetos de muestra cada vez que se ejecute el Servlet y se volvieran a añadir los mismos objetos una y otra vez. 

    private Items items = new Items();
 
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // En caso de que la lista esté vacía, se van a generar algunos objetos
        //  de muestra para las pruebas, que se añadirán a la lista que se 
        //  encuentra dentro del objeto items. Se indica como fecha, la del día actual
        if(items.getItemsList().isEmpty()) {
            items.getItemsList().add(new Item(1, "Primero", 111, Calendar.getInstance().getTime()));
            items.getItemsList().add(new Item(2, "Segundo", 222, Calendar.getInstance().getTime()));
            items.getItemsList().add(new Item(3, "Tercero", 333, Calendar.getInstance().getTime()));
        }
 
        // ...

Consulta de datos (GET)

Mostrar contenido de la lista como resultado de petición GET

Para ir probando que el funcionamiento de la aplicación del servidor es correcto, se puede mostrar el contenido de la lista en la página web que genera el Servlet. Por defecto, cuando una página web se carga desde el navegador web, se está haciendo una llamada usando el método GET, por lo que vamos a meter el código correspondiente en la sección del caso GET:

            out.println("<h1>Servlet RestItems at " + request.getContextPath() + "</h1>");            
 
            switch (tipoPeticion) {
                case PETICION_GET:
                    // Recorrer todos los elementos de la lista almacenada en items
                    for(Item item : items.getItemsList()) {
                        // Se muestra, por ejemplo, el id y la cadena de caracteres
                        out.println(item.getId() + ": " + item.getAstring() + "<br>");
                    }
                    break;
                case PETICION_POST:
                    // Escribir aquí las accciones para peticiones por POST
                    break;
                case PETICION_PUT:
                    // Escribir aquí las accciones para peticiones por PUT
                    break;
                case PETICION_DELETE:
                    // Escribir aquí las accciones para peticiones por DELETE
                    break;
                default:
                    break;
            }     
 

Si ejecutas de nuevo este Servlet (recuerda ejecutar la clase, no el proyecto), podrás ver en el navegador web el contenido de la lista que hayas indicado que se muestre:

Generación de la consulta de datos como XML

Pero en la arquitectura REST no se desea obtener la información en formato HTML, sino como XML para que luego pueda ser procesada la información más cómodamente. Por ello, hay que indicar que la salida generada por el Servlet va a ser de tipo XML, y se usará el método marshall de la librería JAXB para convertir en formato XML el objeto que contiene la lista. Observarás que es obligatorio añadir una captura de la excepción JAXBException para usar los métodos de JAXB.

//        response.setContentType("text/html;charset=UTF-8");
        response.setContentType("text/xml;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            /* TODO output your page here. You may use following sample code. */
//            out.println("<!DOCTYPE html>");
//            out.println("<html>");
//            out.println("<head>");
//            out.println("<title>Servlet RestItems</title>");            
//            out.println("</head>");
//            out.println("<body>");
 
            JAXBContext jaxbContext = JAXBContext.newInstance(Items.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            switch (tipoPeticion) {
                case PETICION_GET:
                    // Convertir a XML el contenido de items, generando el resultado en out
                    jaxbMarshaller.marshal(items, out);
                    break;
                case PETICION_POST:
                    // Escribir aquí las accciones para peticiones por POST
                    break;
                case PETICION_PUT:
                    // Escribir aquí las accciones para peticiones por PUT
                    break;
                case PETICION_DELETE:
                    // Escribir aquí las accciones para peticiones por DELETE
                    break;
                default:
                    break;
            }     
 
//            out.println("</body>");
//            out.println("</html>");
        } catch (JAXBException ex) {
            Logger.getLogger(RestItems.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            out.close();
        }

Al ejecutar el Servlet, deberás obtener en el navegador web el contenido XML generado:

Aplicación cliente de prueba para mostrar resultado de GET

Puedes crear una clase principal Java en un nuevo proyecto de aplicación Java (normal), para probar que se pueden obtener los datos del servidor mostrándolos en una aplicación cliente. Ten en cuenta que en este nuevo proyecto también debes tener las clases Item e Items que puedes copiar del proyecto web que has elaborado antes.

Una vez recibidos los datos como XML, se deben transformar a objetos Java, utilizando la clase entidad (Items) que se ha declarado con una propiedad de tipo lista, pudiendo almacenar en ella cada uno de los objetos que se reciban. para hacer la conversión de XML a objeto Java, se usará el método unmarshall de la clase Unmarshaller que también se encuentra en el paquete javax.xml.bind de Java.

El código puede ser como el siguiente:

public class EjemploRestfulItemsGet {
 
    public static void main(String[] args) {
        try {
            // Crear una conexión con la URL del Servlet
            String strConnection = "http://localhost:8080/EjemploRestfulItems/RestItems";
            URL url = new URL(strConnection);
            URLConnection uc = url.openConnection();
            HttpURLConnection conn = (HttpURLConnection) uc;
            // La conexión se va a realizar para poder enviar y recibir información
            //   en formato XML
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-type", "text/xml");
            // Se va a realizar una petición con el método GET
            conn.setRequestMethod("GET");
 
            // Ejecutar la conexión y obtener la respuesta
            InputStreamReader isr = new InputStreamReader(conn.getInputStream());
 
            // Procesar la respuesta (XML) y obtenerla como un objeto de tipo Items
            JAXBContext jaxbContext = JAXBContext.newInstance(Items.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Object response = jaxbUnmarshaller.unmarshal(isr);
            isr.close();
 
            // Convertir a la clase Items el objeto obtenido en la respuesta
            Items items = (Items)response;
 
            // Como ejemplo, se mostrará en la salida estándar alguno de los datos
            //  de los objetos contenidos en la lista que se encuentra en items
            for(Item item : items.getItemsList()) {
                System.out.println(item.getId() + ": " + item.getAstring());
            }
 
        } catch (JAXBException ex) {
            Logger.getLogger(EjemploRestfulItemsGet.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(EjemploRestfulItemsGet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
 
}

Si ejecutas esta clase, se puede obtener como resultado, en la salida estándar:

Inserción de nuevos objetos (POST)

Cambios en la aplicación del servidor (Servlet)

La aplicación que estamos desarrollando en el lado del servidor recibirá en formato XML la lista de objetos que se desean añadir. Esto será gestionado como una inserción de nuevos elementos en caso de que la petición al servidor haya llegado usando una llamada desde el cliente usando el método POST, ya que ese es el método asignado en la arquitectura REST para el envío de nuevos elementos al servidor.

Para hacer esta operación volvemos a necesitar hacer la operación de convertir datos XML a objetos Java, por lo que se volverá a usar el método unmarshall de manera similar a que se ha empleado anteriormente en la aplicación cliente para procesar los datos obtenidos como resultado de una consulta GET.

            JAXBContext jaxbContext = JAXBContext.newInstance(Items.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            switch (tipoPeticion) {
                case PETICION_GET:
                    // Convertir a XML el contenido de items, generando el resultado en out
                    jaxbMarshaller.marshal(items, out);
                    break;
                case PETICION_POST:
                    // Obtener la lista de items que se quieren insertar
                    Items newItems = (Items) jaxbUnmarshaller.unmarshal(request.getInputStream());
                    // Recorrer la lista obteniendo cada objeto contenido en ella
                    for(Item item :  newItems.getItemsList()) {
                        // Añadir cada objeto a la lista general
                        items.getItemsList().add(item);
                    }
                    break;
                case PETICION_PUT:
                    // Escribir aquí las accciones para peticiones por PUT
                    break;
                case PETICION_DELETE:
                    // Escribir aquí las accciones para peticiones por DELETE
                    break;
                default:
                    break;
            }

Aplicación cliente de prueba para petición POST

Para probar el funcionamiento de la inserción de objetos se puede crear una clase Java ejecutable (con método main), que haga las funciones de aplicación cliente de manera similar a la aplicación que se ha creado antes para probar la comunicación por GET para la consulta de datos.

La diferencia en este caso es que se indica que la comunicación se va a realizar usando POST. Por otro lado, para probar la inserción de nuevos objetos, es necesario disponer de algún objeto que será el que se envíe al servidor, y en este ejemplo se va a crear un contenido aleatorio para el objeto Item. En este ejemplo, el objeto Item creado se añadirá dentro de la lista de un objeto Items, que será el que se envíe finalmente al servidor,

Usando la conexión que se establece con el servidor, se enviará en formato XML el objeto o los objetos que se desean enviar al servidor. Se podría enviar un único objeto, en cuyo caso se indicaría en el contexto de JAXB (JAXBContext.newInstance) la clase Item, pero con el fin de poder enviar varios objetos a la vez, y por mantener el mismo código que para las otras operaciones, se enviará al servidor un objeto Items (el que contiene una lista de objetos Item).

El envío de los datos al servidor en formato XML se prepara con el método marshall, indicando como segundo parámetro la conexión que se ha realizado con el servidor usando conn.getOutputStream(). Será la llamada a conn.getInputStream() la que haga finalmente la conexión con el servidor y obtenga los datos de respuesta que envía de vuelta al cliente. En este ejemplo, el Servlet no se ha sido programado para que envíe algún dato de vuelta tras realizar la petición POST, pero sería conveniente que enviara alguna información de vuelta para informar al cliente que se ha realizado bien el proceso. Un opción podría ser enviar de vuelta el mismo objeto que ha recibido el servidor, lo cual se puede programar añadiendo el mismo código que se ha empleado para el GET, y la aplicación cliente debería leer esos datos (también usando un código como el utilizado en la aplicación cliente del GET).

public class EjemploRestfulItemsPost {
 
    public static void main(String[] args) {
        try {
            String strConnection = "http://localhost:8080/EjemploRestfulItems/RestItems";
            URL url = new URL(strConnection);
            URLConnection uc = url.openConnection();
            HttpURLConnection conn = (HttpURLConnection) uc;
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-type", "text/xml");
 
            // Se va a realizar una petición con el método POST
            conn.setRequestMethod("POST");
 
            // Se crea un nuevo objeto, con contenido aleatorio, que será el que
            //  se envíe al servidor
            Item item = new Item();
            Random random = new Random();
            item.setId(random.nextInt(1000));
            String cadenaAleatoria = "";
            for(int i=0; i<10; i++) {
                cadenaAleatoria += (char)('A' + random.nextInt(26));
            }
            item.setAstring(cadenaAleatoria);
 
            // Aunque sólo se va a enviar un único objeto, se utilizará un objeto
            //  de la clase Items que almacenará dicho objeto. Se va a hacer
            //  así para usar siempre la clase Items al generar los XML
            Items items = new Items();
            items.getItemsList().add(item);
 
            // Convertir objeto items a XML y preparar para enviar al servidor
            JAXBContext jaxbContext = JAXBContext.newInstance(Items.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.marshal(items, conn.getOutputStream());
            // Ejecutar la conexión y obtener la respuesta
            InputStreamReader isr = new InputStreamReader(conn.getInputStream());
 
        } catch (JAXBException ex) {
            Logger.getLogger(EjemploRestfulItemsPost.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(EjemploRestfulItemsPost.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
 
}

Para probar el funcionamiento de la aplicación cliente que usa POST, asegúrate de haber ejecutado previamente el Servlet, y luego ejecuta una o varias veces la aplicación del POST. Luego ejecuta la aplicación cliente que se había creado antes para probar la consulta de datos con GET, y se deberían mostrar en la salida estándar los 3 objetos que se crear inicialmente desde dentro del código del Servlet, más un objeto nuevo con contenido aleatorio por cada ejecución que hayas realizado de POST.

 

Actualización de datos (PUT) y borrado (DELETE)

Las acciones que debe realizar el Servlet al recibir una petición PUT o DELETE son muy similares a las realizadas para el POST. Entre otras cosas, habrá que tener en cuenta, que antes de actualizar o eliminar un objeto, habrá que buscarlo en la lista de objetos que se esté gestionando en el Servlet. La manera de localizar el objeto en la lista dependerá de la información contenida en los objetos. En este ejemplo de la clase Item, habría que localizar en la lista (recorriéndola) el objeto cuyo ID coincide con el ID del objeto que el cliente envía al servidor. Una vez localizado el objeto con ese ID, habrá que actualizar el resto de los datos (para el caso PUT) o eliminarlo (para el DELETE).