viernes, 4 de diciembre de 2009

Java Reflection

En un momento se me dio la necesidad de invocar los métodos getter y setter de una clase dinámicamente, y al googlear me encontré con la API de reflection de Java junto al ejemplo que aparece en esta página

Con esto logre invocar los métodos getter y setter sin necesidad de invocarlos explícitamente ( instancia.getValor ), para lo cual hice el siguiente ejemplo.


primero una clase donde tenemos el origen de los datos



PersonaOrigen.java


public class PersonaOrigen {

private String nombre;
private String apellido;
private String edad;

public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getEdad() {
return edad;
}
public void setEdad(String edad) {
this.edad = edad;
}


}




una clase donde volvaremos los datos.


Persona.java


public class Persona {

private String nombre;
private String apellido;
private String edad;

public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getEdad() {
return edad;
}
public void setEdad(String edad) {
this.edad = edad;
}


}



Y tenemos la clase que realiza la operacion.


Prueba.java
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;





public class Prueba {





public static void main(String[] args) {



/*

* La clase PersonaOrigen Representara la fuente de los datos

*/

PersonaOrigen po = new PersonaOrigen();

po.setNombre("Juan");

po.setApellido("Perez");

po.setEdad("18");



/*

* por simplicidad, en este caso supondremos que los

* campos que vienen de la fuente de datos son conocidos

* por lo cual los guardaremos en un ArrayList

* (Cuando lo implemente los obtenia de base de datos)

*/

ArrayList<String> campos = new ArrayList<String>();

campos.add("nombre");

campos.add("apellido");

campos.add("edad");





HashMap metodos;

try{

metodos = new HashMap();

Persona persona = new Persona();

        Field[] fields = persona.getClass().getDeclaredFields();



        /*

         * recorro la clase y almaceno los atributos en un hashmap

         * esto se podria evitar, y grabar directamente los datos.

         */

        for( int zz = 0;  zz < fields.length ; zz++ ){

            metodos.put(fields[zz].getName(), fields[zz]);

        }

        

        //recorremos los campos

        Iterator i = campos.iterator();

        String nombreCampo = null;

        while(i.hasNext()){

        

         //rescato el nombre del campo

         nombreCampo = (String) i.next();

        

         //genero el string que contiene el nombre de los metodos getter y settet de cada campo

String setterName = "set" + String.valueOf(nombreCampo.charAt(0)).toUpperCase() + nombreCampo.substring(1);

String getterName = "get" + String.valueOf(nombreCampo.charAt(0)).toUpperCase() + nombreCampo.substring(1);



//rescato el valor de la fuente de origen de los datos

                Method getter = po.getClass().getMethod(getterName);

                Object valor = getter.invoke(po, new Object[0]);



                //seteo el valor en la instancia de la clase Persona

Field field2= (Field) metodos.get(nombreCampo);

Method setter = persona.getClass().getMethod(setterName, field2.getType());

setter.invoke(persona, new Object[]{( valor ) });         

        

        }



        /*

         * Finalmente podemos ver volcados los datos de PersonaOrigen a persona

         */

        System.out.println("Nombre:" + persona.getNombre());

        System.out.println("Nombre:" + persona.getApellido());

        System.out.println("Nombre:" + persona.getEdad());

        



}

catch (Exception e) {

;

}





}



}



martes, 27 de octubre de 2009

Como usar Log4j

A continuación expondré como hacer funcionar Log4J, no expongo que sea la mejor manera de hacerlo, simplemente es como me funciono bien (Bajo tomcat 5.5) .

Como primera acción debemos incluir la librería (jar) de Log4j en nuestro proyecto

Generamos el Servlet Log4JInit que nos permitira acceder de mojor forma a la ruta del contexto.


Log4jInit.java

package cl.ruta.package;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.PropertyConfigurator;

/**
* Servlet implementation class for Servlet: Log4jInit
*
* Servlet que permite obtener la ruta del contexto de la aplicacion, con el fin
* de poder setear la ruta para la generacion del LOG del Sistema log4j.
*
*/
public class Log4jInit extends javax.servlet.http.HttpServlet implements
javax.servlet.Servlet {
static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

}

/**
* Inicializacion de LOG4J en base a lo descrito en {@link log4j.properties}
*/
public void init() throws ServletException {

Properties prop = new Properties();
FileInputStream is = null;

/*
* Obtengo el contexto de la apliación
*/
String prefix = getServletContext().getRealPath("/");

/*
* Cargo desde el web.xml la ruta en donde se encontrara el archivo
* properties
*/
String file = getInitParameter("log4j-init-file");

try {
/*
* Abre el fichero y carga el properties
*/
is = new FileInputStream(prefix + file);
prop.load(is);
} catch (IOException ioe) {
ioe.printStackTrace();
}

FileOutputStream out = null;
/*
* Se guarda la modificacion y se carga para log4j
*/
try {

out = new FileOutputStream(prefix + file);
prop.store(out, "---No Comment---");
out.close();

} catch (IOException ioe) {
ioe.printStackTrace();
}

/*
* Setea para el log4j el properties modificado
*/
if (file != null) {
PropertyConfigurator.configure(prefix + file);
}

}
}





El Servler debe ser agregado al archivo web.xml


<servlet>
<servlet-name>Log4jInit</servlet-name>
<servlet-class>cl.ruta.package.Log4jInit</servlet-class>
<init-param>
<param-name>log4j-init-file</param-name>
<param-value>WEB-INF/classes/log4j.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>



luego agregamos el log4j.properties (Donde quedo definido en el param del web.xml) en mi caso quedo en "
WEB-INF/classes/log4j.properties"



# ***** Tipos de salida que tendra el LOG.
log4j.rootLogger=debug,R

# Configuración Registro en archivo
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${catalina.home}/webapps/[contexto]/WEB-INF/log/[archivo_log].log
log4j.appender.R.MaxFileSize=250KB
log4j.appender.R.MaxBackupIndex=20
# ***** Encoding de salida
log4j.appender.R.Encoding=UTF-8
# ***** Patternlayout indica el tipo de formato usado
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{dd-MMM-yyyy HH:mm:ss}] %p %m%n



por ultimo lo agregamos en las clases java.



import org.apache.log4j.Logger;

/* Dentro de la clase*/
private Logger log = Logger.getLogger(this.getClass());
private String clase = this.getClass().getName().toString();

/*donde se quiere imprimir el mensaje*/
log.debug(clase +"::mensaje:" );

/*Si es dentro de un exception*/
catch (Exception e) {
log.debug(clase +"::Exception::", e);
}





sábado, 25 de julio de 2009

Navegador BOLT pata BlackBerry

Buscando como poder navegar en hattrick desde un blackberry me recomendaron el el navegador BOLT

se ven bastante bien las páginas web.

domingo, 28 de junio de 2009

Arroz para suchi.

Para hacer el arroz para el suchi al menos mi receta es:

para una taza de arroz (de preferencia arroz grano corto) .
  • Lavar bien el arroz.
  • Poner 2 tazas de agua en una olla mediana (según lo que he escuchado mientras más grande la olla mejor queda el arroz obviamente sin exagerar)
  • Prender la cocina llama baja o alta con tostador.
  • Echar el arroz con cuidado y en forma uniforme en la olla.
  • Tapar la olla y esperar hasta que se cocine bien.
En lo personal para ver si está listo uso un palito chino que lo inserto hasta el fondo de la olla y si sale mojado le doy un ratito más.

martes, 5 de mayo de 2009

Maqueta Shelby Series 1

Al fin logre terminar mi primera maqueta al 100%, antes había tenido experimentos con aviones y helicópteros, pero siempre pasaba algo que no me permitía terminar de buena forma.

Aquí dejo las fotos de la evolución de mi primera maqueta.















































domingo, 3 de mayo de 2009

Publicar en Twitter desde php

Mientras nos matábamos de frio con un amigo decidimos hacer un bot para que vía twiter nos informe la temperatura.

lo complicado era aprender como publicar en twitter cosa que se logra en 4 líneas gracias a esta api

el código
para publicar es el siguiente:


<?php

include('ruta a la api');
$twitter = new Twitter("usuario_twitter", "contraseña_twitter");
$public_timeline_xml = $twitter->getPublicTimeline("xml");
$twitter->updateStatus("Mensaje a publicar");

?>

Gracias a esa base se genero el bot twitter que nos entrega el tiempo meteochile_stgo.

para que funcione automaticamente el php se ejecuta mediante crontab.


domingo, 19 de abril de 2009

vmware + ubuntu + samba

En las siguientes líneas les mostrare como hice logre montar una carpeta de linux bajo vmware desde windows (para esto me base en HOWTO: VMware - Ubuntu to XP - Setup Samba File Sharing ).

Esto no necesariamente es la mejor forma, pero es la que me funciono :)

Para esto el linux antes que nada debe contar con el servicio samba.

En mi caso para partir con un ejemplo que me fuera útil, montare la carpeta '/var/www' donde apache almacena los fuentes de los sitios web.

Creamos el grupo sharer
#sudo groupadd sharer

Creamos el usuario sharer perteneciente al grupo sharer
#sudo useradd --gid sharer --shell /bin/false sharer --home /nonexistent

le asignamos una clave al usuario sharer
#sudo smbpasswd -a sharer

para este ejemplo compartiremos la carpeta /var/www

#cd /var
#sudo chown tu_username:sharer www
#sudo chmod 775 www
#sudo chmod g+s www

editamos /etc/samba/smb.conf


security = share

[www]
path = /var/www
valid users = sharer
read only = No
create mask = 0777
directory mask = 0777


Ahora reiniciamos samba

#sudo /etc/init.d/samba restart


Codigo para montar desde un linux (probado en un linux ubuntu 9.10)
sudo mount -t cifs //192.168.1.130/www /mnt/smb -o username=sharer,password=xxxxx

Ahora viene montar la unidad desde windows
En mi caso tengo el windows en ingles

En windows nos vamos al explorador de windows
ahí seleccionamos Tools->Map Network Drive



En mi caso le asigne la unidad 'Z'
y la carpeta \\la_ip_de_mi_linux\www



Selecciono: Connect using a different user name (conectarse con un usuario distinto).
usuario: sharer
password: cla clave asignada al usuario sharer


Presionamos 'OK' y finalmente 'Finish'

Quedando finalmente asi.


domingo, 5 de abril de 2009

Columna con 100% de alto dentro de div.

Hace poco me tope con un problema en el cual deseaba poner una columna en el lado izquierdo con un alto del 100% y que a su vez no excediera la altura del contenedor de dimensiones variables para que el pie de página no exceda los límites del navegador.

Si el contenido de la columna del lado izq hacia que excediera la altura del contenedor debia funcionar la opción css 'overflow: auto'

Primero genere una página basándome en http://www.cssstickyfooter.com/ para que el pie de pagina siempre quedara al final (razón por me era desconocido la altura del contenedor).

además use las librerías de prototype para simplificar el manejo de los javascript.

Quedando asi.



el lado blanco representa el menú izquierdo, el amarillo el contenido donde si desean pueden aplicar el mismo truco, la parte inferior el pie de página.




Codigo XHTML
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<link rel="stylesheet" href="http://www.cssstickyfooter.com/style.css" type="text/css" media="screen" />
<script type="text/javascript" src="http://www.prototypejs.org/javascripts/prototype.js"></script>

<script type="text/javascript">
Event.observe(window, 'load', function() {
redimensiona();
});

window.onresize = function(){
redimensiona();
}

function redimensiona(){
var contenedor = $('contenedor');
var menu = $('menu-izq');
var foot = $('footer');
var contDims = contenedor.getDimensions();
var menuDims = menu.getDimensions();
var footDims = foot.getDimensions();
var y = ( contDims.height - footDims.height ) ; /*resto footer*/
var styles = { height: y +'px' };
menu.setStyle(styles);

}

</script>

</head>

<body id="contenedor">

<div id="wrap" style="background-color:#CCCCCC">
<div id="main" class="clearfix" >
<div id="menu-izq" style="background-color:#FFFFFF;float:left;width:100px;overflow:auto;">menu </div>
<div id="detalle" style="background-color:#FFFF00">contenido</div>
</div>
</div>
<div id="footer" style="background-color:#993300">
Pie de pagina
</div>
</body>
</html>


la función redimensiona se encarga de redimensionar la altura del menú izquierdo al calcular la nueva altura 'y' al restarle al contenedor principal 'contenedor' la altura del pie 'footer' con la operacion var y = ( contDims.height - footDims.height ) ; para luego reasignársela al menú 'menu-izq' con var styles = { height: y +'px' }; menu.setStyle(styles); .