jueves, 26 de diciembre de 2019

Instalar Apache TOMCAT

Descarga

Para ello debemos dirigirnos al sitio oficial de Apache TOMCAT mediante la búsqueda en un buscador como "Google" u otro de nuestra preferencia. Caso contrario ingresar al Link: https://tomcat.apache.org/download-90.cgi



Luego descargar el que se desee según el sistema operativo que posean:

  • 32-bit Windows zip (pgp, sha512): nos descarga para una arquitectura de 32 bits
  • 64-bit Windows zip (pgp, sha512): nos descarga para una arquitectura de 64 bits
  • 32-bit/64-bit Windows Service Installer (pgp, sha512): nos descarga un instalador para arquitecturas de 32 o 64 bits


En mi caso elegí el comprimido de 64 bits, luego descomprimir el archivo en donde deseemos tener nuestro servidor, por ejemplo:


Creando usuarios

En algunas aplicaciones, nos requerirá emplear un usuario. Para ello, nos dirigimos a la carpeta de descarga del servidor y ubicamos el archivo XML llamado: "tomcat-users.xml"

Abrimos el archivo y buscamos casi al final las siguientes líneas

<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->


Agregamos luego:
<user username="root" 
password="tomcat" 
roles="manager-script,admin,manager-gui" />

Ahí indicamos un nuevo usuario con nombre "root" y contraseña "tomcat" y los roles de:

  • manager-script
  • admin
  • manager-gui


Configurando el servidor en Eclipse

Abrimos Eclipse, luego vamos a crear un proyecto web dinámico

Posteriormente, agregamos un "Runtime", dándole clic al botón "New Runtime..." ahí seleccionamos la versión del Apache que hemos descargado y deseamos conectar. Además, podemos crear un Servidor local. Luego le damos clic a "Finalizar"


Observaremos en el lado de los proyectos que se creó uno nuevo llamado Servers y si lo expandimos encontraremos nuestro servidor. Desde la consola podemos iniciar nuestro servidor, pero si lo deseamos ver funcionando terminamos de crear el proyecto web dinámico y creamos un JSP, luego hacemos ejecutar el proyecto en el servidor ("Run on Server")


 Podremos apreciar un URL, podemos copiarlo a un navegador y con ello finalizado la instalación y configuración.

Configurando el servidor en NetBeans

Abrimos NetBeans y nos vamos a la sección de Servicios (si no se ven puedes ingresar Ctrl + 5 o desde el menú "Window" o ventanas).

Damos clic derecho y agregar un nuevo servidor en la opción "Server" o servidores como se aprecia en la siguiente imagen.


Seleccionamos un nuevo servidor de Apache Tomcat


Especificamos la ruta donde se descomprimió la carpeta, ingresamos las credenciales "root" con "tomcat" y desmarcamos la opción de crear un usuario.



Iniciamos el servidor, quizás nos pedirá usuario y contraseña, ingresamos las credenciales indicadas al inicio en el XML y luego clic a Aceptar y el servidor iniciará




Así tenemos el Apache configurado tanto para Eclipse como para Netbeans.


jueves, 24 de octubre de 2019

Cargar datos en una lista desplegable

Supongamos que queremos agregar un registro a una tabla que se relaciona mediante una clave foránea con otra, solo requiere que se le ingrese el código o id, pero colocar ello en una caja de texto es incómodo, lo ideal sería desplegar en una lista desplegable vertical los registros de la tabla cuyo identificador o código queremos mostrar. Ilustremos ello con un ejemplo:

Sin lista desplegable Con lista desplegable

Agregar datos







Agregar datos








Trabajaremos con las siguientes tablas:


Además, le vamos a crear una vista a la tabla "pagos" (para saber como crear este código paso a paso has clic aquí)

Si deseas ver la implementación para visualizar la tabla "pagos" en un JSP (has clic aquí)

Primero vamos a crear una función en el "DaoInquilinos" (clic aquí para ver como realizar el DAO):
package dao;
import java.util.List;
import dto.Inquilinos;

public interface DaoInquilinos {
    public List <Inquilinos> inquilinosSel();
    public Inquilinos inquilinosGet(Integer id);
    public String inquilinosIns(Inquilinos inquilino);
    public String inquilinosUpd(Inquilinos inquilino);
    public String inquilinosDel(List<Integer> ids);
    public List<Object[]> inquilinosCbo();
    public String getMessage();
}

Y la implementación para la función "inquilinosCbo"sería en el "DaoInquilinosImpl.java" (clic aquí para ver la implementación completa):
 
    @Override
    public List<Object[]> inquilinosCbo() {
        List<Object[]> list = null;
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno")
                .append(" FROM inquilinos");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();
            list = new ArrayList<>();
            while (rs.next()) {
                Object[] inquilino = new Object[5];                
                inquilino[0]=rs.getInt(1);
                inquilino[1]=rs.getString(2);
                inquilino[2]=rs.getString(3);
                inquilino[3]=rs.getString(4);
                inquilino[4]=rs.getString(5);
                list.add(inquilino);
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return list;
    }
 


En "PagosValidator" agregar una función llamada "pagosCbo" (has clic para ver el Validator original)
 
    public void pagosCbo() {
        List<Object[]> inquilinos = daoInquilinos.inquilinosCbo();
        request.setAttribute("inquilinos", inquilinos);
    }
 


Modificar el Servlet agregando una nueva funcionalidad (has clic para ver el Servlet original):
 
                case "CBO":
                validator.pagosCbo();
                target = request.getParameter("target") + ".jsp";
                break;
 

Crear un botón o enlace que llame a una función de JS que llamaremos: "pagosIns();"

 
    <a href="#" onclick="pagosIns();">
        Agregar pago
    </a>
 

El código JavaScript sería:
 
   function pagosIns() {
       window.location = "Pagos?accion=CBO&target=pagosIns";
   }
 

Nuestro "target" o lugar a donde apuntamos es "pagosIns" que en el Servlet es aumentado con la extensión ".jsp", por lo que requerimos crear un JSP que se llame "pagosIns.jsp", que sería el siguiente:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Agregar un pago</title>        
    </head>
    <body>
        <a href="pagos.jsp">Regresar</a><br/>
       <h1>Agregar pago</h1>
        <form action="Pagos" method="post" style="margin: auto; display: table"> 
            <input type="hidden" name="accion" value="INS"/>
            <fieldset>
                <legend>Agregar datos</legend>
                <br/>
                <label>Seleccione el inquilino</label> 
                <select name="inquilino">
                    <c:forEach var="i" items="${inquilinos}">
                        <option value="${i[0]}">${i[1]} - ${i[2]} ${i[3]} ${i[4]}</option>
                    </c:forEach>
                </select>
                <br/><br/>
                <label>Ingrese el monto</label> 
                <input type="number" name="monto" style="width: 400px" min="0.01" step="0.01"/>                
                <br/>    
                <br/><p style="text-align: center;">
                    <button type="submit">Agregar</button>
                </p>               
            </fieldset>
        </form>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
    </body>
</html>

Tendríamos algo similar a:
Agregar datos
 

 


Estructura

miércoles, 23 de octubre de 2019

Trabajando con JavaTime - LocalDateTime

La clase "LocalDate" que fue añadida en la versión 1.7 del JDK es de alguna manera la nueva forma como podemos manipular fechas en JAVA en lugar de emplear la clase "Date" de "java.util"

Veamos los siguientes ejemplos:

package test;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Fechas {

    public static void main(String[] args) {
        //Capturando la hora actual
        LocalDateTime hoy = LocalDateTime.now();
        System.out.println("Fecha y hora actual: " + hoy.toString());

        //Ingresando el año, mes, día, hora y minuto (segundo es opcional)
        LocalDateTime desdeInt = LocalDateTime.of(2019, 10, 23, 12, 31);
        System.out.println("Fecha y hora actual desde ints: " + desdeInt.toString());

        //Ingresando hora desde un String, usando formato año, mes, día, hora, minuto y segundo
        LocalDateTime desdeString = LocalDateTime.parse("1992-06-30T21:11:30");
        System.out.println("Fecha y hora con formato por defecto: " + desdeString.toString());

        //Ingresando hora desde un String que tiene formato: Horas y minutos
        DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
        LocalDateTime conFormato = LocalDateTime.parse("30-06-1992 21:52:00", formato);
        System.out.println("Fecha y hora ingresados con formato: " + conFormato.toString());
        //Si queremos retornar en un String con formato personalizado
        DateTimeFormatter formatoFechaHora = DateTimeFormatter.ofPattern("dd-MMM-yyyy hh:mm:ss a");
        String horaCorta = conFormato.format(formatoFechaHora);
        System.out.println("Fecha y hora mostrados con formato: " + horaCorta);

        //Extrayendo los datos individualmente
        System.out.println("Fecha y hora: "
                + traductor(conFormato.getDayOfWeek().toString()) + ", "
                + conFormato.getDayOfMonth() + " de "
                + traductor(conFormato.getMonth().toString()) + " de "
                + conFormato.getYear() + ". A las "
                + conFormato.getHour() + " horas con "
                + conFormato.getMinute() + " minutos y "
                + conFormato.getSecond() + " segundos");
    }

     private static String traductor(String eng) {
        String esp;
        switch (eng) {
            case "TUESDAY":
                esp = "MARTES";
                break;
            case "JUNE":
                esp = "JUNIO";
                break;
            default:
                esp = eng;
        }
        return esp;
    }
}

Nos producirá una salida similar a esta:
Fecha y hora actual: 2019-10-23T12:44:55.758
Fecha y hora actual desde ints: 2019-10-23T12:31
Fecha y hora con formato por defecto: 1992-06-30T21:11:30
Fecha y hora ingresados con formato: 1992-06-30T21:52
Fecha y hora mostrados con formato: 30-jun-1992 09:52:00 PM
Fecha y hora: MARTES, 30 de JUNIO de 1992. A las 21 horas con 52 minutos y 0 segundos

Se creó, además, una función extremadamente simple llamada traductor que convierte los meses y nombres de días de ingles a español.

Trabajando con JavaTime - LocalTime

La clase "LocalDate" que fue añadida en la versión 1.7 del JDK es de alguna manera la nueva forma como podemos manipular fechas en JAVA en lugar de emplear la clase "Date" de "java.util"

Veamos los siguientes ejemplos:

package test;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Horas {

    public static void main(String[] args) {
        //Capturando la hora actual
        LocalTime horaHoy = LocalTime.now();
        System.out.println("Hora actual: " + horaHoy.toString());

        //Ingresando la hora, minutos, segundos y nanosegundos.
        LocalTime horaDeInt = LocalTime.of(21, 11, 30, 0);
        System.out.println("Hora desde ints: " + horaDeInt.toString());

        //Ingresando hora desde un String, usando formato hora, minutos y segundos.
        LocalTime horaDeString = LocalTime.parse("21:11:30");
        System.out.println("Hora con formato por defecto: " + horaDeString.toString());

        //Ingresando hora desde un String que tiene formato: Horas y minutos
        DateTimeFormatter formato = DateTimeFormatter.ofPattern("HH:mm");
        LocalTime horaConFormato = LocalTime.parse("21:11", formato);
        System.out.println("Hora con formato 24 horas: " + horaConFormato.toString());
        //Si queremos retornar en un String con formato AM y PM
        DateTimeFormatter formatoAM_PM = DateTimeFormatter.ofPattern("hh:mm a");
        String horaCorta = horaConFormato.format(formatoAM_PM);
        System.out.println("Hora con formato AM - PM: " + horaCorta);
        //Extrayendo los datos individualmente
        System.out.println("Fecha con formato largo: "
                + horaConFormato.getHour() + " horas "
                + horaConFormato.getMinute() + " minutos "
                + horaConFormato.getSecond() + " segundos");
    }

}

    }
    
}

Nos producirá una salida similar a esta:
Hora actual: 12:21:39.183
Hora desde ints: 21:11:30
Hora con formato por defecto: 21:11:30
Hora con formato 24 horas: 21:11
Hora con formato AM - PM: 09:11 PM
Fecha con formato largo: 21 horas 11 minutos 0 segundos


  • Por defecto se usa el formato HH-mm-ss
  • Si se desea cambiar ese formato para ingresar el String, se emplea un "DateTimeFormatter" donde se indica la forma como llegará el String al LocalTime. 

Observa la siguiente tabla comparativa de los diversos formatos en fechas:


Formato Salida
HH:mm:ss 21:30:15
hh:mm:ss 09:30:15
hh:mm:ss a 09:30:15 AM
HH:mm 21:30
HH:mm:ss.SSS 21:30:15.000

Se empla "H" para formato de horas de 1 a 23, "h" para formato de 1 a 12, la "m" para los minutos, "s" para los segundos, "S" para fracciones de segundo en este caso puede ser: "S", "SS" o "SSS". Además, si queremos agregar AM o PM se agrega "a"

Trabajando con JavaTime - LocalDate

La clase "LocalDate" que fue añadida en la versión 1.7 del JDK es de alguna manera la nueva forma como podemos manipular fechas en JAVA en lugar de emplear la clase "Date" de "java.util"

Veamos los siguientes ejemplos:

package test;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Fechas {
    
    public static void main(String[] args) {       
        //Capturando la fecha actual
        LocalDate fechaHoy = LocalDate.now();
        System.out.println("Fecha actual: " + fechaHoy.toString());
        
        //Ingresando la fecha como año, mes y día en formatos numéricos
        LocalDate fechaDeInt = LocalDate.of(2019,12,31);        
        System.out.println("Fecha desde ints: " + fechaDeInt.toString());
        
        //Ingresando fecha desde un String, usar formato: año, mes y día
        LocalDate fechaDeString = LocalDate.parse("1992-06-30");
        System.out.println("Fecha con formato por defecto: " + fechaDeString.toString());
        
        //Ingresando fecha desde un String que tiene formato: día, mes y año
        DateTimeFormatter formato = DateTimeFormatter.ofPattern("dd-MM-yyyy");
        LocalDate fechaConFormato = LocalDate.parse("31-12-2000", formato);
        System.out.println("Fecha con formato por defecto: " + fechaConFormato.toString());
        //Si queremos retornar en un String con el mismo formato obtenido
        String fechaCorta = fechaConFormato.format(formato);
        System.out.println("Fecha con formato corto: " + fechaCorta);        
        //Extrayendo los datos individualmente en dos casos
        System.out.println("Fecha con formato corto: "
                + fechaConFormato.getDayOfMonth() + " / "
                + fechaConFormato.getMonthValue() + " / "
                + fechaConFormato.getYear());
        System.out.println("Fecha con formato largo : "
                + fechaConFormato.getDayOfWeek() + " / "
                + fechaConFormato.getMonth() + " / "
                + fechaConFormato.getYear());
    }
    
}

Nos producirá una salida similar a esta:
Fecha actual: 2019-10-23
Fecha desde ints: 2019-12-31
Fecha con formato por defecto: 1992-06-30
Fecha con formato por defecto: 2000-12-31
Fecha con formato corto: 31-12-2000
Fecha con formato corto: 31 / 12 / 2000
Fecha con formato largo : SUNDAY / DECEMBER / 2000


  • Por defecto se usa el formato dd-MM-yyyy
  • Si se desea cambiar ese formato para ingresar el String, se emplea un "DateTimeFormatter" donde se indica la forma como llegará el String al LocalDate. 

Observa la siguiente tabla comparativa de los diversos formatos en fechas:


Formato Salida
yyyy-MM-dd 2019-12-31
dd-MM-YYYY 31-12-2019
dd-MMM-yyyy 31-dic-2019
dd-MM-yy 31-12-19
dd-MMM-uuuu 31-12-2019

También se puede emplear "u" en lugar de "y", para los días se emplea "d" y los meses "M". No usar "m" pues estos se emplean para minutos.

Creando JSP con una vista de una base de datos

Trabajaremos con las siguientes tablas:


Además, le vamos a crear una vista a la tabla "pagos" (para saber como crear este código paso a paso has clic aquí):

CREATE VIEW pagos_view AS
SELECT 
  pagos.idpagos id,
  inquilinos.dni dni,
  CONCAT_WS(" ", inquilinos.nombres, inquilinos.paterno, inquilinos.materno) datos,
  pagos.monto monto,
  DATE(pagos.fecha) fecha,
  TIME(pagos.fecha) hora
FROM pagos INNER JOIN inquilinos 
  ON pagos.inquilino = inquilinos.idinquilinos


Creando el DTO, DAO y su implementación

DTO

¿Cómo crear un DTO desde una tabla de una base de datos? Dale clic

package dto;

import java.time.LocalDateTime;

public class Pagos {
    private Integer idpagos;
    private Integer inquilino;
    private Double monto;
    private LocalDateTime fecha;

    public Pagos() {
    }

    public Integer getIdpagos() {
        return idpagos;
    }
    public void setIdpagos(Integer idpagos) {
        this.idpagos = idpagos;
    }
    public Integer getInquilino() {
        return inquilino;
    }
    public void setInquilino(Integer inquilino) {
        this.inquilino = inquilino;
    }
    public Double getMonto() {
        return monto;
    }
    public void setMonto(Double monto) {
        this.monto = monto;
    }
    public LocalDateTime getFecha() {
        return fecha;
    }
    public void setFecha(LocalDateTime fecha) {
        this.fecha = fecha;
    }
        
}

DAO

¿Cómo crear un DAO para una tabla de una base de datos? Dale clic

package dao;
import java.util.List;

public interface DaoPagos {
    public List<Object[]> pagosSel();
    public String getMessage();
}

Implementación

¿Cómo crear la implementación de un DAO? Dale clic

package dao.impl;

import biblioteca.ConectaBD;
import dao.DaoPagos;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class DaoPagosImpl implements DaoPagos {

    private final ConectaBD conectaDb;
    private String mensaje;

    public DaoPagosImpl() {
        this.conectaDb = new ConectaBD();
    }

    @Override
    public List<Object[]> pagosSel() {
        List<Object[]> list = null;
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("id,")
                .append("dni,")
                .append("datos,")
                .append("monto,")
                .append("fecha,")
                .append("hora")
                .append(" FROM pagos_view");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();
            list = new ArrayList<>();
            while (rs.next()) {
                Object[] pago = new Object[6];
                pago[0] = rs.getInt(1);
                pago[1] = rs.getString(2);
                pago[2] = rs.getString(3);
                pago[3] = rs.getDouble(4);
                pago[4] = rs.getString(5);
                pago[5] = rs.getString(6);
                list.add(pago);
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return list;
    }

    @Override
    public String getMessage() {
        return mensaje;
    }
}


Se puede apreciar que la función "pagosSel" devuelve un "List" pero no de "Pagos" sino tipo "Object[]", esto porque la vista no devuelve los mismo elementos ni tipos que hace la tabla. Es muy importante recordar que a la vista solo se le hace consultas de tipo "SELECT", no debemos intentar actualizar o eliminar, pues nos dará error.

Servlet y Validator

¿Cómo crear un validator y Servlet para una tabla de una base de datos? Dale clic

Validator

package web.validator;

import dao.DaoPagos;
import dao.impl.DaoPagosImpl;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

public class PagosValidator {

    private final HttpServletRequest request;
    private final DaoPagos daoPagos;

    public PagosValidator(HttpServletRequest request) {
        this.request = request;
        this.daoPagos = new DaoPagosImpl();
    }

    public String pagosSel() {
        String result = null;
        List<Object[]> list = daoPagos.pagosSel();
        if (list != null) {
            request.setAttribute("list", list);
        } else {
            result = daoPagos.getMessage();
        }
        return result;
    }
}

Servlet

package web.servlet;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import web.validator.PagosValidator;

@WebServlet(name = "PagosServlet", urlPatterns = {"/Pagos"})
public class PagosServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        String accion = request.getParameter("accion");
        accion = (accion == null) ? "" : accion;
        String result;
        String target = "pagosSel.jsp";

        PagosValidator validator = new PagosValidator(request);

        switch (accion) {
            case "SEL":
                result = validator.pagosSel();
                break;
            case "":
                result = "Solicitud requerida";
                break;
            default:
                result = "Solicitud no reconocida";
        }

        if (result != null) {
            request.setAttribute("message", result);
        }

        RequestDispatcher dispatcher = request.getRequestDispatcher(target);
        dispatcher.forward(request, response);
    }

    @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);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }

}

Los JSP con la vista

¿Cómo crear un JSP para una tabla de una base de datos? Dale clic

El JSP que realiza la llamada al Servlet: pagos.jsp
 
<%response.sendRedirect("Pagos?accion=SEL");%>
 

El JSP que recibe los datos del Servlet: pagosSel.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Reporte de pagos</title>
        <script src="jq/jquery-3.3.1.min.js" type="text/javascript"></script>
        <script src="js/pagos.js" type="text/javascript"></script>
    </head>
    <body>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>DNI</th>
                    <th>NOMBRES Y APELLIDOS</th>
                    <th>MONTO PAGADO</th>
                    <th>FECHA</th>
                    <th>HORA</th>
                </tr>
            </thead>
            <tbody>
            <c:forEach var="f" items="${list}">                
                <tr>
                    <td>${f[0]}</td>
                    <td>${f[1]}</td>
                    <td>${f[2]}</td>
                    <td>${f[3]}</td>
                    <td>${f[4]}</td>
                    <td>${f[5]}</td>
                </tr>
            </c:forEach> 
        </tbody>
    </table>
</body>
</html>

El resultado sería:
ID DNI NOMBRES Y APELLIDOS MONTO PAGADO FECHA HORA
1 31378082 LUISA PAUCAR NARRO 400.0 2019-10-21 21:34:35
2 43331042 AUGUSTO SOTOMAYOR NARVAJO 300.0 2019-10-18 18:30:00

Estructura


jueves, 17 de octubre de 2019

Creando JSP con acceso a base de datos

Debemos tener un "index.html" donde colocaremos nuestro menú para las diversas acciones, este puede ser modificado posteriormente por un "login" para manejar accesos.

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <a href="inquilinos.jsp">Mantenimiento a inquilinos</a>
    </body>
</html>


Primera llamada al Servlet

Tenemos el JSP que nos llevará al listado de "inquilinos", este llama al Servlet (clic aquí para ver el Servlet) de nombre "Inquilinos" y como parámetro "accion" es valor es "SEL", en el Servlet podemos observar que la acción SEL no se varía el "target", por lo que nos llevaría al "target" por defecto que es: "inquilinosSel.jsp". Es importante este pequeño archivo, ya que de lo contrario no le diríamos de ninguna forma al Servlet que acción debe realizar y no haría nada, pero se puede reemplazar con otros métodos más sencillos.

<%response.sendRedirect("Inquilinos?accion=SEL");%>
  


Lectura de datos y despliegue en una tabla HTML

En "inquilinosSel.jsp" tendremos una tabla en la que empleando la biblioteca JSTL con la función "foreach" le colocamos los valores de la consulta SELECT a la base de datos.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Mantenimiento de inquilinos</title>
        <script src="jq/jquery-3.3.1.min.js" type="text/javascript"></script>
        <script src="js/inquilinos.js" type="text/javascript"></script>
    </head>
    <body>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
        <table border="1">
            <thead>
                <tr>
                    <th>
                        <a href="#" onclick="inquilinosIns();">
                            Agregar                            
                        </a>
                    </th>
                    <th>ID</th>
                    <th>DNI</th>
                    <th>NOMBRES</th>
                    <th>PATERNO</th>
                    <th>MATERNO</th>
                    <th>TELEFONO</th>
                    <th>FECHA DE INGRESO</th>
                    <th>CORREO</th>
                    <th>DEUDAS</th>
                    <th>
                        <a href="#" onclick="inquilinosUpd();">
                            Actualizar                            
                        </a>
                    </th>
                    <th>
                        <a href="#" onclick="inquilinosDel();">
                            Eliminar                         
                        </a>
                    </th>
                </tr>
            </thead>
            <tbody>
            <c:forEach var="f" items="${list}">                
                <tr>
                    <td colspan="2">${f.idinquilinos}</td>
                    <td>${f.dni}</td>
                    <td>${f.nombres}</td>
                    <td>${f.paterno}</td>
                    <td>${f.materno}</td>
                    <td>${f.telefono}</td>
                    <td>${f.fecha_ingreso}</td>
                    <td>${f.correo}</td>
                    <td>${f.deuda}</td>
                    <th>
                        <input type="radio" name="id_upd"
                               value="${f.idinquilinos}"/>
                    </th>
                    <th>
                        <input type="checkbox" name="id_del" 
                               value="${f.idinquilinos}"/>
                    </th>
                </tr>
            </c:forEach> 
        </tbody>
    </table>
</body>
</html>

Nos mostrará un resultado como este:
Agregar ID DNI NOMBRES PATERNO MATERNO TELEFONO FECHA DE INGRESO CORREO DEUDAS Actualizar Eliminar
1 31378082 LUISA PAUCAR NARRO 999888777 2018-01-28 lpaucar@mail.com 0.0
2 43331042 AUGUSTO SOTOMAYOR NARVAJO 900800700 2019-10-08 asoto@mail.com 0.0

Agregando datos desde un formulario HTML a la base de datos

Podemos agregar un registro mediante un formulario, este no es necesario que sea un JSP, puede ser un HTML, pero si queremos mostrar un mensaje de error que llegue directamente desde el Servlet, será necesario que sea un JSP. Este archivo se llama: "inquilinosIns.jsp"

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
        
    </head>
    <body>
        <h1>Agregar inquilino</h1>
        <form action="Inquilinos" method="post" style="margin: auto; display: table"> 
            <input type="hidden" name="accion" value="INS"/>
            <fieldset>
                <legend>Agregar datos</legend>
                <br/>
                <input type="text" name="dni" style="width: 400px"
                       placeholder="Ingrese el DNI"/>
                <br/>
                <input type="text" name="nombres" style="width: 400px"
                       placeholder="Ingrese el nombre"/>
                <br/>
                <input type="text" name="paterno" style="width: 400px"
                       placeholder="Ingrese el apellido paterno"/>
                <br/>
                <input type="text" name="materno" style="width: 400px"
                       placeholder="Ingrese el apellido materno"/>
                <br/>
                <input type="text" name="telefono" style="width: 400px"
                       placeholder="Ingrese el telefono"/>
                <br/>
                <label>Ingrese la fecha de ingreso</label> 
                <input type="date" name="fecha_ingreso" style="width: 400px"/>
                <br/>
                <label>Ingrese la deuda</label> 
                <input type="number" name="deuda" style="width: 400px"/>
                <br/>
                <input type="email" name="correo" style="width: 400px"
                       placeholder="Ingrese el correo"/>
                <br/>    
                <br/><p style="text-align: center;">
                    <button type="submit">Agregar</button>
                </p>               
            </fieldset>
        </form>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
    </body>
</html>


Actualizando datos desde un formulario HTML a la base de datos

Podemos actualizar un registro mediante un formulario, este debe ser un JSP, ya que vamos a cargar los datos del registro a actualizar en el formulario de actualización, vemos como aparecen los atributos "value" en los elementos HTML "input", el nombre debe coincidir con el dado en el "validator". Este archivo se llama: "inquilinosUpd.jsp"

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

    </head>
    <body>
        <h1>Actualizar inquilino</h1>
        <form action="Inquilinos" method="post" style="margin: auto; display: table"> 
            <input type="hidden" name="accion" value="UPD"/>
            <input type="hidden" name="idinquilinos" value="${inquilino.idinquilinos}"/>
            <fieldset>
                <legend>Actualizar datos</legend>
                <br/>
                <input type="text" name="dni" style="width: 400px"
                       placeholder="Ingrese el DNI" 
                       value="${inquilino.dni}"/>
                <br/>
                <input type="text" name="nombres" style="width: 400px"
                       placeholder="Ingrese el nombre" 
                       value="${inquilino.nombres}"/>
                <br/>
                <input type="text" name="paterno" style="width: 400px"
                       placeholder="Ingrese el apellido paterno" 
                       value="${inquilino.paterno}"/>
                <br/>
                <input type="text" name="materno" style="width: 400px"
                       placeholder="Ingrese el apellido materno" 
                       value="${inquilino.materno}"/>
                <br/>
                <input type="text" name="telefono" style="width: 400px"
                       placeholder="Ingrese el telefono" 
                       value="${inquilino.telefono}"/>
                <br/>
                <label>Ingrese la fecha de ingreso</label> 
                <input type="date" name="fecha_ingreso" style="width: 400px" 
                       value="${inquilino.fecha_ingreso}"/>
                <br/>
                <label>Ingrese la deuda</label> 
                <input type="number" name="deuda" style="width: 400px" 
                       value="${inquilino.deuda}"/>
                <br/>
                <input type="email" name="correo" style="width: 400px"
                       placeholder="Ingrese el correo" 
                       value="${inquilino.correo}"/>
                <br/>    
                <br/><p style="text-align: center;">
                    <button type="submit">Actualizar</button>
                </p>               
            </fieldset>
        </form>
        <a href="index.html">Regresar</a><br/>
        <c:if test="${message != null}">
            <div>${message}</div>
        </c:if>
    </body>
</html>


Funciones JavaScript de apoyo

La navegación entre páginas es relativamente compleja si no empleamos funciones de JavaScript que nos ayudan incluso a mostrar algunos mensjaes de alerta. Este archivo se llama: "inquilinos.js" y se debe colocar en una carpeta llamada "js". Todo este embrollo de colocarlos en carpetas es muy útil para mantener un orden y trabajar de forma estandarizada.

function inquilinosIns() {
    window.location = "inquilinosIns.jsp";
}

function inquilinosDel() {
    var ids = [];
    $("input[name='id_del']:checked").each(function () {
        ids.push($(this).val());
    });
    if (ids.length === 0) {
        alert("Advertencia\n\nSeleccione la(s) fila(s) a Retirar");
    } else {
        var exito = confirm('¿Seguro que deseas borrar los registros?');
        if (exito) {
            window.location = "Inquilinos?accion=DEL&ids=" + ids.toString();
        } else {
            alert("Operación cancelada");
        }
    }
}

function inquilinosUpd() {    
    var id = $("input[name='id_upd']:checked").val();
    if (isNaN(id)) {
        alert("Seleccione Fila para Actualizar Datos");
    } else {
        window.location = "Inquilinos?accion=GET&idinquilino=" + id;
    }
}


Estas funciones son llamadas en la pantalla "inquilinosSel.jsp" en los botones de eliminar, actualizar o agregar.

Estructura de carpetas y archivos

Tendremos la siguiente estructura, es necesario incluir al JQuery parapoder trabajar de forma más sencilla con el código JS, pero no es necesario si se modifican las funciones de JS que lo emplean. Aún así es importante recalcar que prácticamente todos los Frameworks de FrontEnd emplean a esta biblioteca de JavaScript.



Servlets

¿Qué es un Servlet?

Se le llama así a una de las tecnologías proporcionadas por Java que generan componentes independientes que serán empleados en aplicaciones web, estos tienen acceso completo a las API de Java y las bibliotecas de HTTP. Los servlets están intimanente ligados a la plataforma y el servidor.

¿Cómo crear un Servlet en NetBeans?

Seguir los pasos:


¿Qué debemos modificar?

Cambiar el nombre de acuerdo a la función que hará o tabla que dará mantenimiento, colocarlo por preferencia en un paquete que contendrá a los servlets, en algunos casos podemos llamarlos controllers haciendo referencia al patrón MVC.

Modificar el alias del Servlet a uno que no incluya la terminación servlet y finalizar.


Código de ejemplo

Teniendo como base a la tabla "Inquilinos"(clic aquí para ver el DTO) a la que le realizaremos un mantenimiento (CRUD) teniendo como DAO a "DaoInquilinos" y su correspondiente implementación (clic aquí para ver el DAO).Además, las pruebas a las funciones declaradas en el DAO (clic aquí para ver el DAO).

Crearemos dos paquetes dentro del paquete web que serán "servlet" y "validator", dentro crearemos respectivamente el servlet llamado "InquilinosServlet" y una clase de apoyo llamada "InquilinosValidator", esta untima clase nos sirve para reducir la cantidad de código en el Servlet y poder tener mejor mantenimiento de este, por lo tanto es opcional.

Tendríamos el código de "InquilinosValidator" considerando las funciones que declaramos en el DAO, de la siguiente forma:
package web.validator;

import biblioteca.DeString;
import dao.DaoInquilinos;
import dao.impl.DaoInquilinosImpl;
import dto.Inquilinos;
import java.time.LocalDate;
import java.util.List;
import javax.servlet.http.HttpServletRequest;

public class InquilinosValidator {

    private final HttpServletRequest request;
    private final DaoInquilinos daoInquilinos;

    public InquilinosValidator(HttpServletRequest request) {
        this.request = request;
        this.daoInquilinos = new DaoInquilinosImpl();
    }

    public String inquilinosSel() {
        String result = null;
        List<Inquilinos> list = daoInquilinos.inquilinosSel();
        if (list != null) {
            request.setAttribute("list", list);
        } else {
            result = daoInquilinos.getMessage();
        }
        return result;
    }

    public String inquilinosGet() {
        String result = null;
        Integer idinquilino = DeString.aInteger(request.getParameter("idinquilino"));
        Inquilinos inquilino = daoInquilinos.inquilinosGet(idinquilino);
        if (inquilino != null) {
            request.setAttribute("inquilino", inquilino);

        } else {
            result = daoInquilinos.getMessage();
        }
        return result;
    }

    public String inquilinosInsUpd(boolean upd) {
        StringBuilder result = new StringBuilder("<ul>");
        Integer idinquilino = DeString.aInteger(request.getParameter("idinquilinos"));
        String dni = request.getParameter("dni");
        String nombres = request.getParameter("nombres");
        String paterno = request.getParameter("paterno");
        String materno = request.getParameter("materno");
        String telefono = request.getParameter("telefono");
        LocalDate fecha_ingreso = LocalDate.parse(request.getParameter("fecha_ingreso"));
        String correo = request.getParameter("correo");
        Double deuda = DeString.aDouble(request.getParameter("deuda"));
        if (upd && idinquilino == null) {
            result.append("<li>Id requerido</li>");
        }
        if (nombres == null || nombres.trim().length() == 0) {
            result.append("<li>Nombre requerido</li>");
        } else if (nombres.trim().length() < 3 || nombres.trim().length() > 50) {
            result.append("<li>La dimensión del nombre debe estar entre")
                    .append("3 a 50 caracteres</li>");
        }
        if (paterno == null || paterno.trim().length() == 0) {
            result.append("<li>Apellido paterno requerido</li>");
        } else if (paterno.trim().length() < 3 || paterno.trim().length() > 50) {
            result.append("<li>La dimensión del apellido paterno debe estar entre")
                    .append("3 a 50 caracteres</li>");
        }
        if (materno == null || materno.trim().length() == 0) {
            result.append("<li>Apellido materno requerido</li>");
        } else if (materno.trim().length() < 3 || materno.trim().length() > 50) {
            result.append("<li>La dimensión del apellido materno debe estar entre")
                    .append("3 a 50 caracteres</li>");
        }
        if (fecha_ingreso == null) {
            result.append("<li>Fecha requerida</li>");
        }
        if (deuda < 0d) {
            result.append("<li>La deuda no puede ser negativa</li>");
        }
        Inquilinos inquilino = new Inquilinos();
        inquilino.setIdinquilinos(idinquilino);
        inquilino.setDni(dni);
        inquilino.setNombres(nombres);
        inquilino.setPaterno(paterno);
        inquilino.setMaterno(materno);
        inquilino.setFecha_ingreso(fecha_ingreso);
        inquilino.setTelefono(telefono);
        inquilino.setDeuda(deuda);
        inquilino.setCorreo(correo);
        if (result.length() == 4) {
            String msg = upd
                    ? daoInquilinos.inquilinosUpd(inquilino)
                    : daoInquilinos.inquilinosIns(inquilino);
            if (msg != null) {
                result.append("<li>").append(msg).append("</li>");
            }
        }
        if (result.length() > 4) {
            request.setAttribute("inquilino", inquilino);
        }
        return result.length() == 4 ? null : result.append("</ul>").toString();
    }

    public String inquilinosDel() {
        List<Integer> ids = DeString.ids(request.getParameter("ids"));
        String result = (ids != null)
                ? daoInquilinos.inquilinosDel(ids)
                : "IDs incorrectos";
        return result;
    }
}

Mientras el código del Servlet sería:

package web.servlet;

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import web.validator.InquilinosValidator;

@WebServlet(name = "InquilinosServlet", urlPatterns = {"/Inquilinos"})
public class InquilinosServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        String accion = request.getParameter("accion");
        accion = (accion == null) ? "" : accion;
        String result;
        String target = "inquilinosSel.jsp";

        InquilinosValidator validator = new InquilinosValidator(request);

        switch (accion) {
            case "SEL":
                result = validator.inquilinosSel();
                break;
            case "INS":
                result = validator.inquilinosInsUpd(false);
                target = result == null ? "inquilinos.jsp" : "inquilinosIns.jsp";
                break;
            case "DEL":
                result = validator.inquilinosDel();
                target = "inquilinos.jsp";
                break;
            case "GET":
                result = validator.inquilinosGet();
                target = "inquilinosUpd.jsp";
                break;
            case "UPD":
                result = validator.inquilinosInsUpd(true);
                target = result == null ? "inquilinos.jsp" : "inquilinosUpd.jsp";
                break;
            case "":
                result = "Solicitud requerida";
                break;
            default:
                result = "Solicitud no reconocida";
        }

        if (result != null) {
            request.setAttribute("message", result);
        }

        RequestDispatcher dispatcher = request.getRequestDispatcher(target);
        dispatcher.forward(request, response);
    }

    @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);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }

}

La estructura de carpetas resultaría en:

La clase DeString es una librería interna. (clic aquí para ver el código), esta permite convertir String a Integer y Double, incluso en colecciones tipo List.

domingo, 13 de octubre de 2019

Pruebas simples a un DAO

Estructura

Crear un paquete de pruebas que llamaremos "test", dentro un "Java Main Class" que se llamará "TestDaoInquilinos "


Código

Probamos cada una de las funciones de la clase DAO, en este caso del "DaoInquilinos" (clic aquí para ver el código del DAO)

Probando el listado de registros

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
List<Inquilinos> list = daoInquilinos.inquilinosSel();
if (list != null) {
 try {
  list.forEach((t) -> {
   System.out.println(t.getIdinquilinos().toString() + " "
    + t.getDni() + " "
    + t.getNombres() + " "
    + t.getPaterno() + " "
    + t.getMaterno() + " "
    + t.getTelefono() + " "
    + t.getCorreo() + " "
    + t.getDeuda().toString() + " "
    + t.getFecha_ingreso().toString());
  });
 } catch (Exception e) {
  System.out.println(daoInquilinos.getMessage());
  System.out.println(e.getMessage());
 }
} else {
 System.out.println("Lista vacía");
}


Probando el obtener un registro por su código

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
Inquilinos inquilino = daoInquilinos.inquilinosGet(1);
if (inquilino != null) {
 try {
  System.out.println(inquilino.getIdinquilinos().toString() + " "
    + inquilino.getDni() + " "
    + inquilino.getNombres() + " "
    + inquilino.getPaterno() + " "
    + inquilino.getMaterno() + " "
    + inquilino.getTelefono() + " "
    + inquilino.getCorreo() + " "
    + inquilino.getDeuda().toString() + " "
    + inquilino.getFecha_ingreso().toString());
 } catch (Exception e) {
  System.out.println(daoInquilinos.getMessage());
  System.out.println(e.getMessage());
 }
} else {
 System.out.println("Usuario no encontrado");
}


Probando el insertar un nuevo registro

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
Inquilinos inquilino = new Inquilinos();
inquilino.setDni("71005052");
inquilino.setNombres("ROBERT");
inquilino.setPaterno("JONES");
inquilino.setMaterno("SMITH");
inquilino.setTelefono("997777822");
inquilino.setCorreo("robert@mail.com");
inquilino.setDeuda(0d);
inquilino.setFecha_ingreso(LocalDate.parse("2010-12-18"));
try {
 daoInquilinos.inquilinosIns(inquilino);
} catch (Exception e) {
 System.out.println(daoInquilinos.getMessage());
 System.out.println(e.getMessage());
}


Probando la actualización de un registro ingresando su código

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
Inquilinos inquilino = new Inquilinos();
inquilino.setIdinquilinos(5);
inquilino.setDni("79905052");
inquilino.setNombres("PAUL");
inquilino.setPaterno("WAYNE");
inquilino.setMaterno("DIAZ");
inquilino.setTelefono("998484822");
inquilino.setCorreo("paul@mail.com");
inquilino.setDeuda(0d);
inquilino.setFecha_ingreso(LocalDate.parse("2012-12-28"));
try {
 daoInquilinos.inquilinosUpd(inquilino);
} catch (Exception e) {
 System.out.println(daoInquilinos.getMessage());
 System.out.println(e.getMessage());
}


Probando la eliminación de un registro por su código

DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
List<Integer> del = new ArrayList<>();
del.add(4);
del.add(3);
try {
 daoInquilinos.inquilinosDel(del);
} catch (Exception e) {
 System.out.println(daoInquilinos.getMessage());
 System.out.println(e.getMessage());
}


Clase de pruebas

Crear un paquete de pruebas que llamaremos "test", dentro un "Java Main Class" que se llamará "TestDaoInquilinos" donde implementaremos todo el código anterior en un solo archivo para probar todas las funcionalidades en un solo archivo

package test;

import dao.DaoInquilinos;
import dao.impl.DaoInquilinosImpl;
import dto.Inquilinos;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

public class TestDaoInquilinos {

    public static void main(String[] args) throws ParseException {
        Scanner scanner;
        DaoInquilinos daoInquilinos = new DaoInquilinosImpl();
        Inquilinos inquilino;
        Integer opt;
        do {
            scanner = new Scanner(System.in);
            inicio();
            opt = scanner.nextInt();
            switch (opt) {
                case 1:
                    List<inquilinos> list = daoInquilinos.inquilinosSel();
                    if (list != null) {
                        try {
                            list.forEach((t) -> {
                                System.out.println(t.getIdinquilinos().toString() + " "
                                        + t.getDni() + " "
                                        + t.getNombres() + " "
                                        + t.getPaterno() + " "
                                        + t.getMaterno() + " "
                                        + t.getTelefono() + " "
                                        + t.getCorreo() + " "
                                        + t.getDeuda().toString() + " "
                                        + t.getFecha_ingreso().toString());
                            });
                        } catch (Exception e) {
                            System.out.println(daoInquilinos.getMessage());
                            System.out.println(e.getMessage());
                        }
                    } else {
                        System.out.println("Lista vacía");
                    }
                    break;
                case 2:
                    inquilino = daoInquilinos.inquilinosGet(1);
                    if (inquilino != null) {
                        try {
                            System.out.println(inquilino.getIdinquilinos().toString() + " "
                                    + inquilino.getDni() + " "
                                    + inquilino.getNombres() + " "
                                    + inquilino.getPaterno() + " "
                                    + inquilino.getMaterno() + " "
                                    + inquilino.getTelefono() + " "
                                    + inquilino.getCorreo() + " "
                                    + inquilino.getDeuda().toString() + " "
                                    + inquilino.getFecha_ingreso().toString());
                        } catch (Exception e) {
                            System.out.println(daoInquilinos.getMessage());
                            System.out.println(e.getMessage());
                        }
                    } else {
                        System.out.println("Usuario no encontrado");
                    }
                    break;
                case 3:
                    inquilino = new Inquilinos();
                    inquilino.setDni("71005052");
                    inquilino.setNombres("ROBERT");
                    inquilino.setPaterno("JONES");
                    inquilino.setMaterno("SMITH");
                    inquilino.setTelefono("997777822");
                    inquilino.setCorreo("robert@mail.com");
                    inquilino.setDeuda(0d);
                    inquilino.setFecha_ingreso(LocalDate.parse("2010-12-18"));
                    try {
                        daoInquilinos.inquilinosIns(inquilino);
                    } catch (Exception e) {
                        System.out.println(daoInquilinos.getMessage());
                        System.out.println(e.getMessage());
                    }
                    break;
                case 4:
                    inquilino = new Inquilinos();
                    inquilino.setIdinquilinos(5);
                    inquilino.setDni("79905052");
                    inquilino.setNombres("PAUL");
                    inquilino.setPaterno("WAYNE");
                    inquilino.setMaterno("DIAZ");
                    inquilino.setTelefono("998484822");
                    inquilino.setCorreo("paul@mail.com");
                    inquilino.setDeuda(0d);
                    inquilino.setFecha_ingreso(LocalDate.parse("2012-12-28"));
                    try {
                        daoInquilinos.inquilinosUpd(inquilino);
                    } catch (Exception e) {
                        System.out.println(daoInquilinos.getMessage());
                        System.out.println(e.getMessage());
                    }
                    break;
                case 5:
                    List<integer> del = new ArrayList<>();
                    del.add(4);
                    del.add(3);

                    try {
                        daoInquilinos.inquilinosDel(del);
                    } catch (Exception e) {
                        System.out.println(daoInquilinos.getMessage());
                        System.out.println(e.getMessage());
                    }
                    break;
                case 6:
                    System.out.println("Adios");
                    break;
                default:
                    System.out.println("Opción incorrecta");
            }
        } while (opt != 6);
    }

    private static void inicio() {
        System.out.println("--------Claves de las prueba-----");
        System.out.println("1: Lista de usuarios UsuariosSel");
        System.out.println("2: Obtener usuario UsuariosGet");
        System.out.println("3: Insertar usuario UsuariosUpd");
        System.out.println("4: Actualizar usuario UsuariosIns");
        System.out.println("5: Eliminar usuario UsuariosDel");
        System.out.println("6: Salir");
        System.out.println("-----------------------------------");
        System.out.print("\nIngrese la clave: ");
    }
}

Crear un proyecto web con Java en NetBeans 8.2

Debemos seguir los siguientes pasos:


Primero: debemos iniciar el NetBeans, acto seguido seleccionar en "File" o "Archivo" la opción de "New Project..." o "Nuevo Proyecto...". También, podemos usar la combinación de teclas Ctrl + Shift + N o darle clic a la metáfora de nuevo proyecto como se observa en la siguiente imagen.

Fuente: elaboración propia.

Segundo: luego aparecerá una ventana flotante donde seleccionaremos la categoría "Java Web" y el tipo de proyecto "Web Application".

Fuente: elaboración propia.

Tercero:Luego debemos elegir un nombre para el proyecto y su ubicación.

Fuente: elaboración propia.

Cuarto:Seleccionar el servidor, la versión del Java EE y la ruta: en este caso se eligió el Tomcat (puede ser GlassFish), la versión 7 del EE y la ruta será /Demo.

Fuente: elaboración propia.

Quinto: Luego podemos elegir un Framework, dependiendo de la envergadura del proyecto se elige uno o ninguno.

Fuente: elaboración propia.

Sexto:Finalmente, comprobamos la creación del proyecto.

Fuente: elaboración propia.



Ahora podemos empezar a programar las distintas partes de nuestro proyecto.

Conectar MySql o MariaBD con Java (NetBeans)

Se necesita lo siguiente:
  • NetBeans IDE 8.2 o superior.
  • Tener instalado el JDK versión 8 o superior.
  • Tener Instalado MySql versión  5.7.24 o superior, en caso de MariaBD la versión 10.3.12 o superior

El servidor de bases de datos

En este caso debemos tener conocimiento del URL de la base de datos, el puerto que emplea (3306 para MySql y 3307 para MariaBD), el usuario y contraseña.

Creamos una clase llamada "ConectaBD" dentro del paquete "biblioteca" y definimos 4 constantes:
  • URL: que contiene la dirección del servidor de base de datos, en este caso "jdbc:mysql".
  • DRIVER: dirección del driver de conexión de bases de datos, en este caso el driver de MySQL.
  • USER: el usuario, en este caso usamos root.
  • PASS: la constraseña, en este caso está vacía.
El código sería:

package biblioteca;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


public class ConectaBD {
    private final String URL = "jdbc:mysql://localhost:3306/blog";
    private final String DRIVER = "com.mysql.jdbc.Driver";
    private final String USER = "root";
    private final String PASS = "";
    
    public Connection conexionDB() throws SQLException{
    Connection c = null;
        try {
            Class.forName(DRIVER).newInstance();
            c = DriverManager.getConnection(URL, USER, PASS);
        } catch (ClassNotFoundException | 
                 IllegalAccessException | 
                 InstantiationException | 
                 SQLException e) {
            throw new SQLException(e.getMessage());
        }
    
    return c;
    }
}


Se emplea las clases: "Connection", "DriverManager" y "SQLException".

DAO - Objeto de acceso a datos

Los DAO permiten mantener separado el acceso a los datos que pueden provenir de bases de datos, servicios web u otros de las demás tareas que realiza la aplicación, de esta forma las otras partes del programa no deben preocuparse del acceso a los datos, solamente de realizar sus tareas delegando al DAO las operaciones de consulta, inserción, modificación o eliminación de datos en la fuente de datos, que suele ser una base de datos.

DAO actúa como el nexo adaptador entre un componente (como un controlador o Servlet) y la fuente de datos (Como una base de datos SQLite)

Ventajas

Podemos encontrar un escenario actual donde los datos provienen de diversas fuentes como bases de datos relacionales, no relacionales, archivos, etc. y para cada uno de ellos existe una sintaxis diferente, si se cambiara de base de datos como de un Oracle a un PostgreSQL, la sintaxis del código SQL podría varias drásticamente y modificar las diversas partes de un programa que contengan estas sentencias sería costoso ytomaría mucho tiempo, pero si estas sentencias se encuentran localizadas en una sola área como el DAO, las modificaciones, pruebas e incluso la escalabilidad serías mucho más efectivas.

Los DAO abstraen y encapsulan los accesos a las fuentes de datos de forma que este maneja las conexiones con esa fuente, que podría ser por ejemplo una base de datos MySQL, para obtener los datos y almacenarlos posteriormente.

Usar DAO permite ocultar los procesos empleados en un programa que permiten acceder a la fuente de datos. Además, brinda un gran nivel de adaptación a diversas fuentes de almacenamiento sin afectar a las demás capas.

Nota: en los modelos MVC, MVP, MVVM, entre otros los DAO pertenecen a la capa del modelo (M)

Implementación en JAVA

Teniendo como apoyo un DTO o un OD (aunque no son necesarios, pero sí muy útiles) los DAO deben declarar primero una interfaz (esto dependerá mucho de la manera de implementar este patrón, pero usar interfaces tiene múltiples beneficios), para luego implementarse manteniendo un orden y mejorar la facilidad de emplear pruebas.

Ejemplo

Suponiendo la siguiente tabla y que le hemos creado un DTO (para ver como crear un DTO has clic aquí):
La interfaz "DaoInquilinos.java" se colocará dentro de un paquete llamado "dao", el código para dar un mantenimiento básico a la tabla "inquilinos" será

package dao;
import java.util.List;
import dto.Inquilinos;

public interface DaoInquilinos {
    public List <Inquilinos> inquilinosSel();
    public Inquilinos inquilinosGet(Integer id);
    public String inquilinosIns(Inquilinos inquilino);
    public String inquilinosUpd(Inquilinos inquilino);
    public String inquilinosDel(List<Integer> ids);
    public String getMessage();
}


Ahora debemos implementar cada una de esas funciones en un archivo llamado "DaoInquilinosImpl.java" que colocaremos en un paquete llamado "impl" dentro del paquete "dao", para ello empleamos la palabra reservada "implements" que indica que es la implementación del "DaoInquilinos". El código será:

package dao.impl;

import biblioteca.ConectaBD;
import dao.DaoInquilinos;
import dto.Inquilinos;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class DaoInquilinosImpl implements DaoInquilinos {

    private final ConectaBD conectaDb;
    private String mensaje;

    public DaoInquilinosImpl() {
        this.conectaDb = new ConectaBD();
    }

    @Override
    public List<Inquilinos> inquilinosSel() {
        List<Inquilinos> list = null;
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(" FROM inquilinos");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();
            list = new ArrayList<>();
            while (rs.next()) {
                Inquilinos inquilinos = new Inquilinos();
                inquilinos.setIdinquilinos(rs.getInt(1));
                inquilinos.setDni(rs.getString(2));
                inquilinos.setNombres(rs.getString(3));
                inquilinos.setPaterno(rs.getString(4));
                inquilinos.setMaterno(rs.getString(5));
                inquilinos.setTelefono(rs.getString(6));
                inquilinos.setCorreo(rs.getString(7));
                inquilinos.setDeuda(rs.getDouble(8));
                inquilinos.setFecha_ingreso(LocalDate.parse(rs.getString(9)));
                list.add(inquilinos);
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return list;
    }

    @Override
    public Inquilinos inquilinosGet(Integer id) {
        Inquilinos inquilino = new Inquilinos();
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(" FROM inquilinos WHERE idinquilinos = ?");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setInt(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    inquilino.setIdinquilinos(rs.getInt(1));
                    inquilino.setDni(rs.getString(2));
                    inquilino.setNombres(rs.getString(3));
                    inquilino.setPaterno(rs.getString(4));
                    inquilino.setMaterno(rs.getString(5));
                    inquilino.setTelefono(rs.getString(6));
                    inquilino.setCorreo(rs.getString(7));
                    inquilino.setDeuda(rs.getDouble(8));
                    inquilino.setFecha_ingreso(LocalDate.parse(rs.getString(9)));
                } else {
                    inquilino = null;
                }
            } catch (SQLException e) {
                mensaje = e.getMessage();
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return inquilino;
    }

    @Override
    public String inquilinosIns(Inquilinos inquilino) {
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO inquilinos( ")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(") VALUES (?,?,?,?,?,?,?,?) ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setString(1, inquilino.getDni());
            ps.setString(2, inquilino.getNombres());
            ps.setString(3, inquilino.getPaterno());
            ps.setString(4, inquilino.getMaterno());
            ps.setString(5, inquilino.getTelefono());
            ps.setString(6, inquilino.getCorreo());
            ps.setDouble(7, inquilino.getDeuda());
            ps.setString(8, inquilino.getFecha_ingreso().toString());
            int ctos = ps.executeUpdate();
            if (ctos == 0) {
                mensaje = "cero filas insertadas";
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String inquilinosDel(List<Integer> ids) {
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM inquilinos WHERE ")
                .append("idinquilinos = ? ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            cn.setAutoCommit(false);
            boolean ok = true;
            for (int id = 0; id < ids.size(); id++) {
                ps.setInt(1, ids.get(id));
                int ctos = ps.executeUpdate();
                if (ctos == 0) {
                    ok = false;
                    mensaje = "ID: " + ids.get(id) + " no existe";
                }
            }
            if (ok) {
                cn.commit();
            } else {
                cn.rollback();
            }
            cn.setAutoCommit(true);
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String inquilinosUpd(Inquilinos inquilino) {
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE inquilinos SET ")
                .append("dni = ?,")
                .append("nombres = ?,")
                .append("paterno = ?,")
                .append("materno = ?,")
                .append("telefono = ?,")
                .append("correo = ?,")
                .append("deuda = ?,")
                .append("fecha_ingreso = ? ")
                .append("WHERE idinquilinos = ? ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setString(1, inquilino.getDni());
            ps.setString(2, inquilino.getNombres());
            ps.setString(3, inquilino.getPaterno());
            ps.setString(4, inquilino.getMaterno());
            ps.setString(5, inquilino.getTelefono());
            ps.setString(6, inquilino.getCorreo());
            ps.setDouble(7, inquilino.getDeuda());
            ps.setString(8, inquilino.getFecha_ingreso().toString());
            ps.setInt(9, inquilino.getIdinquilinos());
            int ctos = ps.executeUpdate();
            if (ctos == 0) {
                mensaje = "No se pudo actualizar";
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String getMessage() {
        return mensaje;
    }
}

Teniendo la siguiente estructura de carpetas para un proyecto de NetBeans:



domingo, 15 de septiembre de 2019

DTO - Objeto de transferencia de datos

Cuando creamos una aplicación que recibirá peticiones de un cliente, por cada dato que enviemos se realizará una llamada remota, es decir que si tenemos, por ejemplo, una tabla que contiene: código, nombre, apellidos y fecha de nacimiento de un empleado; y nuestro cliente realiza una petición para saber esos datos, se realizará una llamada dato por dato generando 4 llamadas. Para evitar ese consumo de recursos y realizar una comunicación más fluida un DTO empaqueta todos esos datos en un solo objeto reduciendo las llamadas a solo 1.

Los DTO son las clases entidad, estas se pasean por todas las capas cuando se aplica un patrón de diseño de Software como el MVC, MVP o MVVM, se asemejan a las clases en la POO, pero no poseen lógica del negocio.

Características

Teniendo como insumo una tabla de una base de datos como:


Podemos establecer que sus características son:

  • La estructura es idéntica a la de una clase del paradigma de la programación orientada a objetos (POO)
  • Debe cumplir con el encapsulamiento (sus atributos deben tener acceso private) y herencia.
  • Solo debe tener como métodos el constructor (sin parámetros) y los Setter/Getter
  • Como método de buena práctica los atributos deben tener el mismo nombre que los campos de la tabla.


Ejemplo en Java

package dto;

import java.time.LocalDate;

public class Inquilinos {
    private Integer idinquilinos;
    private String dni;
    private String nombres;
    private String paterno;
    private String materno;
    private String telefono;
    private String correo;
    private Double deuda;
    private LocalDate fecha_ingreso;
    public Inquilinos() {
    }
    public Integer getIdinquilinos() {
        return idinquilinos;
    }
    public void setIdinquilinos(Integer idinquilinos) {
        this.idinquilinos = idinquilinos;
    }
    public String getDni() {
        return dni;
    }
    public void setDni(String dni) {
        this.dni = dni;
    }
    public String getNombres() {
        return nombres;
    }
    public void setNombres(String nombres) {
        this.nombres = nombres;
    }
    public String getPaterno() {
        return paterno;
    }
    public void setPaterno(String paterno) {
        this.paterno = paterno;
    }
    public String getMaterno() {
        return materno;
    }
    public void setMaterno(String materno) {
        this.materno = materno;
    }
    public String getTelefono() {
        return telefono;
    }
    public void setTelefono(String telefono) {
        this.telefono = telefono;
    }
    public String getCorreo() {
        return correo;
    }
    public void setCorreo(String correo) {
        this.correo = correo;
    }
    public Double getDeuda() {
        return deuda;
    }
    public void setDeuda(Double deuda) {
        this.deuda = deuda;
    }
    public LocalDate getFecha_ingreso() {
        return fecha_ingreso;
    }
    public void setFecha_ingreso(LocalDate fecha_ingreso) {
        this.fecha_ingreso = fecha_ingreso;
    }
}


Beneficios

Reducción del número de llamadas remotas: mediante una sola llamada donde trae todos los datos contenidos en un solo objeto se logra reducir la cantidad de estas y aumentar la velocidad de respuesta.

Protección del funcionamiento interno del programa: al pasar los datos encapsulados se provee una mayor seguridad ante ingeniería inversa.

Obtener objetos de negocio: en ocasiones podemos encontrar que un DTO es común a muchos negocios o áreas y puede ser considerado un objeto de negocio sirviendo como plantilla para futuras implementaciones a los programadores, desarrolladores, analistas, etc.

Facilidad de pruebas. Si se aplican lenguajes de intercambio como XML o Json, mediante un DTO se puede realizar pruebas con mayor facilidad pára comprobar la integridad de los datos o el funcionamiento de la aplicación.