lunes, 26 de septiembre de 2011

Eclipse - Decompilador

En esta URL se encontrara un plugin para eclipse que nos permite decompilar los .class a demanda

http://java.decompiler.free.fr/?q=jdeclipse

Otra opción que probé y me anduvo bien:

http://www.mkyong.com/java/java-decompiler-plugin-for-eclipse/

NOTA: Seguir todos los pasos.. primero descargar el JAD (lo baje como ZIP) y despues bajarnos el plugin para eclipse y por ultimo configurarlo desde windows->preferences->java->jadClipse

martes, 13 de septiembre de 2011

Oracle - Creacion de tablas y secuencias

A continuación vamos a ver algunos ejemplos básicos de creación de tablas en Oracle como así también la generación de PK, FK y secuencias:

Requisitos previos

Tener instalado y levantado una base de datos Oracle.

Usuario / password de base de datos

  • prueba prueba

Comandos para crear el usuario y password en la BD, necesarios para este tutorial:

  • drop user prueba cascade;
  • create user prueba identified by prueba ;
  • grant DBA to prueba;


Ejemplos

A continuación crearemos un par de tablas con PKs, PK compuesta,  FKs y un sequence.


create table USUARIOS(
  nombre varchar2(30),
  clave varchar2(10)
);


select * from usuarios;


drop table usuarios;


select * from all_tables


CREATE TABLE supplier (      
    supplier_id     numeric(10)     not null,
    supplier_name   varchar2(50)    not null,
    contact_name    varchar2(50),
    CONSTRAINT supplier_pk PRIMARY KEY (supplier_id)
);


CREATE TABLE products (      
    product_id      numeric(10)     not null,
    supplier_id     numeric(10)     not null,
    CONSTRAINT fk_supplier  FOREIGN KEY (supplier_id) REFERENCES supplier(supplier_id)
);


create table employee_history( 
    employee_id       number(6) not null,
    salary            number(8,2),
    hire_date         date default sysdate,
    termination_date  date,
    termination_desc varchar2(4000),
    constraint emphistory_pk
    primary key (employee_id, hire_date)
);


CREATE SEQUENCE test_sequence
    START WITH 1
    INCREMENT BY 1;


INSERT INTO SUPPLIER(SUPPLIER_ID, SUPPLIER_NAME, CONTACT_NAME) 
    VALUES(test_sequence.nextval, 'nombre2', 'contacto2');


select * from SUPPLIER



 SUPPLIER_ID     SUPPLIER_NAME     CONTACT_NAME    
 --------------  ----------------  --------------- 
 1               nombre1           contacto1       
 2               nombre2           contacto2       





O bien, para no tener que usar el NEXTVAL del sequence cada vez que insertamos datos, podemos armar un trigger como muestra el siguiente ejemplo:
Trigger definition:
CREATE OR REPLACE TRIGGER dept_bir
BEFORE INSERT ON departments
FOR EACH ROW

BEGIN
  SELECT dept_seq.NEXTVAL
  INTO   :new.id
  FROM   dual;

END;

lunes, 12 de septiembre de 2011

RMI - Mi primer ejemplo

Seguir los pasos de este tutorial:



1. Codigo fuente:

package rmi.server.suma;


import java.rmi.Remote;


/**
 * Es una interface java con todos los métodos que queramos poder invocar de forma remota, es decir, 
 * los métodos que queremos llamar desde el cliente, pero que se ejecutarán en el servidor.
 * 
 * Tiene que heredar de la interface Remote de java, si no el objeto no será remoto
 * 
 * Todos los parámetros y valores devueltos de estos métodos deben ser tipos primitivos 
 * de java o bien clases que implementen la interface Serializable de java
 * 
 * http://www.chuidiang.com/java/rmi/rmi.php
 * 
 * 
 * @author dciocca
 */
public interface InterfaceRemota extends Remote {


    public int suma (int a, int b) throws java.rmi.RemoteException; 
}





package rmi.server.suma;


import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;


/**
 * Esta clase remota debe implementar la interface remota que hemos definido (y por tanto implementará 
 * también la interface Remote de java).
 * 
 * Debe definir métodos como hashCode(), toString(), equals(), etc de forma adecuada a un objeto remoto
 * Es decir, debera tener en cuenta una serie de cosas más o menos complejas y de las que afortunadamente 
 * no tenemos que preocuparnos ya que haremos que esta clase herede de UnicastRemoteObject.
 * 
 * @author dciocca
 *
 *
 */
public class ObjetoRemoto extends UnicastRemoteObject implements InterfaceRemota { 

private static final long serialVersionUID = 1L;

    protected ObjetoRemoto() throws RemoteException {
super();
}


public int suma(int a, int b)  
    { 
        System.out.println ("sumando " + a + " + " + b + "..."); 
        return a+b; 
    }
}




package rmi.server.suma;


import java.rmi.Naming;


/**
 * Programa java que instancie y registre el objeto remoto.
 * 
 * Para su correcto funcionamiento debe estar ejecutandose el proceso 
 * rmiregistry
 * En caso que no este corriendo el demonio rmiregistry lanzara la siguiente 
 * excepcion:
 * java.rmi.ConnectException: Connection refused to host: localhost
 *  
 * @author dciocca
 *
 */
public class Servidor {

    public Servidor() {
        try {
       
// Este programa instanciara y registrara el objeto remoto. 
        // Es importante mantener la barra al final.
System.setProperty(
"java.rmi.server.codebase",
"file:/C:/Desarrollo/wc_rmi/Rmi_Test/bin/");

            // Se publica el objeto remoto
            InterfaceRemota objetoRemoto = new ObjetoRemoto();
            // El método rebind() registra el objeto en rmiregistry. 
            // Si ya estuviera registrado, lo sustituye por el que acabmos de pasarle
            Naming.rebind ("//localhost/ObjetoRemoto", objetoRemoto);
            
            System.out.println("Objeto registrado en el rmiregistry!!");
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Servidor();
    }


}



package rmi.server.suma;

import java.rmi.Naming;

/**
 * Programa que utiliza el objeto de forma remota previamente registrado en el
 * rmiregistry
 * 
 * IMPORTANTE:
 * 
 * Para que el código del cliente compile necesita ver en su classpath a InterfaceRemota.class. 
 * Para que además se ejecute sin problemas los metodos del stub, necesita además ver a ObjetoRemoto_Stubs.class, 
 * por lo que estas clases deben estar accesibles desde el servidor o bien tener copias locales de ellas.
 *  
 * @author dciocca
 *
 */
public class Cliente {
/** Crea nueva instancia de Cliente */
    public Cliente() {
        try {
        // Lugar en el que está el objeto remoto.
        // Debe reemplazarse "localhost" por el nombre o ip donde
        // esté corriendo "rmiregistry".
        // Naming.lookup() obtiene el objeto remoto
            InterfaceRemota objetoRemoto = 
                (InterfaceRemota)Naming.lookup ("//localhost/ObjetoRemoto");
            
            // Se realiza la suma remota.
            System.out.print ("2 + 3 = ");
            System.out.println (objetoRemoto.suma(2,3));
            
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Cliente();
    }

}


2. Generación del stub (en la pc servidor)


Para que desde un programa que se encuentra en una PC o JVM se pueda llamar a un método de una clase que está en otra PC o JVM, está claro que de alguna manera se debe enviar un mensaje por red de una pc a otra, indicando que se quiere llamar a determinado método de determinada clase y además pasar los parámetros de dicha llamada. Una vez ejecutado el método, el ordenador que lo ha ejecutado debe enviar un mensaje con el resultado. La clase de stubs es una clase con los mismos métodos que nuestro ObjetoRemoto, pero en cada uno de esos métodos está codificado todo el tema del envio del mensaje por red y recepción de la respuesta.
Es por eso que si se modifica la clase, también se debera modificar el stub para que el cliente tenga siempre el ultimo objeto con el que interactuar.

C:\Desarrollo\wc_rmi\Rmi_Test\src> set CLASSPATH=c:\Desarrollo\wc_rmi\Rmi_Test\bin

C:\Desarrollo\wc_rmi\Rmi_Test\src> rmic rmi.server.suma.ObjetoRemoto

Este comando nos generara la siguiente clase:

ObjetoRemoto_Stub.class


NOTA: Esto generara el .class bajo el directorio donde lanzamos RMIC respetando el package de la clase.


3. Ejecutamos el rmiregistry  (en la pc servidor)

C:\Desarrollo\wc_rmi\Rmi_Test\src> set CLASSPATH=
C:\Desarrollo\wc_rmi\Rmi_Test\src> rmiregistry

NOTA: Listo, queda escuchando el proceso. Ahora podemos instanciar el objeto remoto al rmiregistry



4. Ejecutamos el servidor.java para instanciar el objeto remoto al remiregistry  (en la pc servidor)




De esta manera queda registrado el objeto en el rmiregistry de la pc que actúa como servidor.


5. Copiamos o agregamos al classpath (tanto la InterfaceRemota.class como el stub generado previamente (en la pc que actúa como cliente)


Es necesario agregar tanto la interface InterfaceRemota.class (del servidor) y el stub (del servidor) en el mismo directorio donde vamos a ejecutar la clase Cliente.java (en el cliente). Es decir, estas 3 clases ya compiladas las copiamos a otra carpeta por ejemplo: c:\Desarrollo\Prueba\rmi\server\suma





6. Ejecutamos el cliente.java (en la pc que actua como cliente)




ANEXO 1: Todas las capturas juntas



Aquí vemos como en la ventana del servidor sale un "Sumando 2 + 3 = ..." y en la del cliente "2 + 3 = 5".


ANEXO 2: Paso por parametro de un objeto serializable ( no primitivo )


En estos casos, el objeto debera implementar la interface serializable y luego tendremos que tener una copia del .class del objeto utilizado como parametro en la pc o JVM donde este corriendo el cliente.

Para que la clase sea realmente Serializable, necesita además, que todos sus atributos sean también Serializable

Cuando pasamos un objeto Serializable como parámetro de un método remoto, java se encarga de convertir ese objeto a bytes (serializar el objeto), enviarlo por red y hacerlo llegar al otro lado (el servidor). Allí, java se encarga de convertir nuevamente esos bytes a un objeto (deserializar el objeto). Si no usamos carga dinámica de clases, tanto el cliente como el servidor deben tener esa clase en su CLASSPATH para poder usarla.

Existe otro pasaje de parámetros conocido como parámetros remotos pero que no se entrara en detalle.


ANEXO 3: Carga dinamica de clases

Como vimos en este ejemplo, cada clase Serializable que pasemos de un lado a otro (cliente/servidor) necesita tener dos copias del fichero .class, una en el cliente y otra en el servidor, de forma que ambos puedan usarlo. 

Habilitando un mecanismo de RMI llamado carga dinámica de clases, podemos evitar hacer estas copias. Por medio de este mecanismo, el cliente y el servidor dicen donde están sus clases Serializable. Este sitio debe ser accesible desde la red. De esta forma, cuando el servidor, por ejemplo, necesite una clase del cliente porque la recibe como parámetro, RMI se encargará de descargar esa clase automáticamente del sitio que ha indicado el cliente.






martes, 6 de septiembre de 2011

SVN - Instalación del plug-in de SVN para Eclipse

Plug-in Subclipse

En la siguiente URL encontraremos paso a paso como configurar e instalar el plugin de SVN para eclipse

http://subclipse.tigris.org/

y de ahí vamos a la opción "Download and Install" o bien vamos directamente mediante la siguiente opción:

http://subclipse.tigris.org/servlets/ProjectProcess;jsessionid=5A625973C921F8565D47C08504027F31?pageID=p4wYuA

En caso que querramos realizar la instalacion offline (es decir, bajarnos el plugin e instalarlo en eclipse sin descarga alguna), vamos a utilziar la siguiente pagina (o bien desde el sitio oficial nos bajamos el ZIP):
Ej: site-1.4.8.zip 


Luego descomprimimos este ZIP y hacemos todos los pasos como si estuviesemos instalandolo mediante la URL pero con la unica salvedad que a la hora de agregar la URL presionamos local e indicamos donde esta la carpeta con el subclipse descomprimido.

Compatibilidad con el TortoiseSVN


A la hora instalar tanto el plugin del eclipse (subecilpse) como el tortoiseSVN, para tener un control de versiones tanto de la IDE como desde el filseystem, se tiene que tener cierta precaución respecto a las versiones que se utilizan ya que sino vamos a tener problemas:

Ver http://subclipse.tigris.org/wiki/JavaHL


Subclipse Version
SVN/JavaHL Version

1.8.x
1.7.x

1.6.x
1.6.x

1.4.x
1.5.x

1.2.x
1.4.x

1.0.x
1.4.x


Compatibilidad con cliente de SVN (sliksvn) por consola:

Descargar el cliente llamado sliksvn version 1.7.x para las versiones del subeclipse 1.8.x y version del svn 1.7.x

Descargar desde aqui: http://www.sliksvn.com/en/download

Existe otro del collabnet: http://www.collab.net/downloads/subversion


Como mergear entre dos ramas distintas (rama A contra 6 commits seleccionados por el usuario de la rama B) utilizando el TortoiseSVN


Nos paramos sobre la rama A (que es donde vamos a querer traer los cambios de los 6 commits que se produjeron en la rama B) y presionamos merge




Luego, seleccionamos la rama B y sobre esta rama seleccionamos los 6 commits que vamos a querer llevar a la rama A:


Luego vamos a SHOW LOGs y ahi seleccionamos los COMMITs que queremos pasar a la rama A


Una vez seleccionados todos los COMMITs, presionamos OK y nos aparecera la siguiente pantalla.


Luego presionamos NEXT


Y antes mergear, presionamos TEST MERGE para ver de forma simulada lo que pasara:









NOTA IMPORTANTE: 

Para los casos de CONFLICTOS si NO queremos mergearlos/mirarlos desde el TORIOISE ya que confunde un poco, podemos luego mirarlos desde el ECLIPSE. 

Para esto podemos resolverlos despues (RESOLVE LATER). De esta manera luego podemos ir al eclipse, seleccionar el archivo y luego comparalo con la version del BRANCH (Rama B) y desde ahi ver con que cosas nos quedamos y con que cosas no.


Ver: Guia rápida para utilizar el tortoiseSVN

Pasos para crear un BRANCH/TAG


http://tortoisesvn.net/docs/nightly/TortoiseSVN_es/tsvn-dug-branchtag.html


Seleccionamos Copy to...