Esta vez , nos encontramos en el caso de que queremos encontrar que tablas de nuestra base de datos contienen una columna de la cuál sabemos su nombre o una parte de él, para realizar esta búsqueda, tenemos dos formas, o vamos abriendo tabla por tabla... o bien mediante una consulta SQL, donde especificamos en el LIKE el nombre de la columna a buscar

MYSQL

select * from INFORMATION_SCHEMA.COLUMNS 
where COLUMN_NAME like '%nombreColumna%' 
order by TABLE_NAME

ORACLE

select distinct table_name, 
                column_name, 
                data_type || ' (' || 
                decode(data_type,'LONG',null,'LONG RAW',null,
                       'BLOB',null,'CLOB',null,'NUMBER',
                       decode(data_precision,null,to_char(data_length),
                              data_precision||','||data_scale
                             ), data_length
                      ) || ')' data_type
  from all_tab_columns
 where column_name like ('%' || upper('nombreColumna') || '%');

Debemos tener en cuenta las mayúsculas o minúsculas del nombre de la tabla, para ello, bastaría con modificar las queries de manera sencilla.

Puede darse el caso que a la hora de compilar nuestros proyectos en maven querramos forzar que se baje los jars (dependencias establecidas en el archivo pom.xml) del repositorio remoto , para ello , a nuestro comando de compilación añadiremos -U

Por ejemplo, si queremos borrar carpeta target, compilar y forzar que se baje las dependencias, ejecutaremos:

mvn clean install -U

En el caso que no queramos que se baje ningún jar de nuestro repositorio remoto, si no, que siempre use las que tengamos en nuestro repositorio local, usaremos -o

mvn clean install -o

Puede darse el caso que necesitemos saber con que versión de la JDK de java está compilada la calse, para ello tenemos dos comandos que podemos utilizar, en función del sistema operativo en el que nos encontremos.

Para Windows:

javap -v <class> | findstr major

Para Linux/Unix:

javap -v <class> | grep major

Por ejemplo, si queremos saber la versión con que está compilada la clase ./org/apache/log4j/Appender.class del jar de log4j

javap -v ./org/apache/log4j/Appender.class | grep major
 major version: 45

Donde nos indica que la versión es la 51, número que corresponde con la siguiente tabla de versiones de Java JDK:

Major version Versión Java
45.3 Java 1.1
46 Java 1.2
47 Java 1.3
48 Java 1.4
49 Java 5
50 Java 6
51 Java 7
52 Java 8

Para enviar emails desde un EJB, tendremos que crear un bean de sessión donde definimos por jndi la configuración del email, a posteriori creamos nuestro message de la clase MimeMessage

@Stateless(name = "EmailEJB")
public class EmailEJB implements EmailRemoteEJB {


@Resource(name = "mail/miMailSession")
private Session mailSession;

@Asynchronous
@Lock(LockType.READ)
    public void sendMail(String recipient, String subject, String msg) {
        try {
                        //En algunos servidores (como wildfly 10) la inyección del Resource no funciona, entonces tendremos que hacer el lookup.
            if (mailSession == null) {
                InitialContext ic = new InitialContext();
                mailSession = (Session) ic.lookup("java:/futuramail");
            }
            MimeMessage message = new MimeMessage(mailSession);
            Address[] to = new InternetAddress[]{new InternetAddress(recipient)};
            message.setRecipients(Message.RecipientType.TO, to);
            message.setSubject(subject);
            message.setSentDate(new Date());
            message.setContent(msg, "text/html"); 

            // No es obligatorio, pero es bueno, indicar quien genera el mensaje
             message.setHeader("X-Mailer", "Mail generado por runando");

            Transport.send(message);
            Logger.getLogger(EmailEJB.class.getName()).log(Level.INFO, null, "Email enviado correctamente.");
        } catch (MessagingException me) {
            //me.printStackTrace();
            Logger.getLogger(EmailEJB.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NamingException ex) {              
            Logger.getLogger(EmailEJB.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Ahora tendremos que configurar el JNDI Mail Session en nuestro contenedor de aplicaciones (weblogic , wildfly, jboss...)
Entramos en la consola de weblogic:

http://IPWEBLOGIC:port/console

En la opción de Services, subopción Mail Sessions, pulsamos sobre "configurar un email de sesión", siendo los parámetros:

Name: mail/miMailSession
JNDI name: mail/miMailSession
Username: miEmail@company.com
Password:  [password del usuario]
JavaMail Properties:
mail.smtp.starttls.enable=true
mail.smtp.port=587
mail.user=miEmail
mail.smtp.ssl.trust=smtp.company.com
mail.smtp.auth=true
mail.smtp.host=smtp.company.com
mail.smtp.password=[password del usuario]
mail.debug=True
username=miEmail@company.com
mail.from=miEmail@company.com
mail.smtp.user=miEmail@company.com
mail.transport.protocol=smtp

No olvidar seleccionar un servidor de destino al final del procedimiento, para que la sesión esté disponible.

Podemos tener el caso que tengamos un array de objetos, los cuales queramos añadir mediante cóigo, y a partir de uno de sus atributos, para ello la API de php proporciona la funció usort .

Supongamos que tenemos el array de datos siguiente:

 Array
(
    [element-0] => stdClass Object
        (
            [ID] => 1
            [nombre] => María
            [edad] => 42
        )

    [element-1] => stdClass Object
        (
            [ID] => 2
            [nombre] => Fernando
            [edad] => 23
        )

    [element-2] => stdClass Object
        (
            [ID] => 3
            [nombre] => Juan
            [edad] => 35
        )

Y para realizar la ordenación, a la función usort pasaremos como parámetros el array que queremos ordenar y la función que realizará las comprobaciones.

usort($teachers,'sortArrayByLastName');

donde la función sortArrayByLastName sería:

function sortArrayByLastName( $a, $b )
{
    if(  $a->name ==  $b->name){
        return 0; 
    }
    return ($a->name < $b->name) ? -1 : 1;
}

Dando como resultado , si lo imprimos:

Fernando
Juan
María

Si queremos realizarlos de manera ascendente o descendente tendremos que invertir el comparador < por > en la función.

Una versión más completa podría ser la siguiente que ofrece la posibilidad de ordenar String, o de manera ascendente o descendente.

   function sortArrayByKey(&$array,$key,$string = false,$asc = true){
    if($string){
        usort($array,function ($a, $b) use(&$key,&$asc)
        {
            if($asc)    return strcmp(strtolower($a[$key]), strtolower($b[$key]));
            else        return strcmp(strtolower($b[$key]), strtolower($a[$key]));
        });
    }else{
        usort($array,function ($a, $b) use(&$key,&$asc)
        {
            if($a[$key] == $b[$key]){return 0;}
            if($asc) return ($a[$key] < $b[$key]) ? -1 : 1;
            else     return ($a[$key] > $b[$key]) ? -1 : 1;

        });
    }
}

y su uso sería:

sortArrayByKey($yourArray,"name",true); //String sort (ascending order)
sortArrayByKey($yourArray,"name",true,false); //String sort (descending order)
sortArrayByKey($yourArray,"id"); //number sort (ascending order)
sortArrayByKey($yourArray,"count",false,false); //number sort (descending order)

Hay que tener en cuenta que usort hace perder las claves del array original, es decir, que el array inicial, quedaría.

 Array
(
    [0] => stdClass Object
        (
            [ID] => 2
            [nombre] => Fernando
            [edad] => 23
        )

    [1] => stdClass Object
        (
            [ID] => 3
            [nombre] => Juan
            [edad] => 35
        )
        
    [2] => stdClass Object
        (
            [ID] => 1
            [nombre] => María
            [edad] => 42
        )   

para evitarlo y si las claves son necesarias y no quieres perderlas deberás utilizar la función uasort(), que funciona de forma similar pero manteniendo las claves:
cuenta que usort hace perder las claves del array original, es decir, que el array inicial, quedaría.

 Array
(
    [element-0] => stdClass Object
        (
            [ID] => 2
            [nombre] => Fernando
            [edad] => 23
        )

    [element-1] => stdClass Object
        (
            [ID] => 3
            [nombre] => Juan
            [edad] => 35
        )
        
    [element-2] => stdClass Object
        (
            [ID] => 1
            [nombre] => María
            [edad] => 42
        )   

Podéis encontrar más información en la documentación oficial.

BIRT

Birt es un proyecto de la fundación eclipse . En pocas palabras, es un framework de informes que permite crear fácilmente informes visuales (que incluyen gráficos, gráficos y tablas) desde cualquier fuente de datos compatible con Java (JDBC, por ejemplo).

Los informes BIRT se crean y se visualizan con Eclipse. El único inconveniente de esto es que todo el mundo que quiere ver un informe BIRT necesita el informe real en su PC más Eclipse instalado. Para evitar esto, BIRT tiene un visor que se puede ejecutar desde cualquier contenedor de Java EE como Tomcat o JBoss. Otra forma de visualizar los informes generados , es ejecutar el motor de Birt desde un web service, servicio REST, clase java... pero eso lo veremos otro día.

Instalación Java

La versión que tenemos que utilizar es la JDK 1.8 que se puede descargar de la página , aseguramos que en las variables del sistema establecemos las variables JAVA_HOME y PATH con la nueva instalación de la máquina virtual.

JAVA_HOME ="RUTA HASTA LA INSTALACION"
PATH = %PATH%;%JAVA_HOME%\bin

Instalación y configuración de Tomcat

Descargar de la página de Apache tomcat. Estas pruebas han sido realizadas con la versión bajada 8.5.13. El nombre del archivo exacto fue apache-tomcat-8.5.13.zip que contiene el servidor.
Descomprimimos en una carpeta y realizamos la configuración para dar permisos al usuario.
apache-tomcat-8.5.13\conf\tomcat-users.xml

añadir, por ejemplo:

<role rolename="admin"/>
<role rolename="manager"/>
<role rolename="manager-gui"/>
<user username="admin" password="admin" roles="admin,manager"/>
<user  username="tomcat" password="tomcat" roles="admin, manager-gui,manager"/>

Para comprobar que arranca de manera correcta, introducimos la url http://localhost:8080/ (si hemos cambiado el puerto, lo cambiamos por el 8080), tendremos el mensaje.

org.apache.coyote.AbstractProtocol start
INFORMACIÓN: Starting ProtocolHandler ["http-apr-8080"]
org.apache.coyote.AbstractProtocol start
INFORMACIÓN: Starting ProtocolHandler ["ajp-apr-8009"]
org.apache.catalina.startup.Catalina start
INFORMACIÓN: Server startup in 17313 ms

Instalación Birt Viewer

BIRT Viewer puede ser descargado desde el paquete Birt Engine, en nuestro caso hemos descargado la versión 4.6.0-20160607 que corresponde con el archivo birt-runtime-4.6.0-20160607.zip. Una vez descargado , descomprimimos el zip y copiamos el directorio WebViewerExample directory a la ruta de despliegue de aplicaciones, webapps, de nuestro tomcat, podemos renombrarlo como queramos, por ejemplo, birt.

Recuerda dar permisos suficientes al directorio de birt para el usuario que ejecuta el tomcat, en caso que estemos en una máquina linux.

Reiniciamos el tomcat y podemos comprobar que BIRT está desplegado correctamente , si entramos en el Manager del tomcat http://localhost:8080/manager/html. Si está bien (running), podremos acceder al Birt Viewer con la url http://localhost:8080/birt , si no ha arrancado correctamente, visualizar los logs del tomcat para detectar el problema.

Una vez está desplegado, deberemos copiar los reports que hayamos realizado en la raiz del war (.../apache-tomcat-7.0.53/webapps/birt) , ubicación por defecto, y podremos acceder a ellos a través de la url http://localhost:8080/birt/frameset?__report=example_report.rptdesign .
Puede ocurrir que por organización querramos tener todos nuestros reports en un directorio aparte, u organizarlos en subcarpetas (.../apache-tomcat-7.0.53/webapps/birt/path_report/) , en ese caso, en la url, añadiremos esa carpeta a través de la que se podrá acceder http://localhost:8080/birt/frameset?__report=path_report/example_report.rptdesign

Habilitar el acceso a base de datos

Si nuestros reportes acceden a base de datos, deberemos instalar el driver JDBC en el war de Birt Viewer.

Una vez descargados , copiar el jar correspondiente a la base de datos que esté utilizando, mysql-connector-java-3.1.14-bin.jar o ojdbc6-11g.jar a BIRT en la ruta:
.../apache-tomcat-7.0.53/webapps/birt/WEB-INF/platform/plugin/org.eclipse.birt.report.data.oda.jdbc_2.6.2.r262_v20110127/drivers/

Posibles errores

Si al desplegar y ejecutar Birt Viewer obtienes algunos de estos errores:

  • Caused by: java.lang.UnsupportedClassVersionError: org/eclipse/datatools/connectivity/oda/OdaException : Unsupported major.minor version 52.0 (no puedo cargar clase org.eclipse.datatools.connectivity.oda.OdaException)

  • Caused by: java.lang.SecurityException: Invalid signature file digest for Manifest main attributes

  • java.lang.SecurityException: class "org.eclipse.datatools.package..."'s signer information does not match signer information of other classes in the same package

    • La solución es eliminar los archivos META-INF/ECLIPSE_.RSA y META-INF/ECLIPSE_.SF de los jars de la carpeta WEB-INF\lib del war de Birt Viewer, por ejemplo, de org.eclipse.birt.runtime_4.6.0-20160607.jar, ya que este error es debido a que, el archivo org.eclipse.birt.runtime_4.6.0-20160607.jar has no tiene una firma válida. O bien bajarse la versión más reciente de org.eclipse.birt.runtime_4.6.0-20160607.jar

Este error se obtiene cuando se intenta ejecutar una clase con una versión menor a la versión de Java con que fue compilada, es decir: Si tenemos una clase compilada con Java 8, es decir, tiene la versión principal 52 y la ejecutamos como clase en JRE 7, obtendremos el mensaje "Unsupported Major.minor versión 52.0 "

Las versiones de la jdk se refieren de la siguiente forma:

JDK Versión
Java SE 8 52
Java SE 7 51
Java SE 6.0 50
Java SE 5.0 49
JDK 1.4 48
JDK 1.3 47
JDK 1.2 46
JDK 1.1 45

Cuando estamos utilizando openEJB para realizar nuestros test unitarios (Junit) puede sernos de gran utilidad hacer rollback en algunos métodos, como por ejemplo, al realizar un insert , delete o update de registros y estamos trabajando con base de datos finales, lo que provocaría que no tendrían efectos los cambios que hicieramos en nuestros test.

En nuestras pruebas estamos utilizando UserTransaction para controlar los datos de la prueba.

Para realizar el rollback, anotamos como @BeforeClass y @AfterClass los método que realizarán las operaciones de inicio y final de la transación, si lo vamos a usar en muchas clases, podríamos moverlo a una clase padre y heredar de ella..
Esto funciona bien con openejb 3.0.
UserTransaction se puede recuperar con una búsqueda jndi (java:openejb/UserTransaction) siempre que la inyección con la anotación @Resource no llegará a funcionar.

public MyTest { 

 static  MyService service; 
 
 @Resources
 UserTransaction tx; 

@BeforeClass 
public static void  onBeforeClass() throws Exception{ 
   // start openejb embeded container  here 
   InitialContext ctx  = new  IntialContext(props); 
   // lookup service here 
   service = (MyService)  ctx.lookup("java:openejb/MyServiceLocal"); 
  
} 

@AfterClass 
public static void  onAfterClass() throws Exception{     
   OpenEJB.destroy(); //destruimos el EJB
} 

@Before 
public void onBefore() throws Exception{ 
  //iniciamos la transacción o bien, la anotamos con @Resources
  //utx = new org.openejb.core.CoreUserTransaction() 
  //comenzamos la transacción
  utx.begin(); 
} 

@After 
public void onAfter() throws Exception{ 
    //hacemos rollback
  utx.rollback();
  //podríamos hacer el commit si nos interesara más que el rollback
  //utx.commit();
} 

//ejemplo de test 
@Test 
public void testServiceMethod() throws  Exception{ 
  service.hacerAlgo(); 
} 

} 

En algunos casos puede interesarnos generar un String con el MD5 de una cadena de texto.

Utilizaremos para ello la clase de java.security.MessageDigest y la instanciaremos indicando el algoritmo que queremos ejecutar.

MessageDigest soporta los siguientes algoritmos estándar: MD5, SHA-1 y SHA-256

Utilizando la función digest donde pasamos los bytes del String que queremos codificar, obtendremos el array de bytes con el md5 generado, para transformarlo a String, utilizamos la conversión que trae Integer mediante la función toHexString.

public static String MD5(String md5) {
   try {
        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(md5.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
          sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
       }
        return sb.toString();
    } catch (java.security.NoSuchAlgorithmException e) {
    }
    return null;
}

O lo que es lo mismo, mediante Reflection, la obtención de todos los campos de una clase incluidos los de la clase padre.

Supongamos que tenemos dos clases, una clase A, y una clase B que extiende de A.

public class A {
    private String attriA;
}

public class B extends A {
    private String attriB;
}

Si sólo quisiera obtener los campos de la clase B, sin los de la clase padre A, lo haríamos sencillamente en una supuesta ejecución.

B b = new B();
Class klassB = b.getClass();

y para obtener los campos:

Fields[] fieldB = klassB.getDeclaredFields();

Ahora bien, al tener un padre, tendremos que recorrer también los campos del padre, que solucionamos con implementando un método que nos devolverá los campos del padre y del hijo.

Sólo los campos del padre.

Fields[] fieldA = klassB.getSuperclass()getDeclaredFields();

Y para obtener todos los campos, añadimos a un ArrayList tanto los del hijo como los del padre (si lo tuviera)

 List<Field> fields = new ArrayList<Field>();
        fields.addAll(Arrays.asList(klass.getDeclaredFields()));
        if (klass.getSuperclass() != null) {
            fields.addAll(Arrays.asList(getAllFields(klass.getSuperclass())));
        }
Copyright © 2016 runando