Como enviar un email en Java con la API JavaMail

Como enviar un correo electronico con Java usando la API JavaMail. Desde hace tiempo estaba pensado en exponer algo respecto a este tema y por fin me decidi a hacerlo. El ejemplo en si es muy sencillo pero util si lo necesitas usar inmediatamente.

Herramientas que necesitas

Necesitas principalmente dos cosas:

  • Libreria JavaMail.
  • libreria JAF ( JavaBeans Activation Framework ).

Como observas, te e puesto un link a la pagina de descarga de cada libreria, esa es la que he utilizado y que a la fecha me ha funcionado. Lo que debes hacer es bajarte los .zip, poner todos los archivos .jar juntos y agregarlos a la variable de entorno CLASSPATH de tu sistema operativo. Si no te quieres molestar en entrar a la pagina a continuacion yo ya los he bajado y a continuacion te dejo el link de descarga directa de la libreria JavaMail que contiene los JAR: dns.jar, imap.jar, mail.jar, mailapi.jar, pop3.jar, smtp.jar, la libreria JAF contiene un unico jar activation.jar.

Sigamos con lo interesante…

El codigo fuente

A continuacion pego el codigo fuente para el envio de el correo electronico que por cierto es muy corto. Sino fuera por la sencilla GUI que e creado….

/*
	Descripcion: Sencillo ejemplo de como enviar un Email con la libreria JavaMail
			a travez de una interfaz grafica.
	Author: Gonzalo Silverio    gonzasilve@gmail.com
	Archivo:  FrmVentanaMail.java
	Fuente:		https://gonzasilve.wordpress.com/
 **/
 
import javax.swing.*;
import java.awt.*;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import java.util.Properties;

//Para manejo de JavaMail
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class FrmVentanaMail extends JFrame {

	//Para el cuadro de dialogo de Opciones
	JPanel pnlServidor;
	JPanel pnlBotones;
	JPanel pnlRemitente;
	JPanel pnlPasswordRemitente;
	JPanel pnlDestino;
	JPanel pnlAsunto;
	JPanel pnlMensaje;
	
	JLabel lblServidor; 	JTextField jtfServidor;
	
	JLabel lblRemitente; 	JTextField jtfRemitente;	JPasswordField jpfPasswordRemitente;
	JLabel lblDestino; 	JTextField jtfDestino;
	JLabel lblAsunto; 	JTextField jtfAsunto;
	JLabel lblMensaje; 	JTextArea jtaMensaje;
	
	JButton btnEnviar;
	JButton btnCancelar;
	
	public FrmVentanaMail(String strTitulo, int i_ancho, int i_alto ) {
		this.setTitle(strTitulo);
    this.setSize(i_ancho,i_alto);    
    this.setLocationRelativeTo(null);

		this.setResizable(false);
		
		Box boxPrincipal = Box.createVerticalBox();
		crearCamposVentana();
		crearBotones();
		boxPrincipal.add(Box.createVerticalStrut(15));
		boxPrincipal.add(pnlServidor);
		boxPrincipal.add(Box.createVerticalStrut(15));
		boxPrincipal.add(pnlRemitente);
		boxPrincipal.add(Box.createVerticalStrut(15));
		boxPrincipal.add(pnlDestino);
		boxPrincipal.add(Box.createVerticalStrut(15));
		boxPrincipal.add(pnlAsunto);
		boxPrincipal.add(Box.createVerticalStrut(15));
		boxPrincipal.add(pnlMensaje);
		boxPrincipal.add(Box.createVerticalStrut(15));
		boxPrincipal.add(pnlBotones);
		
		add(boxPrincipal);
		
		btnCancelar.addActionListener( new ActionListener() {			
				public void actionPerformed(ActionEvent evt) {
					//dispose();
					System.exit(0);
				}
			}
		);
		
		btnEnviar.addActionListener( new ActionListener() {			
				public void actionPerformed(ActionEvent e) {
					if(enviarEmail() ) {
						JOptionPane.showMessageDialog(null,"Mensaje enviado!");
						jtaMensaje.requestFocus(true);
					} else {
						JOptionPane.showMessageDialog(null,"Por el momento NO SE PUDO ENVIAR el mensaje.");
					}
					
				}			
			}			
		);
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	
	}
	
	private void crearCamposVentana() {
		Box boxServidor =  Box.createHorizontalBox();
		lblServidor = new JLabel("Servidor");
		jtfServidor = new JTextField("smtp.gmail.com",15);		
		boxServidor.add(Box.createHorizontalStrut(15));
		boxServidor.add(lblServidor);
		boxServidor.add(Box.createHorizontalStrut(20));
		boxServidor.add(jtfServidor);
		pnlServidor = new JPanel(new FlowLayout(FlowLayout.LEFT));
		pnlServidor.add(boxServidor);
		
		//Remitente
		Box boxRemitente =  Box.createHorizontalBox();
		lblRemitente = new JLabel("<html><font color='#0000FF'>Remitente</font></html>");
		jtfRemitente = new JTextField("gonzasilve@gmail.com",15);
		jpfPasswordRemitente =  new JPasswordField(15);
		jpfPasswordRemitente.setToolTipText("Escriba el password de este remitente");
		boxRemitente.add(Box.createHorizontalStrut(15));
		boxRemitente.add(lblRemitente);
		boxRemitente.add(Box.createHorizontalStrut(20));
		boxRemitente.add(jtfRemitente);
		boxRemitente.add(Box.createHorizontalStrut(5));
		boxRemitente.add(jpfPasswordRemitente);
		pnlRemitente = new JPanel(new FlowLayout(FlowLayout.LEFT));
		pnlRemitente.add(boxRemitente);
	
		//Destino
		Box boxDestino =  Box.createHorizontalBox();
		lblDestino = new JLabel("<html><font color='#0000FF'>Destino</font></html>");
		jtfDestino = new JTextField("gonzasilve@hotmail.com",15);
		jtfDestino.setToolTipText("Puede escribir varios destinatarios separados con coma");
		boxDestino.add(Box.createHorizontalStrut(15));
		boxDestino.add(lblDestino);
		boxDestino.add(Box.createHorizontalStrut(20));
		boxDestino.add(jtfDestino);
		pnlDestino = new JPanel(new FlowLayout(FlowLayout.LEFT));
		pnlDestino.add(boxDestino);			
			
		//Asunto
		Box boxAsunto =  Box.createHorizontalBox();
		lblAsunto = new JLabel("<html><font color='#0000FF'>Asunto</font></html>");
		jtfAsunto = new JTextField("Test JavaMail",15);		
		boxAsunto.add(Box.createHorizontalStrut(15));
		boxAsunto.add(lblAsunto);
		boxAsunto.add(Box.createHorizontalStrut(20));
		boxAsunto.add(jtfAsunto);
		pnlAsunto = new JPanel(new FlowLayout(FlowLayout.LEFT));
		pnlAsunto.add(boxAsunto);		
			
		//Mensaje
		Box boxMensaje =  Box.createHorizontalBox();
		lblMensaje = new JLabel("<html><font color='#0000FF'>Mensaje</font></html>");
		jtaMensaje = new JTextArea("Mensaje desde JavaMail",5,30);
		jtaMensaje.setLineWrap(true);
		JScrollPane jspScrollMsg = new JScrollPane(jtaMensaje);

		jtaMensaje.setAutoscrolls(true);
		boxMensaje.add(Box.createHorizontalStrut(15));
		boxMensaje.add(lblMensaje);
		boxMensaje.add(Box.createHorizontalStrut(20));
		boxMensaje.add(jspScrollMsg);
		pnlMensaje = new JPanel(new FlowLayout(FlowLayout.LEFT));
		pnlMensaje.add(boxMensaje);
	}
	
	private void crearBotones() {
		btnEnviar = new JButton("Enviar email");
		btnCancelar = new JButton("Cancelar");
		Box boxBotones = Box.createHorizontalBox();
		boxBotones.add(btnEnviar);
		boxBotones.add(Box.createHorizontalStrut(25));
		boxBotones.add(btnCancelar);
		boxBotones.add(Box.createHorizontalStrut(25));
		pnlBotones = new JPanel(new FlowLayout(FlowLayout.RIGHT));
		pnlBotones.add(boxBotones);
				
	}
	
	private void mostrar() {
		setVisible(true);
	}
	
	//Devuelve true en caso de que se envie el email de manera correcta, o
	//devuelve false si no se pudo enviar el email
	private boolean enviarEmail() {
    try
    {
        // Propiedades de la conexión
        Properties props = new Properties();
        props.setProperty("mail.smtp.host",  "smtp.gmail.com");
        props.setProperty("mail.smtp.starttls.enable", "true");
        props.setProperty("mail.smtp.port", "587");
        props.setProperty("mail.smtp.auth", "true");

        // Preparamos la sesion
        Session session = Session.getDefaultInstance(props);
				
	//Recoger los datos
	String str_De 		= jtfRemitente.getText();
	String str_PwRemitente 		= jpfPasswordRemitente.getText();				
	String str_Para 	= jtfDestino.getText();
	String str_Asunto = jtfAsunto.getText();
	String str_Mensaje = jtaMensaje.getText();
	//Obtenemos los destinatarios
	String destinos[] = str_Para.split(",");
				
        // Construimos el mensaje
        MimeMessage message = new MimeMessage(session);
        
        message.setFrom(new InternetAddress( str_De ));

	//Otra forma de especificar las direcciones de email 
	//a quienes se enviar el correo electronico
	//Forma 1
        //Address [] receptores = new Address []{
	//      new InternetAddress ("fuerenio@gmail.com"),
	//      new InternetAddress ("gonzasilve@gmail.com")
	//  };
	//Forma 2
	//  Address [] receptores = new Address []{
	//      new InternetAddress ( str_De )
	// };
	//Forma 3
        Address [] receptores = new Address [ destinos.length ];
        int j = 0;
	while(j<destinos.length){					
		receptores[j] = new InternetAddress ( destinos[j] ) ;					
		j++;				
	}

        
        //receptores.
        message.addRecipients(Message.RecipientType.TO, receptores);        
        message.setSubject( str_Asunto );        
        message.setText( str_Mensaje );
            
        // Lo enviamos.
        Transport t = session.getTransport("smtp");
        t.connect(str_De, str_PwRemitente);
        t.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
				
        // Cierre de la conexion.
        t.close();
        return true;
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return false;
    }		
	}
	
	public static void main(String gonzi[]) {
		FrmVentanaMail prueba1 = new FrmVentanaMail("Envio de email con JavaMail", 500, 400);
		prueba1.mostrar();
	}
	
}

En si no hay mucho que explicar, el metodo mas importante de la clase anterior es enviarEmail() pues es el que toma los datos de las cajas de texto y los configura como parametros para JavaMail y envia el mensaje escrito, usando el email remitente a los emails destino. Si observas éste devuelve un valor booleano para poder determinar el mensaje que se le muestra al usuario despues de que pulsa el boton Enviar email.

Pantallas del ejemplo

A continuación la pantalla que se dibuja al ejecutar el código anterior (e rellenado algunos campos):
GUI para enviar email con JavaMail

Si el email se envió correctamente aparece el siguiente mensaje:
Envio exitoso con JavaMail

El email que le llega al email destino es el siguiente:
Email recibido, fue enviado desde JavaMail

En caso de dudas, ó si te gusto el ejemplo te invito a que me dejes un comentario (me motivas a escribir mas). Si gustas tener el codigo por fa, dejame un comentario y te lo envio a la brevedad.

Hasta pronto.

Determinar si un año es Bisiesto

En esta ocasion y a peticion de un visitante del blog les dejo el codigo para determinar si un Año es bisiesto.

//              Instituto Tecnologico de Zacatepec
//      Descripcion:  Validacion de si un anio es bisiesto
//      Author: Gonzalo Silverio   gonzasilve@gmail.com
//      Archivo: AnioBisiesto.java

import java.util.GregorianCalendar;

public class AnioBisiesto {

   public static void main(String[] args) {

      String res = new String();
      for(int i=2000; i<=2012; i++)
      {
         res = esBisiesto(i) ? "Anio bisiesto" : "Anio NO bisiesto";
         System.out.println(i+" "+res);
         System.out.println("Comprobando con clase java GregorianCalendar...");
         res = esBisiestoJava(i) ? "Anio bisiesto" : "Anio NO bisiesto";
         System.out.println(i+" "+res+"\n----------");
      }
   }
   
   private static boolean esBisiesto(int anio)
   {
      int elanio = anio;

      if ((elanio % 4 == 0) && ((elanio % 100 != 0) || (elanio % 400 == 0)))
         return true;
      else
         return false;
   }
   
   private static boolean esBisiestoJava(int anio)
   {
      int elanio = anio;
      GregorianCalendar calendar = new GregorianCalendar();
      return calendar.isLeapYear(elanio);
   }

}

Parte de la salida de ejecucion en Netbeans:

Salida en Netbeans

Salida en Netbeans

Quien este interesado en el codigo solo basta con dejar su correo. Gracias x visitar. Hasta pronto.

Clase java para recorrer y buscar registros de tabla (de Sql Server, Mysql o Postgres) con botones primero, anterior, siguiente y ultimo.

Clase java para recorrer y buscar registros de tabla de base de datos con botones primero, anterior, siguiente y ultimo. El objetivo de esta entrada de blog es mostrar una clase diseñada por mi para facilitar la navegacion por los registros de una tabla. Se me ocurrio esto debido a que en muchas ocasiones en los programas necesitamos recorrer los registros de una tabla con los tipicos botones:
Primero Permite ir al primer registro de la tabla.
Anterior Permite ir al anterior registro.
Siguiente Permite ir al siguiente registro.
Ultimo Permite ir al ultimo registro.

La siguiente imagen muestra un ejemplo clasico donde se requieren estos botones (los botones con flechas verdes):

Ventana con botones de navegacion de registros.
Ventana con botones de navegacion de registros.

Como se puede imaginar con ayuda de estos botones nos podemos colocar en cualquier registro de la tabla y una vez posicionados en el registro deseado se pueden usar otros botones para modificar o eliminar el registro. Bueno sin mas preambulos muestro el codigo de la clase:

GonzaBD.java
El truco de esta clase es almacenar en un array todos los campos llave de la tabla que se desee manipular (por cada tabla se debe crear un nuevo objeto de esta clase). Al llamar al metodo primero() con ayuda de una variable se accede al primer elemento del arreglo de llaves primarias. Al llamar al metodo ultimo() con ayuda de una variable se accede al ultimo elemento del arreglo de llaves primarias. Al llamar al metodo siguiente() con ayuda de una variable; si por ejemplo estamos en la fila 5, se accede al elemento 5 +1, del arreglo de llaves primarias. Despues se realiza un Select hacia la tabla y los datos quedan en un Objeto Resultset (llamado rs) que es local a esta clase, bueno a continuacion muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que contiene metodos para recorrer los registros de una tabla 
 *						hacia el primer, anterior, siguiente o ultimo registro
 * Archivo: GonzaBD.java
 * author Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */
import java.sql.*;


public class GonzaBD 
{
	String strSentenciaSQL = "";
	String strCadenaConexion = "";
	String strOrdenarPor = "";
	String strCampoLLave = "";
	String strTabla = "";
	String strArrayCamposLlave[];
	int intArrayCamposLlave[];
	
	//Los posibles tipos del campo llave son cadena y entero
	//Por defecto el campo llave es de tipo cadena
	String strTipoCampoLlave = "cadena";
	
	int intTotalRegistros = 0,intFilaActual = 0;	
	
	String strDriverMySQL 		="com.mysql.jdbc.Driver";
	String strDriverPostgres 	="org.postgresql.Driver";
	String strDriverSqlServer 	="net.sourceforge.jtds.jdbc.Driver";	
	
	String strManejador 		= "mysql";
	String strBaseDatos 		= "BD";
	String strServidor 		= "localhost";
	String strUsuario 		= "usuario";
	String strPassword		= "password";
	String strControlador 	= strDriverMySQL;
	String strPuerto			= "3306";
	
	private static Connection con = null;
	Statement st;
	ResultSet rs;
	
    public GonzaBD()
    {
    	
    }
    
    //se mueve a la primera fila y devuelve true si se pudo, false sino se pudo ir a la primera fila
    public  boolean  primero()
    {
      try
		{
			intFilaActual = 0;
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la anterior fila y devuelve true si se pudo, false sino se pudo ir a la anterior fila
    public  boolean  anterior()
    {
      try
		{
			intFilaActual--;
			if(intFilaActual<0)
				intFilaActual=0;
				
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la siguiente fila y devuelve true si se pudo, false sino se pudo ir a la siguiente fila
    public  boolean  siguiente()
    {
      try
		{
			intFilaActual++;
			if(intFilaActual>intTotalRegistros-1)
				intFilaActual=intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //se mueve a la ultima fila y devuelve true si se pudo, false sino se pudo ir a la ultima fila
    public  boolean  ultimo()
    {
      try
		{
			intFilaActual = intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);
				
			if( rs.next() )
				return true;
			
			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
	 
	//Obtiene el controlador del manejador mysql o postgres
    public  String obtenerDriverManejador(String manejador)
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
			return strDriverSqlServer;
		else if(manejador.equals("mysql"))							//Si el manejador es mysql
			return strDriverMySQL;
		else if(manejador.equals("postgres"))							//Si el manejador es postgres
			return strDriverPostgres;

			//en caso d k no sea ninguno devuelve el de MySQL			
			return strDriverMySQL;
    }
  	
	//Conecta a la BD con los datos por default
    public boolean conectarBD() throws SQLException
    {    
      try
		{
			return conectarServidor(strManejador,strServidor,strUsuario,strPassword,strBaseDatos,strControlador);
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    

	//Conecta a la BD con los datos del usuario, bd y password especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD )// throws SQLException
    {
    	boolean ress;
      try
		{
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			ress = conectarServidor(strManejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
    //permite especificar el campo por el que se van a ordenar los registros
    public  void ordenarPor(String campo)
    {
    	strOrdenarPor = campo;
    }
    
	//Conecta a la BD con los datos especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD, String manejador) //throws SQLException
    {
    	boolean ress;
      try
		{
			strControlador = obtenerDriverManejador(manejador);			
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			strManejador 	= manejador;
			ress = conectarServidor(manejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }
    
	//Realiza una conexion a sqlserver, mysql o postgres con los datos especificados
    public boolean conectarServidor(String manejador,String servidor,String usuario,String pw,String bd, String driver) throws SQLException
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
		{
		    try
		    {
		        Class.forName(driver);
		        strCadenaConexion = "jdbc:jtds:sqlserver://"+servidor+"/"+bd+";instance=SQLSERVEREXPRESS;";
		        con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		        if (con == null )
		    			return false;
		        return true;
		    }
		    catch(SQLException sqlex)
		    {
		    		sqlex.printStackTrace();
		        	return false;
		    }
		    catch(Exception e)
		    {
		    		e.printStackTrace();
		        	return false;
		    }
		}            
    	else if(manejador.equals("mysql"))									//Si el manejador es mysql
    	{
           try
           {
		          Class.forName(driver);
		          strCadenaConexion = "jdbc:mysql://"+servidor+"/"+bd;
		          con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		          if (con == null )		          	
		          	return false;
		          
		          return true;
            }
            catch(SQLException sqlex)
            {
            	sqlex.printStackTrace();
                return false;
            }
            catch(Exception e)
            {
            	e.printStackTrace();
            	return false;
            }
    	}
    	else if(manejador.equals("postgres"))							//Si el manejador es postgress
      {
          try
          {
              Class.forName(driver);
              strCadenaConexion = "jdbc:postgresql://"+servidor+":5432/"+bd;
              con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
              if (con == null )
          			return false;

              return true;
          }
          catch(SQLException sqlex)
          {

          		sqlex.printStackTrace();
              	return false;
          }
          catch(Exception e)
          {
          	e.printStackTrace();
              return false;
          }
      }

	    	return false;
    }
    
	//Ejecuta un SELECT y devuelve el Resultset con los resultados
	public ResultSet ejecutarConsulta(String cadSQ) throws SQLException
	{
		rs = null;
		if( ! strOrdenarPor.equals("") )
			cadSQ += " ORDER BY " +strOrdenarPor;
			
		try
		{
			rs = st.executeQuery(cadSQ);
			return rs;
       }
       catch(SQLException sqlex)
       {
       		sqlex.printStackTrace();
       		return rs;
       }

	}

	public  void obtenerCamposLlave()
	{
		obtenerCamposLlave(strTabla);
	}
	

	//Si el campo llave es de tipo entero guarda las llaves primarias en un arreglo de enteros
	//Si el campo llave es de tipo cadena guarda las llaves primarias en un arreglo de Strings
	public  void obtenerCamposLlave(String tabla)
	{
		int c=0;
		try
		{
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			while(rs.next())
				c++;
			intTotalRegistros = c;
			strArrayCamposLlave = new String[intTotalRegistros];
			intArrayCamposLlave = new int[intTotalRegistros];
			
			cerrar(rs);		//Cerrar consulta anterior
			//Ejecutar nuevamente la consulta
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			rs.next();		//Moverse al primer registro
			
			c=0;
			do
			{			//determina el tipo del campo llave y en base a eso guarda en el array correspondiente
				if( strTipoCampoLlave.equals("cadena") )				
					strArrayCamposLlave[c] = rs.getString(strCampoLLave);
				else
					intArrayCamposLlave[c] = rs.getInt(strCampoLLave);
					
				c++;
			}while( rs.next() );
			
		}
		catch(SQLException sqlex)
		{
       	sqlex.printStackTrace();
		}
		
	}

	
	// Cierra un objeto Resultset
	public static void cerrar(ResultSet rs)
	{	
		try
		{
			rs.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	// cierra un objeto Statemet
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// Cierra un objeto Connection
	public static void cerrar(Connection con)
	{	
		try
		{
			con.close();
		} 
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	
	//Permite especificar cual es el campo llave de la tabla
	public  void setCampoLlave(String campo)
	{
		strCampoLLave = campo;
	}
	
	//Permite especificar cual es el campo llave y su tipo, de la tabla
	public  void setCampoLlave(String campo, String tipo)
	{
		strCampoLLave = campo;
		strTipoCampoLlave = tipo;
	}
	
	public void setTipoCampoLlave(String tipo)
	{
		strTipoCampoLlave = tipo;
	}
	
	//Especifica la tabla sobre la k se va a trabajar
	public  void setTabla(String tabla)
	{
		try
		{
			strTabla = tabla;
			st=con.createStatement();
		}
		catch(SQLException ex)
		{
			ex.printStackTrace();
		}

	}	
}	//Fin de la clase

Lo interesante de esta clase es que esta preparada para recorrrer los registros de tablas que esten creadas en cualquera de los manejadores SQL Server, MySQL o de Postgres, obviamente que los .jar de los JConnector de dichos DBMS deben estar copiados en C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext, Lo que esta en negrita lo e resaltado debido a que la version del JVM puede cambiar segun la que tengas instalada. Los JConnector que e usado para probar esta clase son los siguientes (puedes dar click en el enlace para descargarlo sino lo tienes).
JConnector de SQL Server: jtds-1.2.5.jar
JConnector de Postgres: postgresql-9.1-901.jdbc4.jar
JConnector de MySQL: mysql-connector-java-5.1.18-bin.jar

Para ejemplificar el uso de la clase anterior e usado una tabla que esta en SQL Server. Los parametros de conexion son:
Manejador de Base de datos (DBMS): SQL Server 2005 Express
Base de datos: prueba
Tabla: tbl_alumnos
Usuario: sa
Password: 123456
El Script para crear la tabla alumnos en SQL Server es el siguiente (generado con el Microsoft SQL Server Management Studio):

USE [prueba]
GO
/****** Object:  Table [dbo].[tbl_alumnos]    Script Date: 12/28/2011 17:59:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tbl_alumnos](
	[matricula] [int] NOT NULL,
	[nombre] [varchar](50) NULL,
	[apellidos] [varchar](100) NULL,
	[edad] [int] NULL,
	[peso] [decimal](10, 2) NULL,
	[sexo] [char](1) NULL,
 CONSTRAINT [PK__tbl_alumnos__6FBF826D] PRIMARY KEY CLUSTERED
(
	[matricula] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

La imagen de la tabla ya creada en SQL Server se ve asi:

Tabla Alumnos en SQL Server

DIAGRAMA UML DE LA CLASE gonzaBD

Diagrama UML de la clase gonzaBD

Diagrama UML de la clase gonzaBD

BREVE EXPLICACION DE LOS ATRIBUTOS DE LA CLASE gonzaBD:

Atributo Descripcion
intfilaActual Contiene un número que se usa como índice para acceder a una llave primaria dentro del arreglo strArrayCamposLlave o el arreglo strArrayCamposLlave (dependiendo de si la llave primaria es de tipo cadena o tipo entero, respectivamente). Este atributo contiene el número actual de fila-1.
strArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Cadena.
intArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Entero.
rs Contiene los datos de la fila actual mostrandose. Cada vez que se manda a llamar al método primero(), anterior(), siguiente() o ultimo() se realiza una consulta y este atributo (tipo Resultset) se actualiza con los campos de la nueva fila.

COMO SE USA LA CLASE gonzaBD
A continuacion voi a poner un fragmento de codigo con la intencion mostrar los pasos a realizar para usar correctamente la clase.

//Crear un objeto de esta clase
GonzaBD a = new GonzaBD();
//AHORA SE DEBE REALIZAR LO SIGUIENTE EN EL MISMO ORDEN…
//Primeramente se debe indicar especificar cual es la llave primaria de la tabla y su tipo
a.setCampoLlave("matricula","entero");
//Se de desea se puede indicar que si se desean ordenar los registros de la tabla por un campo, //este paso es opcional en todo caso sino se realiza, no se ordenan por ningún campo
a.ordenarPor("nombre");
//A continuación usamos un metodo sobrecargado para conectarse al DBMS, aquí es donde //indicamos a que manejador se debe accesar
a.conectarBD("sa","12345","pruebas","sqlserver");
//Una vez que ya estamos conectados se debe especificar la tabla que se va a manipular
a.setTabla("tbl_alumnos");
//Ahora se manda a llamar al método que rellena el arreglo de llaves primarias dentro de la clase; //dependiendo del tipo de dato del campo llave se rellena el arreglo de Strings o el arreglo de //enteros.
a.obtenerCamposLlave();
//Ahora ya se puede llamar a cualquiera de los métodos primero(), anterior(), siguiente() o ultimo()...

Despues de realizar lo anterior, para que el objeto rs se rellene con los datos de la primera fila se invoca al metodo:
a.primero();
Después de que se invoco ese metodo, el atributo rs de la clase gonzaBD se quedara con los datos de la fila 1. Supongamos que la tabla “alumnos”contiene las siguientes filas, rs apuntara a la fila:

El atributo rs esta en la posicion de la primera fila.

El atributo rs esta en la posicion de la primera fila.

Si inmediatamente despues se llama al método siguiente()
a.siguiente();
El atributo rs apuntara al siguiente registro despues del primero, es decir rs apuntara a la fila:

El atributo rs apunta a los datos de la segunda fila

El atributo rs apunta a los datos de la segunda fila

Y asi sucesivamente, una observación: si te fijas en el codigo de los metodos (siguiente() y anterior()) cuando se ha llegado a la ultima fila, es decir, si rs apunta al registro 4 y se ejecuta una llamada al método siguiente() (se intenta accesar una fila después de la ultima); dicho método contiene un ‘candado’ para detectar eso y siempre dejara a rs apuntando al ultimo registro. El método anterior() igualmente tiene esa precaucion y siempre que se intente accesar a un registro antes del primero automáticamente moverá a rs para que apunte a la primera fila. De esta manera no es posible sobrepasar los limites (inferior ni superior) de filas de la tabla que se este manipulando.

Finalmente Para ilustrar el uso de la clase gonzaBD anterior he creado una ventana muy basica.

JfrPrincipal.java
Esta clase crea una ventana de formulario con 6 campos y los 4 botones; primero, anterior, siguiente y ultimo en la parte inferior de dicha ventana. Es la misma clase que utilice para ilustrar como usar ventanas de formulario en Java, pero la he modificado con algunos campos mas. Bueno ahora muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que crea una GUI para ilustrar el uso de la clase GonzaBD
 * Archivo: JfrPrincipal.java
 * author: Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

//Se usara para cambiar los Margenes de los botones
import java.awt.Insets;

//Para Manejo de BD
import java.sql.*;

public class JfrPrincipal extends JFrame
{
	//Campos de texto y sus etiquetas 
	JLabel jlbMatricula;    JTextField  jtfMatricula;
	JLabel jlbNombre;       JTextField  jtfNombre;
	JLabel jlbApellidos;    JTextField  jtfApellidos;
	JLabel jlbEdad;         JTextField  jtfEdad;
	JLabel jlbPeso;         JTextField  jtfPeso;
	JLabel jlbSexo;         JComboBox   jcbSexo;
	
	//Botones de navegacion de los registros
	JButton btnPrimero;
	JButton btnAnterior;
	JButton btnSiguiente;
	JButton btnUltimo;
	
	Box boxVCamposVentana;   //Contiene todo los campos de texto (con su respectiva etiqueta)
	JPanel panBotones;      //Contiene los botones Guardar y Cancelar
	
	//Objeto de la clase que nos ayuda a navegar por los registros de la tabla
	GonzaBD bd = new GonzaBD();
	
	JfrPrincipal(String strTitulo, int intAncho, int intAlto)
	{
		super(strTitulo);
		this.setSize(intAncho, intAlto);
		this.setResizable(false);		//Ventana no redimensionable
		this.setLocationRelativeTo(null);       //Centrar ventana en pantalla
		
		//Box vertical por que los botones van a estar abajo
		Box boxVContenidoVerticalVentana = Box.createVerticalBox();
		crearCamposVentana();
		crearBotones();
		//Espacio del borde superior de la ventana al primer Campo
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(30));
		boxVContenidoVerticalVentana.add(boxVCamposVentana);
		//Espacio entre el ultimo campo (sexo) y los botones Guardar y Cancelar
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(20));
		boxVContenidoVerticalVentana.add(panBotones);
		
		this.add(boxVContenidoVerticalVentana);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  
	  //Conecta la Base de datos
		conectarBD();
		bd.primero();		//Posicionarse en el primer registro
		rellenarCampos();		//Rellenar los campos con los datos del primer registro
		
		//ASIGNAR UN ESCUCHADOR PARA CADA BOTON DE NAVEGACION
		//Boton Primero
		btnPrimero.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.primero();
				rellenarCampos();
			}
		});
		//Boton Anterior
		btnAnterior.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.anterior();
				rellenarCampos();
			}
		});
		//Boton Siguiente
		btnSiguiente.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.siguiente();
				rellenarCampos();
			}
		});
		//Boton Ultimo
		btnUltimo.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.ultimo();
				rellenarCampos();
			}
		});
		  	
        	
	}		//Fin del constructor

	//Crea los campos de la ventana (cada caja tiene su correspondiente etiqueta)
    private void crearCamposVentana()
    {
        Box boxHMatricula =  Box.createHorizontalBox();        
        jlbMatricula = new JLabel("Matricula ");   jtfMatricula = new JTextField(15);
        boxHMatricula.add(Box.createHorizontalStrut(20));
        boxHMatricula.add(jlbMatricula);
        boxHMatricula.add(Box.createHorizontalStrut(14));
        boxHMatricula.add(jtfMatricula);
        JPanel panMatricula =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panMatricula.add(boxHMatricula);

        Box boxHNombre =  Box.createHorizontalBox();
        jlbNombre = new JLabel("Nombre ");   jtfNombre = new JTextField(15);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jlbNombre);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jtfNombre);
        JPanel panNombre =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panNombre.add(boxHNombre);

        Box boxHApellidos =  Box.createHorizontalBox();
        jlbApellidos = new JLabel("Apellidos ");   jtfApellidos = new JTextField(15);
        boxHApellidos.add(Box.createHorizontalStrut(20));
        boxHApellidos.add(jlbApellidos);
        boxHApellidos.add(Box.createHorizontalStrut(11));
        boxHApellidos.add(jtfApellidos);
        JPanel panApellidos =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panApellidos.add(boxHApellidos);

        Box boxHEdad =  Box.createHorizontalBox();
        jlbEdad = new JLabel("Edad ");   jtfEdad = new JTextField(15);
        boxHEdad.add(Box.createHorizontalStrut(20));
        boxHEdad.add(jlbEdad);
        boxHEdad.add(Box.createHorizontalStrut(40));
        boxHEdad.add(jtfEdad);
        JPanel panEdad =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panEdad.add(boxHEdad);
        
        Box boxHPeso =  Box.createHorizontalBox();
        jlbPeso = new JLabel("Peso ");   jtfPeso = new JTextField(15);
        boxHPeso.add(Box.createHorizontalStrut(20));
        boxHPeso.add(jlbPeso);
        boxHPeso.add(Box.createHorizontalStrut(40));
        boxHPeso.add(jtfPeso);
        JPanel panPeso =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panPeso.add(boxHPeso);

        Box boxHSexo =  Box.createHorizontalBox();
        jlbSexo = new JLabel("Sexo ");   jcbSexo = new JComboBox();
        jcbSexo.addItem("Masculino");
        jcbSexo.addItem("Femenino");
        boxHSexo.add(Box.createHorizontalStrut(20));
        boxHSexo.add(jlbSexo);
        boxHSexo.add(Box.createHorizontalStrut(40));
        boxHSexo.add(jcbSexo);
        JPanel panSexo =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panSexo.add(boxHSexo);

        boxVCamposVentana = Box.createVerticalBox();
        boxVCamposVentana.add(panMatricula);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panNombre);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panApellidos);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panEdad);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panPeso);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panSexo);
    }

    private void crearBotones()
    {
        Box boxHBotones = Box.createHorizontalBox();
        
        btnPrimero = new JButton("|< Primero");
        btnAnterior = new JButton("< Anterior");
        btnSiguiente = new JButton("Siguiente >");
        btnUltimo = new JButton("Ultimo >|");
        //Cambiar los margenes de los botones
        			//Insets(margen_sup, margen_izq, margen_inf, margen_der)
        btnPrimero.setMargin(new Insets(0, 2, 0, 2));
        btnAnterior.setMargin(new Insets(0, 2, 0, 2));
        btnSiguiente.setMargin(new Insets(0, 2, 0, 2));
        btnUltimo.setMargin(new Insets(0, 2, 0, 2));
        
        boxHBotones.add(btnPrimero);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnAnterior);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnSiguiente);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnUltimo);
        
        panBotones =  new JPanel(new FlowLayout(FlowLayout.CENTER) );
        panBotones.add(boxHBotones);
    }
	//Conecta con la BD y devuelve true si se conecto correctamente
	//false en cualquiero otro caso
	public boolean conectarBD()
	{
		// Especificar cual es la llave primaria de la tabla y su tipo
		bd.setCampoLlave("matricula","entero");
    	bd.ordenarPor("nombre");	//Ordena los registros de la tabla por este campo
		
		//Conecta con el usuario, pass, BD y dbms (manejador) especificados
		bd.conectarBD("sa","12345","pruebas","sqlserver");
		
    	//especifica la tabla sobre la que se va a manipular
    	bd.setTabla("tbl_alumnos");
    	//Dentro del objeto bd rellena un arreglo con las llaves 
    	//primarias de la tabla que se esta manipulando
		bd.obtenerCamposLlave();
		
		return true;
	}
	
	//Rellena los campos de texto con los datos del registro actual
    public void rellenarCampos()
    {
		try
		{
    		jtfMatricula.setText(aCadena(bd.rs.getInt("matricula")));
    		jtfNombre.setText(bd.rs.getString("nombre").trim ());
    		jtfApellidos.setText(bd.rs.getString("apellidos").trim ());
    		jtfEdad.setText(aCadena(bd.rs.getInt("edad")));
    		jtfPeso.setText(aCadena(bd.rs.getFloat("peso")));
    		jcbSexo.setSelectedItem( bd.rs.getString("sexo").equals("f") ? "Femenino" : "Masculino" );
    		
    		this.setTitle("Alumno "+(bd.intFilaActual+1)+" de "+bd.intTotalRegistros);
		}
		catch( SQLException ex )
		{
			ex.printStackTrace();
		}
    }
    
    //Recibe un numero entero y lo devuelve como Cadena (String)
    private String aCadena(int num)
    {
    	return String.valueOf(num);
    }
    
    //Recibe un numero decimal y lo devuelve como Cadena (String)
    private String aCadena(float num)
    {
    	return String.valueOf(num);
    }
    
    private void mostrar()
    {
        this.setVisible(true);
    }

    public static void main(String args[])
    {
        JfrPrincipal prueba1 = new JfrPrincipal("Recorrer registros de SQL Server en Java",400,400);
        prueba1.mostrar();
    }
}

Y aqui una imagen de la ejecucion:

Ejecucion del ejemplo: Mostrando la tabla alumnos

Ejecucion del ejemplo: Mostrando la tabla alumnos

A diferencia de la otra entrada de blog anterior a esta, ahora se pueden realizar busquedas e igualmente se pueden recorrer los resultados con ayuda de la misma clase. La busqueda se puede realizar por matricula, nombre o por genero (sexo). Por ejemplo en caso de que decidamos buscar en los nombres de los alumnos la cadena ‘ar’, debemos marcar el radio nombre, escribir en la cajita ‘ar’ y dar clic en el boton Buscar en este caso se encontraron 4 resultados, como se muestra en la siguiente imagen:

Buscando por nombre a un alumno

Buscando por nombre a un alumno

Observa como automaticamente se desactivan los controles de busqueda y se muestran los resultados; los cuales tambien se pueden recorrer con los mismos botones de Primero, Anterior, Siguiente y Ultimo. Ademas el texto del boton Buscar cambia y ahora ese boton permite terminar la Busqueda. Al dar click en el boton Fin Busqueda se muestran nuevamente todos los alumnos de la tabla y se despliega el que estaba mostrandose antes de hacer la busqueda. Por ultimo muestro otro pantallazo de una busqueda por Sexo:

Buscando alumnos por sexo

Buscando alumnos por sexo

Como decia anteriormente lo interesante es que si ahora deseamos que la tabla alumnos este creada en MySQL o Postgres, entonces la creamos en dicho manejador (con ayuda del script que puse mas arriba; estan los nombres de los campos y su tipo) y en la linea 402 de la clase JfrPrincipal.java, cambiamos los parametros de Conexion (usuario,pass,bd, manejador) de dicho manejador, la clase automaticamente usara el Driver adecuado y se conectara a dicho DBMS sin problemas.

Sin querer se hizo un poco largo este ejemplo, pero no era para mas, espero haber sido lo suficiente explicito y no haber dejado muchas dudas, los ya avanzados en Java supongo que mi codigo lo habran digerido sin problemas y los que empiezan de todas maneras pregunten sin compromiso, les aseguro que yo tambien soy un novato y seguro hay alguna manera mas fina y elegante de hacer esto del recorrido de registros, solo es una idea. . Y es que a la clase GonzaBD.java la simplifique y le quite mucho codigo para que quedara simple y sencilla de entender ya que mi version original tiene muchos mas metodos para realizar las cuatro Operaciones SQL de manera mas simple (INSERT, DELETE, UPDATE, SELECT), pero me reservo el codigo y posiblemente mas adelante lo libere en este mismo blog, por ahora creo que seria demasiado y requeria mas tiempo para explicarlo y estoy muy ocupado estod dias.

Bueno no me queda mas que decir hasta pronto y si a alguien le interesan los fuentes basta con pedirlos y se los envio, hasta pronto y gracias x visitar.

Encriptar Passwords en MD5 en Java

Encriptar Passwords en MD5 en Java. En vista de que e visto muchos comentarios a la entrada de blog Autentificar usuarios en Java, voi a ampliar un poco ese tema con algo extra. Digo esto porque pienso utilizar estos mismos fundamentos para almacenar los passwords encriptados (en MD5) de los usuarios en la BD. Googleando por la red me encontre (al igual que muchos otros) muchas maneras muy similares de encriptar en MD5, algunas un poco equivocadas, algunas con mas cosas que otras, pero la que mas me gusto es la que voi a mostrar a continuacion.

Antes que todo muestro la configuracion de la computadora en la que hice esta prueba:

Tipo de Computadora: Laptop, Toshiba
S.O.: Linux, distribucion Ubuntu 10.10 [Maverick]
version del Kernel: 2.6.35-27
Version de la JVM: 1.6.0_26

La clase siguiente contiene un metodo muy sencillo que recibe una cadena (String) y regresa otra pero encriptada en MD5. Por si no lo sabias, hasta este momento creo que java no cuenta con algun metodo para encriptar en MD5, asi que tenemos que ingeniarnosla de alguna manera para encriptar en este formato. Bueno el codigo es el siguiente para hacer la encriptacion es:
TestEncriptarMD5.java

/**
 *      Instituto Tecnologico de Zacatepec
 * Descripcion:   Encriptacion de paswords en MD5
 * @author Gonzalo Silverio
 * Fecha: 03-12-2011
 * Archivo:  TestEncriptarMD5.java
 */

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class TestEncriptarMD5
{
	private static final char[] CONSTS_HEX = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
  	public static String encriptaEnMD5(String stringAEncriptar)
	{
		try
		{
		   MessageDigest msgd = MessageDigest.getInstance("MD5");
		   byte[] bytes = msgd.digest(stringAEncriptar.getBytes());
		   StringBuilder strbCadenaMD5 = new StringBuilder(2 * bytes.length);
		   for (int i = 0; i < bytes.length; i++)
		   {
		       int bajo = (int)(bytes[i] & 0x0f);
		       int alto = (int)((bytes[i] & 0xf0) >> 4);
		       strbCadenaMD5.append(CONSTS_HEX[alto]);
		       strbCadenaMD5.append(CONSTS_HEX[bajo]);
		   }
		   return strbCadenaMD5.toString();
		} catch (NoSuchAlgorithmException e) {
		   return null;
		}
	}

	public static void main(String args[])
	{
		System.out.println("\n\nEncriptacion en MD5 de 123: '"+encriptaEnMD5("123")+"'");
		System.out.println("Encriptacion en MD5 de hola: '"+encriptaEnMD5("hola")+"'");
	}
}

Como se puede observar el metodo esta super corto y efectivamente se obtiene la cadena encriptada en MD5 y para probarlo a continuacion la compilacion y ejecucion de la clase anterior:

Ejemplo de encriptacion en MD5 en Java

Ejemplo de encriptacion en MD5 en Java

Bueno hasta pronto y ya sabes si gustan el codigo basta con dejar su email.  Suerte!!

Clase java para recorrer registros de tabla SQL Server con botones primero, anterior, siguiente y ultimo

Clase java para recorrer registros de tabla SQL Server con botones primero, anterior, siguiente y ultimo. El objetivo de esta entrada de blog es mostrar una clase diseñada por mi para facilitar la navegacion por los registros de una tabla. Se me ocurrio esto debido a que en muchas ocasiones en los programas necesitamos recorrer los registros de una tabla con los tipicos botones:
Primero Permite ir al primer registro de la tabla.
Anterior Permite ir al anterior registro.
Siguiente Permite ir al siguiente registro.
Ultimo Permite ir al ultimo registro.

La siguiente imagen muestra un ejemplo clasico donde se requieren estos botones (los botones con flechas verdes):

Ventana con botones de navegacion de registros.
Ventana con botones de navegacion de registros.

Como se puede imaginar con ayuda de estos botones nos podemos colocar en cualquier registro de la tabla y una vez posicionados en el registro deseado se pueden usar otros botones para modificar o eliminar el registro. Bueno sin mas preambulos muestro el codigo de la clase:

GonzaBD.java
El truco de esta clase es almacenar en un array todos los campos llave de la tabla que se desee manipular (por cada tabla se debe crear un nuevo objeto de esta clase). Al llamar al metodo primero() con ayuda de una variable se accede al primer elemento del arreglo de llaves primarias. Al llamar al metodo ultimo() con ayuda de una variable se accede al ultimo elemento del arreglo de llaves primarias. Al llamar al metodo siguiente() con ayuda de una variable; si por ejemplo estamos en la fila 5, se accede al elemento 5 +1, del arreglo de llaves primarias. Despues se realiza un Select hacia la tabla y los datos quedan en un Objeto Resultset (llamado rs) que es local a esta clase. Bueno a continuacion muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que contiene metodos para recorrer los registros de una tabla
 *						hacia el primer, anterior, siguiente o ultimo registro
 * Archivo: GonzaBD.java
 * author Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */
import java.sql.*;

public class GonzaBD
{
	String strSentenciaSQL = "";
	String strCadenaConexion = "";
	String strOrdenarPor = "";
	String strCampoLLave = "";
	String strTabla = "";
	String strArrayCamposLlave[];
	int intArrayCamposLlave[];

	//Los posibles tipos del campo llave son cadena y entero
	//Por defecto el campo llave es de tipo cadena
	String strTipoCampoLlave = "cadena";

	int intTotalRegistros = 0,intFilaActual = 0;

	String strDriverMySQL 		="com.mysql.jdbc.Driver";
	String strDriverPostgres 	="org.postgresql.Driver";
	String strDriverSqlServer 	="net.sourceforge.jtds.jdbc.Driver";

	String strManejador 		= "mysql";
	String strBaseDatos 		= "BD";
	String strServidor 		= "localhost";
	String strUsuario 		= "usuario";
	String strPassword		= "password";
	String strControlador 	= strDriverMySQL;
	String strPuerto			= "3306";

	private static Connection con = null;
	Statement st;
	ResultSet rs;

    public GonzaBD()
    {

    }

    //se mueve a la primera fila y devuelve true si se pudo, false sino se pudo ir a la primera fila
    public  boolean  primero()
    {
      try
		{
			intFilaActual = 0;
			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //se mueve a la anterior fila y devuelve true si se pudo, false sino se pudo ir a la anterior fila
    public  boolean  anterior()
    {
      try
		{
			intFilaActual--;
			if(intFilaActual<0)
				intFilaActual=0;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //se mueve a la siguiente fila y devuelve true si se pudo, false sino se pudo ir a la siguiente fila
    public  boolean  siguiente()
    {
      try
		{
			intFilaActual++;
			if(intFilaActual>intTotalRegistros-1)
				intFilaActual=intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //se mueve a la ultima fila y devuelve true si se pudo, false sino se pudo ir a la ultima fila
    public  boolean  ultimo()
    {
      try
		{
			intFilaActual = intTotalRegistros-1;

			if( strTipoCampoLlave.equals("cadena") )
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"='"+strArrayCamposLlave[intFilaActual]+"'");
			else
				rs = ejecutarConsulta("SELECT * FROM " + strTabla + " WHERE "+strCampoLLave+"="+intArrayCamposLlave[intFilaActual]);

			if( rs.next() )
				return true;

			return false;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

	//Obtiene el controlador del manejador mysql o postgres
    public  String obtenerDriverManejador(String manejador)
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
			return strDriverSqlServer;
		else if(manejador.equals("mysql"))							//Si el manejador es mysql
			return strDriverMySQL;
		else if(manejador.equals("postgres"))							//Si el manejador es postgres
			return strDriverPostgres;

			//en caso d k no sea ninguno devuelve el de MySQL
			return strDriverMySQL;
    }

	//Conecta a la BD con los datos por default
    public boolean conectarBD() throws SQLException
    {
      try
		{
			return conectarServidor(strManejador,strServidor,strUsuario,strPassword,strBaseDatos,strControlador);
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

	//Conecta a la BD con los datos especificados
    public boolean conectarBD(String usuario, String password, String BD, String manejador) //throws SQLException
    {
    	boolean ress;
      try
		{
			strControlador = obtenerDriverManejador(manejador);
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			strManejador 	= manejador;
			ress = conectarServidor(manejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

	//Conecta a la BD con los datos del usuario, bd y password especificados, para los demas toma los k estan por default
    public boolean conectarBD(String usuario, String password, String BD )// throws SQLException
    {
    	boolean ress;
      try
		{
			strUsuario 		= usuario;
			strPassword 	= password;
			strBaseDatos 	= BD;
			ress = conectarServidor(strManejador,strServidor,usuario,password,BD,strControlador);
			return ress;
		}
		catch ( SQLException e )
		{
			e.printStackTrace();
			return false;
		}
    }

    //permite especificar el campo por el que se van a ordenar los registros
    public  void ordenarPor(String campo)
    {
    	strOrdenarPor = campo;
    }

	//Realiza una conexion a sqlserver, mysql o postgres con los datos especificados
    public boolean conectarServidor(String manejador,String servidor,String usuario,String pw,String bd, String driver) throws SQLException
    {
		if(manejador.equals("sqlserver"))							//Si el manejador es sql server
		{
		    try
		    {
		        Class.forName(driver);
		        strCadenaConexion = "jdbc:jtds:sqlserver://"+servidor+"/"+bd+";instance=SQLSERVEREXPRESS;";
		        con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		        if (con == null )
		    			return false;
		        return true;
		    }
		    catch(SQLException sqlex)
		    {
		    		sqlex.printStackTrace();
		        	return false;
		    }
		    catch(Exception e)
		    {
		    		e.printStackTrace();
		        	return false;
		    }
		}
    	else if(manejador.equals("mysql"))									//Si el manejador es mysql
    	{
           try
           {
		          Class.forName(driver);
		          strCadenaConexion = "jdbc:mysql://"+servidor+"/"+bd;
		          con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
		          if (con == null )
		          	return false;

		          return true;
            }
            catch(SQLException sqlex)
            {
            	sqlex.printStackTrace();
                return false;
            }
            catch(Exception e)
            {
            	e.printStackTrace();
            	return false;
            }
    	}
    	else if(manejador.equals("postgres"))							//Si el manejador es postgress
      {
          try
          {
              Class.forName(driver);
              strCadenaConexion = "jdbc:postgresql://"+servidor+":5432/"+bd;
              con = DriverManager.getConnection(strCadenaConexion,usuario,pw);
              if (con == null )
          			return false;

              return true;
          }
          catch(SQLException sqlex)
          {

          		sqlex.printStackTrace();
              	return false;
          }
          catch(Exception e)
          {
          	e.printStackTrace();
              return false;
          }
      }

	    	return false;
    }

	//Ejecuta un SELECT y devuelve el Resultset con los resultados
	public ResultSet ejecutarConsulta(String cadSQ) throws SQLException
	{
		rs = null;
		if( ! strOrdenarPor.equals("") )
			cadSQ += " ORDER BY " +strOrdenarPor;

		try
		{
			rs = st.executeQuery(cadSQ);
			return rs;
       }
       catch(SQLException sqlex)
       {
       		sqlex.printStackTrace();
       		return rs;
       }

	}

	public  void obtenerCamposLlave()
	{
		obtenerCamposLlave(strTabla);
	}

	//Si el campo llave es de tipo entero guarda los campos llave en un arreglo de enteros
	//Si el campo llave es de tipo cadena guarda los campos llave en un arreglo de Strings
	public  void obtenerCamposLlave(String tabla)
	{
		int c=0;
		try
		{
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			while(rs.next())
				c++;
			intTotalRegistros = c;
			strArrayCamposLlave = new String[intTotalRegistros];
			intArrayCamposLlave = new int[intTotalRegistros];

			cerrar(rs);		//Cerrar consulta anterior
			//Ejecutar nuevamente la consulta
			rs = ejecutarConsulta("SELECT * FROM " + tabla);
			rs.next();		//Moverse al primer registro

			c=0;
			do
			{			//determina el tipo del campo llave y en base a eso guarda en el array correspondiente
				if( strTipoCampoLlave.equals("cadena") )
					strArrayCamposLlave[c] = rs.getString(strCampoLLave);
				else
					intArrayCamposLlave[c] = rs.getInt(strCampoLLave);

				c++;
			}while( rs.next() );

		}
		catch(SQLException sqlex)
		{
       	sqlex.printStackTrace();
		}

	}

	// Cierra un objeto Resultset
	public static void cerrar(ResultSet rs)
	{
		try
		{
			rs.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// cierra un objeto Statemet
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	// Cierra un objeto Connection
	public static void cerrar(Connection con)
	{
		try
		{
			con.close();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

	//Permite especificar cual es el campo llave de la tabla
	public  void setCampoLlave(String campo)
	{
		strCampoLLave = campo;
	}

	//Permite especificar cual es el campo llave y su tipo, de la tabla
	public  void setCampoLlave(String campo, String tipo)
	{
		strCampoLLave = campo;
		strTipoCampoLlave = tipo;
	}

	public void setTipoCampoLlave(String tipo)
	{
		strTipoCampoLlave = tipo;
	}

	//Especifica la tabla sobre la k se va a trabajar
	public  void setTabla(String tabla)
	{
		try
		{
			strTabla = tabla;
			st=con.createStatement();
		}
		catch(SQLException ex)
		{
			ex.printStackTrace();
		}

	}
}	//Fin de la clase

Como se puede observar en la linea 229 de la clase GonzaBD.java estoy usando un nombre de instancia llamado SQLSERVEREXPRESS Esta clase se podria editar para recibir tambien como parametro el nombre de la instancia de SQL Server que se desee utilizar, se queda de tarea.

Lo interesante de esta clase es que esta preparada para recorrrer los registros de tablas que esten creadas en cualquera de los manejadores SQL Server, MySQL o de Postgres, obviamente que los .jar de los JConnector de dichos DBMS  deben estar copiados en C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext, Lo que esta en negrita lo e resaltado debido a que la version del JVM puede cambiar segun la que tengas instalada. Los JConnector que e usado para probar esta clase son los siguientes (puedes dar click en el enlace para descargarlo sino lo tienes).
JConnector de SQL Server: jtds-1.2.5.jar
JConnector de Postgres: postgresql-9.1-901.jdbc4.jar
JConnector de MySQL: mysql-connector-java-5.1.18-bin.jar

Para ejemplificar el uso de la clase anterior e usado una tabla que esta en SQL Server. Los parametros de conexion son:
Manejador de Base de datos (DBMS): SQL Server 2005 Express
Base de datos: prueba
Tabla: alumnos
Usuario: sa
Password: root

El Script para crear la tabla alumnos en SQL Server es el siguiente:

create table alumnos(matricula int, nombre char(50), apellidos char(100), edad int, peso decimal(10,2),sexo char(1), PRIMARY KEY(matricula) );

La imagen de la tabla ya creada en SQL Server se ve asi:

Tabla alumnos en SQL Server

Tabla alumnos en SQL Server

DIAGRAMA UML DE LA CLASE gonzaBD

Diagrama UML de la clase gonzaBD

Diagrama UML de la clase gonzaBD

BREVE EXPLICACION DE LOS ATRIBUTOS DE LA CLASE gonzaBD:

Atributo Descripcion
intfilaActual Contiene un número que se usa como índice para acceder a una llave primaria dentro del arreglo strArrayCamposLlave o el arreglo strArrayCamposLlave (dependiendo de si la llave primaria es de tipo cadena o tipo entero, respectivamente). Este atributo contiene el número actual de fila-1.
strArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Cadena.
intArrayCamposLlave[] Arreglo que contiene las llaves primarias de la tabla en caso de que el tipo de dato del campo llave sea Entero.
rs Contiene los datos de la fila actual mostrandose. Cada vez que se manda a llamar al método primero(), anterior(), siguiente() o ultimo() se realiza una consulta y este atributo (tipo Resultset) se actualiza con los campos de la nueva fila.

COMO SE USA LA CLASE gonzaBD
A continuacion voi a poner un fragmento de codigo con la intencion mostrar los pasos a realizar para usar correctamente la clase.

//Crear un objeto de esta clase
GonzaBD a = new GonzaBD();
//AHORA SE DEBE REALIZAR LO SIGUIENTE EN EL MISMO ORDEN…
//Primeramente se debe indicar especificar cual es la llave primaria de la tabla y su tipo
a.setCampoLlave("matricula","entero");
//Se de desea se puede indicar que si se desean ordenar los registros de la tabla por un campo, //este paso es opcional en todo caso sino se realiza, no se ordenan por ningún campo
a.ordenarPor("nombre");
//A continuación usamos un metodo sobrecargado para conectarse al DBMS, aquí es donde //indicamos a que manejador se debe accesar
a.conectarBD("sa","root","prueba","sqlserver");
//Una vez que ya estamos conectados se debe especificar la tabla que se va a manipular
a.setTabla("alumnos");
//Ahora se manda a llamar al método que rellena el arreglo de llaves primarias dentro de la clase; //dependiendo del tipo de dato del campo llave se rellena el arreglo de Strings o el arreglo de //enteros.
a.obtenerCamposLlave();
//Ahora ya se puede llamar a cualquiera de los métodos primero(), anterior(), siguiente() o ultimo()... 

Despues de realizar lo anterior, para que el objeto rs se rellene con los datos de la primera fila se invoca al metodo:
a.primero();
Después de que se invoco ese metodo, el atributo rs de la clase gonzaBD se quedara con los datos de la fila 1. Supongamos que la tabla “alumnos” contiene las siguientes filas, rs apuntara a la fila:

El atributo rs esta en la posicion de la primera fila.

El atributo rs esta en la posicion de la primera fila.

Si inmediatamente despues se llama al método siguiente()
a.siguiente();
El atributo rs apuntara al siguiente registro despues del primero, es decir rs apuntara a la fila:

El atributo rs apunta a los datos de la segunda fila

El atributo rs apunta a los datos de la segunda fila

Y asi sucesivamente, una observación: si te fijas en el codigo de los metodos (siguiente() y anterior()) cuando se ha llegado a la ultima fila, es decir, si rs apunta al registro 4 y se ejecuta una llamada al método siguiente() (se intenta accesar una fila después de la ultima); dicho método contiene un ‘candado’ para detectar eso y siempre dejara a rs apuntando al ultimo registro. El método anterior() igualmente tiene esa precaucion y siempre que se intente accesar a un registro antes del primero automáticamente moverá a rs para que apunte a la primera fila. De esta manera no es posible sobrepasar los limites (inferior ni superior) de filas de la tabla que se este manipulando.

Finalmente Para ilustrar el uso de la clase gonzaBD anterior he creado una ventana muy basica.

JfrPrincipal.java
Esta clase crea una ventana de formulario con 6 campos y los 4 botones; primero, anterior, siguiente y ultimo en la parte inferior de dicha ventana. Es la misma clase que utilice para ilustrar como usar ventanas de formulario en Java, pero la he modificado y adaptado para este ejemplo mas elaborado. Bueno ahora muestro el codigo:

/*
 *   Instituto Tecnologico de Zacatepec
 * Descripcion:  Clase que crea una GUI para ilustrar el uso de la clase EasyBD
 * Archivo: JfrPrincipal.java
 * author: Gonzalo Silverio       gonzasilve@hotmail.com
 * fuente:  https://gonzasilve.wordpress.com
 */

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

//Se usara para cambiar los Margenes de los botones
import java.awt.Insets;

//Para Manejo de BD
import java.sql.*;

public class JfrPrincipal extends JFrame
{
	//Campos de texto y sus etiquetas 
	JLabel jlbMatricula;    JTextField  jtfMatricula;
	JLabel jlbNombre;       JTextField  jtfNombre;
	JLabel jlbApellidos;    JTextField  jtfApellidos;
	JLabel jlbEdad;         JTextField  jtfEdad;
	JLabel jlbPeso;         JTextField  jtfPeso;
	JLabel jlbSexo;         JComboBox   jcbSexo;
	
	//Botones de navegacion de los registros
	JButton btnPrimero;
	JButton btnAnterior;
	JButton btnSiguiente;
	JButton btnUltimo;
	
	Box boxVCamposVentana;   //Contiene todo los campos de texto (con su respectiva etiqueta)
	JPanel panBotones;      //Contiene los botones Guardary Cancelar
	
	//Objeto de la clase que nos ayuda a navegar por los registros de la tabla
	GonzaBD bd = new GonzaBD();
	
	JfrPrincipal(String strTitulo, int intAncho, int intAlto)
	{
		super(strTitulo);
		this.setSize(intAncho, intAlto);
		this.setResizable(false);		//Ventana no redimensionable
		this.setLocationRelativeTo(null);       //Centrar ventana en pantalla
		
		//Box vertical por que los botones van a estar abajo
		Box boxVContenidoVerticalVentana = Box.createVerticalBox();
		crearCamposVentana();
		crearBotones();
		//Espacio del borde superior de la ventana al primer Campo
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(30));
		boxVContenidoVerticalVentana.add(boxVCamposVentana);
		//Espacio entre el ultimo campo (sexo) y los botones Guardar y Cancelar
		boxVContenidoVerticalVentana.add(Box.createVerticalStrut(20));
		boxVContenidoVerticalVentana.add(panBotones);
		
		this.add(boxVContenidoVerticalVentana);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  
	  //Conecta la Base de datos
		conectarBD();
		bd.primero();		//Posicionarse en el primer registro
		rellenarCampos();		//Rellenar los campos con los datos del primer registro
		
		//ASIGNAR UN ESCUCHADOR PARA CADA BOTON DE NAVEGACION
		//Boton Primero
		btnPrimero.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.primero();
				rellenarCampos();
			}
		});
		//Boton Anterior
		btnAnterior.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.anterior();
				rellenarCampos();
			}
		});
		//Boton Siguiente
		btnSiguiente.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.siguiente();
				rellenarCampos();
			}
		});
		//Boton Ultimo
		btnUltimo.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent evt) 
			{
				bd.ultimo();
				rellenarCampos();
			}
		});
		  	
        	
	}		//Fin del constructor

	//Crea los campos de la ventana (cada caja tiene su correspondiente etiqueta)
    private void crearCamposVentana()
    {
        Box boxHMatricula =  Box.createHorizontalBox();        
        jlbMatricula = new JLabel("Matricula ");   jtfMatricula = new JTextField(15);
        boxHMatricula.add(Box.createHorizontalStrut(20));
        boxHMatricula.add(jlbMatricula);
        boxHMatricula.add(Box.createHorizontalStrut(14));
        boxHMatricula.add(jtfMatricula);
        JPanel panMatricula =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panMatricula.add(boxHMatricula);

        Box boxHNombre =  Box.createHorizontalBox();
        jlbNombre = new JLabel("Nombre ");   jtfNombre = new JTextField(15);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jlbNombre);
        boxHNombre.add(Box.createHorizontalStrut(20));
        boxHNombre.add(jtfNombre);
        JPanel panNombre =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panNombre.add(boxHNombre);

        Box boxHApellidos =  Box.createHorizontalBox();
        jlbApellidos = new JLabel("Apellidos ");   jtfApellidos = new JTextField(15);
        boxHApellidos.add(Box.createHorizontalStrut(20));
        boxHApellidos.add(jlbApellidos);
        boxHApellidos.add(Box.createHorizontalStrut(11));
        boxHApellidos.add(jtfApellidos);
        JPanel panApellidos =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panApellidos.add(boxHApellidos);

        Box boxHEdad =  Box.createHorizontalBox();
        jlbEdad = new JLabel("Edad ");   jtfEdad = new JTextField(15);
        boxHEdad.add(Box.createHorizontalStrut(20));
        boxHEdad.add(jlbEdad);
        boxHEdad.add(Box.createHorizontalStrut(40));
        boxHEdad.add(jtfEdad);
        JPanel panEdad =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panEdad.add(boxHEdad);
        
        Box boxHPeso =  Box.createHorizontalBox();
        jlbPeso = new JLabel("Peso ");   jtfPeso = new JTextField(15);
        boxHPeso.add(Box.createHorizontalStrut(20));
        boxHPeso.add(jlbPeso);
        boxHPeso.add(Box.createHorizontalStrut(40));
        boxHPeso.add(jtfPeso);
        JPanel panPeso =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panPeso.add(boxHPeso);

        Box boxHSexo =  Box.createHorizontalBox();
        jlbSexo = new JLabel("Sexo ");   jcbSexo = new JComboBox();
        jcbSexo.addItem("Masculino");
        jcbSexo.addItem("Femenino");
        boxHSexo.add(Box.createHorizontalStrut(20));
        boxHSexo.add(jlbSexo);
        boxHSexo.add(Box.createHorizontalStrut(40));
        boxHSexo.add(jcbSexo);
        JPanel panSexo =  new JPanel(new FlowLayout(FlowLayout.LEFT) );
        panSexo.add(boxHSexo);

        boxVCamposVentana = Box.createVerticalBox();
        boxVCamposVentana.add(panMatricula);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panNombre);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panApellidos);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panEdad);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panPeso);
        boxVCamposVentana.add(Box.createVerticalStrut(10));
        boxVCamposVentana.add(panSexo);
    }

    private void crearBotones()
    {
        Box boxHBotones = Box.createHorizontalBox();
        
        btnPrimero = new JButton("|< Primero");
        btnAnterior = new JButton("< Anterior");
        btnSiguiente = new JButton("Siguiente >");
        btnUltimo = new JButton("Ultimo >|");
        //Cambiar los margenes de los botones
        			//Insets(margen_sup, margen_izq, margen_inf, margen_der)
        btnPrimero.setMargin(new Insets(0, 2, 0, 2));
        btnAnterior.setMargin(new Insets(0, 2, 0, 2));
        btnSiguiente.setMargin(new Insets(0, 2, 0, 2));
        btnUltimo.setMargin(new Insets(0, 2, 0, 2));
        
        boxHBotones.add(btnPrimero);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnAnterior);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnSiguiente);
        boxHBotones.add(Box.createHorizontalStrut(20));
        boxHBotones.add(btnUltimo);
        
        panBotones =  new JPanel(new FlowLayout(FlowLayout.CENTER) );
        panBotones.add(boxHBotones);
    }
	//Conecta con la BD y devuelve true si se conecto correctamente
	//false en cualquiero otro caso
	public boolean conectarBD()
	{
		// Especificar cual es la llave primaria de la tabla y su tipo
		bd.setCampoLlave("matricula","entero");
    	bd.ordenarPor("nombre");	//Ordena los registros de la tabla por este campo
		
		//Conecta con el usuario, pass, BD y dbms (manejador) especificados
		bd.conectarBD("sa","root","prueba","sqlserver");
		
    	//especifica la tabla sobre la que se va a manipular
    	bd.setTabla("alumnos");
    	//Dentro del objeto bd rellena un arreglo con las llaves 
    	//primarias de la tabla que se esta manipulando
		bd.obtenerCamposLlave();
		
		return true;
	}
	
	//Rellena los campos de texto con los datos del registro actual
    public void rellenarCampos()
    {
		try
		{
    		jtfMatricula.setText(aCadena(bd.rs.getInt("matricula")));
    		jtfNombre.setText(bd.rs.getString("nombre").trim ());
    		jtfApellidos.setText(bd.rs.getString("apellidos").trim ());
    		jtfEdad.setText(aCadena(bd.rs.getInt("edad")));
    		jtfPeso.setText(aCadena(bd.rs.getFloat("peso")));
    		jcbSexo.setSelectedItem( bd.rs.getString("sexo").equals("f") ? "Femenino" : "Masculino" );
    		
    		this.setTitle("Alumno "+(bd.intFilaActual+1)+" de "+bd.intTotalRegistros);
		}
		catch( SQLException ex )
		{
			ex.printStackTrace();
		}
    }
    
    //Recibe un numero entero y lo devuelve como Cadena (String)
    private String aCadena(int num)
    {
    	return String.valueOf(num);
    }
    
    //Recibe un numero decimal y lo devuelve como Cadena (String)
    private String aCadena(float num)
    {
    	return String.valueOf(num);
    }
    
    private void mostrar()
    {
        this.setVisible(true);
    }

    public static void main(String args[])
    {
        JfrPrincipal prueba1 = new JfrPrincipal("Recorrer registros de SQL Server en Java",400,400);
        prueba1.mostrar();
    }
}

Y aqui una imagen de la ejecucion:

Ejecucion de la clase que recorre registros de tabla de SQL Server.

Ejecucion de la clase que recorre registros de tabla de SQL Server.

Como decia anteriormente lo interesante es que si ahora deseamos que la tabla alumnos este creada en MySQL o Postgres, entonces la creamos en dicho manejador (con ayuda del script que puse mas arriba) y en la linea 216 de la clase JfrPrincipal.java, cambiamos los parametros de Conexion (usuario,pass,bd, manejador) de dicho manejador, la clase automaticamente usara el Driver adecuado y se conectara a dicho DBMS sin problemas.

Sin querer se hizo un poco largo este ejemplo, pero no era para mas, espero haber sido lo suficiente explicito y no haber dejado muchas dudas, los ya avanzados en Java supongo que mi codigo lo habran digerido sin problemas y los que empiezan de todas maneras pregunten sin compromiso, les aseguro que yo tambien soy un novato y seguro hay alguna manera mas fina y elegante de hacer esto del recorrido de registros, solo es una idea. . Y es que a la clase GonzaBD.java la simplifique y le quite mucho codigo para que quedara simple y sencilla de entender ya que mi version original tiene muchos mas metodos para realizar las cuatro Operaciones SQL de manera mas simple (INSERT, DELETE, UPDATE, SELECT), pero me reservo el codigo y posiblemente mas adelante lo libere en este mismo blog, por ahora creo que seria demasiado y requeria mas tiempo para explicarlo y estoy en el fin de mi ultimo semestre de la carrera!!! poryectos por aqui, proyectos por allaa.

Bueno no me queda mas que decir hasta pronto y si a alguien le interesan los fuentes basta con pedirlos y se los envio, hasta pronto y gracias x visitar.

Validar numero decimal en java

Ha veces es necesario validar si una cadena es decimal o no, por ejemplo cuando el usuario de un programa debe introducir un precio, o el peso de un producto, etc.  El metodo que muestro a continuacion valida si una cadena que le llega es un numero decimal devolviendo true en caso de que si y false en caso de que no.


//Devuelve true si la cadena que llega es un numero decimal, false en caso contrario
 public boolean esDecimal(String cad)
 {
 try
 {
   Double.parseDouble(cad);
   return true;
 }
 catch(NumberFormatException nfe)
 {
   return false;
 }
 }

Basicamente lo que hace este metodo es  intentar convertir la cadena que llega a Decimal con el metodo parseDouble() de la clase Double (este metodo devuelve un dato de tipo double de la cadena que se le pasa como argumento) , si la conversion se puede realiza entonces el metodo devuelve true indicando que si es un numero decimal; por el contrario  si la cadena que se intenta convertir a decimal no tiene la sintaxis correcta de un numero decimal, es decir,  esta linea:

Double.parseDouble(cad);

lanza un excepcion del tipo NumberFormatException,  entonces el metodo se va al catch y devuelve false para indicar que no es un numero decimal. Por otro lado podemos ver que incluso si a la cadena  le llega un entero, por ejemplo:  “544” el metodo devuelve true ( metodo parseDouble devolveria 544.0) , si nos ponemos estrictos podemos ver que 544 no es un numero decimal, ES UN NUMERO ENTERO.  Entonces podemos ver que el metodo realmente lo que hace es verificar si la cadena se puede convertir a decimal, por lo tanto se deberia llamar algo asi como: esConvertibleADecimal(). Otra forma de comprobar si la cadena es un decimal es analizar caracter por caracter para detectar todos los casos en que la cadena pudiera tener un error de sintaxis. El metodo que muestro a continuacion realmente es la implementacion de un automata:


/*
 Descripcion:
 Contiene un metodo que Valida si una cadena es un numero decimal. Se da por hecho que a la
 cadena se le han eliminado posibles espacios al principio y al final
 Author: gonzasilve@gmail.com
 Fecha:  08/12/2009
 archivo CadenaDecimal.java
*/

public class CadenaDecimal
{
 //Devuelve true si la cadena que llega tiene la sintaxis de un decimal
 public boolean esDecimal(String cad)
 {
 boolean hayPunto=false;
 StringBuffer parteEntera = new StringBuffer();
 StringBuffer parteDecimal = new StringBuffer();
 int i=0, posicionDelPunto;

 for( i=0;i<cad.length(); i++ )
 if ( cad.charAt(i) == '.')                          //Detectar si hay un punto decimal en la cadena
 hayPunto=true;
 if(hayPunto)                                            //Si hay punto guardar la posicion donde se encuentra el carater punto
 posicionDelPunto=cad.indexOf('.');                  //(si la cadena tiene varios puntos, detecta donde esta el primero).
 else
 return false;                                       //Si no hay punto; no es decimal

 if( posicionDelPunto == cad.length()-1 || posicionDelPunto== 0)    //Si el punto esta al final o al principio no es un decimal
 return false;

 for( i=0;i<posicionDelPunto; i++ )
 parteEntera.append(cad.charAt(i)) ;                 //Guardar la parte entera en una variable

 for(i = 0; i<parteEntera.length(); i++)
 if( ! Character.isDigit(parteEntera.charAt(i)) )    //Si alguno de los caracteres de la parte entera no son digitos no es decimal
 return false;

 for( i=posicionDelPunto+1;i<cad.length(); i++ )
 parteDecimal.append(cad.charAt(i));                 //Guardar la parte decimal en una variable

 for(i = 0; i<parteDecimal.length(); i++)
 if( ! Character.isDigit(parteDecimal.charAt(i)) )   //Si alguno de los caracteres de la parte decimal no es un digito no es decimal
 return false;                                   //Incluye el caso en el que la cadena tenga dos o mas puntos

 return true;                                            //Si paso todas las pruebas anteriores, la cadena es un Numero decimal
 }

    public static void main(String args[])
    {
      CadenaDecimal prueba1 = new CadenaDecimal();
      //Devuelve true
      System.out.println("Cadena \"324.40\" es decimal: "+prueba1.esDecimal("324.40"));
      //Devuelve false
      System.out.println("Cadena \"324.6a\" es decimal: "+prueba1.esDecimal("324.6a"));
      //Devuelve false
      System.out.println("Cadena \"3a4.00\" es decimal: "+prueba1.esDecimal("3a4.00"));
      //Devuelve false
      System.out.println("Cadena \"3a4\" es decimal: "+prueba1.esDecimal("3a4"));
      //Devuelve false, es un entero
      System.out.println("Cadena \"656\" es decimal: "+prueba1.esDecimal("656"));
    }
}

Este metodo es mas estricto y no acepta el “544”, devuelve false pues 544 no es un decimal, ES UN ENTERO. A continuacion muestro una imagen de la compilacion y ejecucion de este metodo:

A continuacion explico un poco el codigo, esta parte:

 for( i=0;i<cad.length(); i++ )
 if ( cad.charAt(i) == '.')                          //Detectar si hay un punto decimal en la cadena
 hayPunto=true;

Detecta si hay un punto dentro de la cadena, las cadenas “23.213” , “4g21.12”, “.232” , “dwe.23”, “434.” , “465..2ew”, “.45dsd34”, “87.232…” pondrian la variable hayPunto en true, pues todas estas cadenas tienen un punto.

despues el siguiente codigo:

 if(hayPunto)                                            //Si hay punto guardar la posicion donde se encuentra el carater punto
 posicionDelPunto=cad.indexOf('.');                  //(si la cadena tiene varios puntos, detecta donde esta el primero).
 else
 return false;                                       //Si no hay punto; no es decimal

verifica si hay un punto se recoge la posicion (el indice) en donde esta esta ese punto dentro de la cadena. Si no hay punto entonces se devuelve false para indicar que la cadena no es un decimal, pues todos los numeros decimales tienen un punto decimal ¿ o no?.

despues el siguiente codigo:

 if( posicionDelPunto == cad.length()-1 || posicionDelPunto== 0)    //Si el punto esta al final o al principio no es un decimal
 return false;

verifica si el punto esta al final o (||) si el punto esta al principio devuelve false, pues los numeros decimales no tiene el punto decimal al principio, en este caso somos muy estrictos y no se aceptan cadenas como “.547” (lleva implicito un cero como parte entera), el metodo devolveria false, por que no se acepta que el usuario piense que el sistema le va a colocar el cero como parte entera. Todo lo demas ya esta explicado en el codigo, asi que ya no lo explico mucho.

Lo siguiente es comprobar si la parte entera (los caracteres que estan antes del punto) todos son digitos enteros, si alguno no lo es entonces devolver false para indicar que no es un decimal, “67sa5.76” no es un decimal ¿o si?.

 for( i=0;i<posicionDelPunto; i++ )
 parteEntera.append(cad.charAt(i)) ;                 //Guardar la parte entera en una variable

 for(i = 0; i<parteEntera.length(); i++)
 if( ! Character.isDigit(parteEntera.charAt(i)) )    //Si alguno de los caracteres de la parte entera no son digitos no es decimal
 return false;

El codigo anterior es el mismo que se uso en la implementacion del metodo para validar numero entero.

Lo siguiente es comprobar si la parte decimal (los caracteres que estan despues del punto) todos son digitos enteros, si alguno no lo es entonces devolver false para indicar que no es un decimal, “6757.8766”, “6757..8766” no son decimales ¿o si?.


 for( i=posicionDelPunto+1;i<cad.length(); i++ )
 parteDecimal.append(cad.charAt(i));                 //Guardar la parte decimal en una variable

 for(i = 0; i<parteDecimal.length(); i++)
 if( ! Character.isDigit(parteDecimal.charAt(i)) )   //Si alguno de los caracteres de la parte decimal no es un digito no es decimal
 return false;                                   //Incluye el caso en el que la cadena tenga dos o mas puntos

por ultimo se devuelve un true si la cadena pudo pasar por toda las serie de pruebas anteriores. SI las paso es por que la cadena tiene toda la sintaxis de un numero decimal correctamente escrito.

 return true;        //Si paso todas las pruebas anteriores, la cadena es un Numero decimal

… hasta pronto.
}

Validar Numero entero en java

Ha veces es necesario comprobar si cierta cadena es un numero o no. Por ejemplo cuando deseamos guardar un dato numerico en una base de datos (campos edad, cantidad, etc), antes de enviarlos a la BD se deben validar para para que el DBMS no nos devuelva error.

El siguiente codigo muestra como validar si en una cadena que llega todos son numeros. Se supone de antemano que a la cadena se le han eliminado espacios al principio y al final.


/*
 Descripcion:
 Contiene un metodo que Valida si una cadena es un numero entero.
 author: gonzasilve@gmail.com
 fecha:  06/12/2009
 archivo CadenaEnteros.java
*/

public class CadenaEnteros
{
 //Devuelve true si en una cadena que llega todos son numeros, false en caso contrario
 public boolean esEntero(String cad)
 {
 for(int i = 0; i<cad.length(); i++)
 if( !Character.isDigit(cad.charAt(i)) )
 return false;

 return true;
 }

 public static void main(String args[])
 {
 CadenaEnteros cadena1 = new CadenaEnteros();
 //Probar con un numero entero valido:   Devuelve true
 System.out.println("\"3432465\" es entero: " + cadena1.esEntero("3432465"));
 //Probar con una cadena invalida:   Devuelve false
 System.out.println("\"34hola\" es entero: " + cadena1.esEntero("34hola"));
 //Probar con una cadena invalida:   Devuelve false
 System.out.println("\"23.5\" es entero: " + cadena1.esEntero("23.5"));
 }
}

Basicamente el metodo recorre la cadena caracter por caracter y comprueba si NO es un digito, si alguno no lo es, devuelve false. Si ninguno fue false llegara la instruccion return true y terminara el metodo.
Ojo, este metodo solo valida NUMERO ENTEROS, los numeros flotantes (con punto decimal) se deben validar con otro metodo. Si se intenta validar un numero flotante con este metodo siempre devolvera false (pues el caracter punto ( . ) no es un digito).

Enseguida se muestra una imagen de la compilacion y ejecucion de la prueba de este metodo en mi sistema Ubuntu.

Aunque la implementacion de esto se puede hacer de muchas formas aqui muestro la manera como se me ocurrio a mi. Es muy util por ejemplo para validar las cadenas introducidas en campos JTextField en una GUI que tenga campos en donde el usuario deba escribir un dato entero.

Espero que le sirva a alguien, hasta pronto.

}

Validar cadena vacia en java

Ha veces es necesario comprobar si una cadena que introduce el usuario es una cadena vacia (o simplemente no escribio nada). Por ejemplo cuando se le solicita al usuario su nombre en un JTextField y el usuario no quiere escribirlo y simplemente escribe uno o varios espacios para intentar engañar al sistema y presiona <enter> o el boton de procesar.

El metodo Java que muestro a continuacion espera recibir una cadena y devuelve true si todos los caracteres son espacio.


/*
 Descripcion:
 Contiene un metodo que Valida si una cadena todos son espacios.
 author: gonzasilve@gmail.com
 fecha:  06/12/2009
 archivo Cadenaespacios.java
*/

public class CadenaEspacios
{
 //Devuelve true si en una cadena que llega todos son espacios, false en caso contrario
 public boolean sonEspacios(String cad)
 {
 for(int i =0; i<cad.length(); i++)
 if(cad.charAt(i) != ' ')
 return false;

 return true;
 }

 public static void main(String args[])
 {
 CadenaEspacios cadena1 = new CadenaEspacios();
 //Devuelve true
 System.out.println("Cadena \"       \" Son espacios: " + cadena1.sonEspacios("        "));
 //Devuelve false
 System.out.println("Cadena \" hola7   \" Son espacios: " + cadena1.sonEspacios(" hola7   "));
 //Devuelve false
 System.out.println("Cadena \"756   \" Son espacios: " + cadena1.sonEspacios("756   "));
 }
}

Como se puede ver el metodo simplemente toma caracter por caracter y lo compara si no es igual al caracter ‘ ‘ (espacio) si  alguno no es espacio (se cumple la condicion if) devuelve false; lo que significa  que en la cadena NO todos los caracteres son espacios. Si el if no se cumple ninguna vez, se ejecuta la instruccion return true; lo que significa que todos los caracteres de la cadena son espacios.

A continuacion muestro una imagen de la compilacion y ejecucion de la prueba de este metodo en mi S.O. Ubuntu.

Algunos pueden pensar que es mas facil escribir un codigo como:


if( cadena.equals(" ") )

Pero en ese caso se esta comparando toda la cadena con un solo espacio, pero eso va a devolver true solo si la cadena tiene un solo espacio, pero (otro pero mas) ¿y si la cadena son varios espacios?, en ese caso el if anterior no se cumpliria (un espacio es diferente de varios espacios).

bueno por otra parte debo decir que el if del metodo SonEspacios() , este if:


 if(cad.charAt(i) != ' ')

se puede reemplazar por este otro:


 if( ! Character.isWhiteSpace( cad.charAt(i) ) )

Espero que alguien le sirva esta cosa, me despido, hasta pronto.

}


if( cadena.equals(" ") )

A %d blogueros les gusta esto: