Mostrando entradas con la etiqueta java. Mostrar todas las entradas
Mostrando entradas con la etiqueta java. Mostrar todas las entradas

domingo, 22 de marzo de 2015

WCS. jar manifest file does not contain the permissions attribute

Estaba trabajando con WebCenter Sites en local, y al actualizar la jre a java 8 el menú lateral de la vista administración desapareció. Al tratar de recuperarlo obtuve un error jar manifest file does not contain the permissions attribute .


Applet no firmado

Buscando un poco por internet, me encuentro con que esta versión de jre no permite la ejecución de applets si no están firmados. La solución fue añadir la excepción del dominio a la configuración java:


Configuración de java que activa el menú en WebCenter Sites en local

Con esto se soluciona el problema.

Saludos.

lunes, 17 de febrero de 2014

CProjectPro. Nuevas características en versión móvil.

Después de un sprint de dos semanas estoy contento, ya que acaba de salir a la venta CProjectPro. Esta versión de la aplicación es similar a CProject free, pero con algunas mejoras:


Vista proyectos

Vista analítica
  • No incluye publicidad. Algo obvio en una versión de pago.
  • Exportación de datos: la gran ventaja de esta versión frente a la gratuita es que permite exportar los datos en formato .xml , compatible con Microsoft Project y con GanttProject.

Además también funciona sobre móviles con resolución 480 x 800 o compatibles. Esto sin duda será una alegría para todos los que me habéis escrito email comentando este tema.

Sé que me he desviado un poco del Roadmap publicado hace unas semanas, pero aunque yo tenía unos planes iniciales los comentarios de la gente me hicieron modificarlos.

Las pantallas de la versión móvil han sido bastante trabajadas. Algunos me comentabais que simplemente reduciendo el tamaño del texto sería suficiente, pero tras unas pruebas me pareció mejor opción incluir pestañas tanto en el kanban como en la vista analítica.


Edición de tareas

Vista kanban

Saludos.

jueves, 19 de septiembre de 2013

Quick Fix en eclipse... Unsupported IClasspathEntry kind=4

Hoy me ha pasado una de esas cosas que dan un poco por saco, sólo un poco, aunque en teoría no afectan al proyecto en el que estoy trabajando. El caso es que tengo un proyecto maven y eclipse me está indicando que tiene un problema en el pom.xml y que debo realizar un quick fix.

Hasta ahí todo correcto, nada nuevo. Lo que me molesta es que después ejecutar dicho quick fix eclipse muestra un error Unsupported IClasspathEntry kind=4 y aunque el aviso de error desaparece, vuelve a aparecer si reinicio eclipse. Como siempre hago, he buscado por internet y he dado con varias soluciones (1 y 2 ) que no me han funcionado y una explicación con algo más de detalle del problema.

Después de varias pruebas he dado con una solución que a mí me funciona :D

Consiste en crear una configuración en maven con los parámetros eclipse:clean eclipse:eclipse y ejecutarla. Por supuesto no he tenido que quitar naturaleza de maven, ni reimportar, etc. Y al reiniciar eclipse… sigue funcionando :D

Saludos

domingo, 8 de septiembre de 2013

Menú contextual en ListView no funciona... Desactivar el foco de los items del ListView

Hace casi un año escribí una entrada en la que ponía como hacer un menú contextual para elementos de un ListView. El otro día intenté realizar mi propio ejemplo, y no funcionaba en la nueva aplicación que estoy desarrollando. No obstante la miniaplicación que usé de ejemplo para sicha entrada funcionaba correctamente.

Después de mucho comerme la cabeza, y de muchísimas búsquedas en san google, dí con esta entrada.

Lo que comenta el autor, es que si los items del ListView tienen elementos con "foco activo", en mi caso botones, hay que desactivar dicho foco para que funcione el menú contextual. En resumen, que a cada botón le he tenido que añadir el código:

android:focusable="false"

Esta tontería me ha tenido varios días liado :( . Menos mal que el personal comparte las cosas, y que existe http://stackoverflow.com.

Saludos.

miércoles, 21 de agosto de 2013

Eclipse Juno a pantalla completa.

Buscando por internet como poner eclipse Juno a pantalla completa, me encuentro con este interesante post de stackoverflow en el comentan que hay un plugin de eclipse para hacer eso. Una vez instalado usando Crtl + F11 eclipse estará a pantalla completa, pero no es multimonitor. Saludos.

martes, 23 de julio de 2013

Tonterías varias que mejoran la usabilidad de una aplicación android

Este post lo iré actualizando con pequeños tips rápidos que voy usando en las aplicaciones.

Hacer que por defecto no salga el teclado en una vista con campos de edición:

// Se pone dentro del método onCreate:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

Volver a atrás pulsando el icono principal de la actividad (el superior izquierdo)


@Override
 public boolean onOptionsItemSelected(MenuItem item) {
  super.onOptionsItemSelected(item);
  switch(item.getItemId()){
      
   case android.R.id.home: 
    this.finish(); 
   break; 
   
  }
  return true;
 }

Bloquear el tipo de pantalla (horizontal vs vertical)

En el archivo AndroidManifest.xml, en la declaración de la actividad que queramos forzar:

android:screenOrientation="landscape"  // En este caso la pantalla siempre será horizontal

Fuentes:

Aquí encontré como fijar el giro de pantalla. Aunque tiene más explicaciones interesantes.


jueves, 18 de julio de 2013

Lista select con spinner en android

Acabo de necesitar hacer una lista de selección para mi aplicación en android. Como en otras ocasiones, encontré la respuesta en un blog conocido.

El primer paso consiste en crear los valores que se mostrarán. Dichos valores se almacenan en un fichero arrays.xml situado en la carpeta values.

En mi caso los valores los he referenciado a través del fichero string.xml


 

   
       @string/kanbanlist1
       @string/kanbanlist2
       @string/kanbanlist3
   
    

Después en el layout de la actividad pertinente, escribimos un "spinner" que referencia a los valores sabiendo que "entries" son las entradas del select, y "prompt" el título que muestra el popup.




Sólo nos queda recuperar el valor desde la actividad. A continuación el resultado final.


Lista select.

Popup que sale al pulsar sobre el select

Recuperación del valor:

// Recupera el valor:
Spinner spinnerKanban = (Spinner) findViewById(R.id.editTaskListNumber);
long valueSpinter = spinnerKanban.getSelectedItemId();
valueSpinter++;  // El spinner comienza en 0, pero mis comparaciones de valores en 1 :D
// Operación a realizar con el valor.

Saludos.

sábado, 13 de julio de 2013

Popup de confirmación en android, usando la clase AlertDialog

A veces necesitamos que se muestre un menú de confirmación antes de realizar una determinada acción (a menudo borrar). En android esto se hace con la clase AlertDialog.

En mi caso en concreto tengo mucho listados (ListView) en los cuales muestro una determinada información y varios botones de acción.


Listado de proyectos de aplicación. Cada ítem tiene varios botones con acciones asociadas.

Cada botón tiene asociada un método usando el valor onclick:

android:onClick="deleteProyect"

Dentro dentro de ese método se encuentra el código que muestro a continuación:


import android.app.AlertDialog;
import android.content.DialogInterface;

...

          AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
          // set title
          String alert_title = getResources().getString(R.string.alert_project_delete_title);
          String alert_description = getResources().getString(R.string.alert_project_delete_description);
    alertDialogBuilder.setTitle(alert_title);

    // set dialog message
    alertDialogBuilder
     .setMessage(alert_description)
     .setCancelable(false)
     .setPositiveButton("Yes",new DialogInterface.OnClickListener() {
      // Lo que sucede si se pulsa yes
      public void onClick(DialogInterface dialog,int id) {
       // Código propio del método borrado para ejemplo
      }
      
      
       })
     .setNegativeButton("No",new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog,int id) {
       // Si se pulsa no no hace nada
       dialog.cancel();
      }
     });
  
     // create alert dialog
     AlertDialog alertDialog = alertDialogBuilder.create();
  
     // show it
     alertDialog.show();

Y este es el resultado final:


Diálogo de confirmación antes de borrar.

Saludos

domingo, 7 de julio de 2013

Desactivando el foco (onFocus) en las vistas de android

Unas de las cosas que más me molesta de las aplicaciones android es que al cambiar de actividad, si la nueva actividad tiene campos de edición como (EditText) el foco se sitúa sobre ellos, mostrando el teclado virtual.

Navegando encontré un buen post en el que se indica como desactivar el autofocus.

Sencillo, simplemente 2 líneas en el elemento padre de la vista:

android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"

En mi opinión este detallido puede parecer una tontería, pero mejora la usabilidad de la aplicación.

Saludos.

sábado, 4 de mayo de 2013

Escritura de archivos XML con JAXB

En un post anterior presenté el proceso que hay que seguir para leer archivos XML usando JAXB. En dicho post generé las clases necesarias y las usé de ejemplo.

Para cerrar el círculo adecuadamente, usando el mismo ejemplo, presento ahora una clase que permite escribir un archivo XML en disco.


import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.example.personas.Persona;
import org.example.personas.Personas;


public class SaveXMLwithJAXB {

 public static void main(String[] args) {

  JAXBContext ctx;
  
  Personas p = new Personas();
  Persona pItem = new Persona();
  pItem.setCiudad("Madrid");
  pItem.setEdad("20");
  pItem.setId("1");
  pItem.setNombre("Carlos");
  
  p.getPersona().add(pItem);
  
  try {
   ctx = JAXBContext.newInstance(Personas.class);
   Marshaller m = ctx.createMarshaller();
   
   File f = new File("C:/destino.xml");
   m.marshal(p, f);
   
  } catch (JAXBException e) {
   e.printStackTrace();
  }  
 }
}


Saludos.

sábado, 27 de abril de 2013

Bases de datos y Groovy.

El tratamiento de bases de datos en cualquier lenguaje es algo básico. A continuación presento un ejemplo sencillo realizado con Groovy. Hay que destacar que el manejo de bases de datos en java está muy conseguido gracias a frameworks como hibernate, jpa, etc. No obstante creo que conocer esta opción no está de más :D


Pasos previos

He creado un proyecto en Eclipse con el plugin comentado en el anterior post.

En postgres he creado una base de datos vacía. Le he dado acceso al usuario postgres/postgres para que pueda interactuar con la bd.

Como en cualquier programa, lo primero que tenemos que hacer es establer la conexión con la base de datos. El paquete groovy.sql contiene la clase Sql, que es la que nos permite operar contra bases de datos.

En concreto para obtener un conexión nos hace falta el método newInstance. Entre las implementaciones disponibles, la más cómoda en mi opinión es newInstance(url,user,password,driverClassName) throws SQLException, ClassNotFoundException

Los parámetros son evidentes:

url:
Es la url a la bd a la que nos vamos a conectar, en formato jdbc:subprotocol:subname
user:
Usuario de la base de datos con los permisos necesarios.
password:
La contraseña del usuario.
driverClassName:
Nombre del driver.

Esta clase devuelve una instancia de la conexión, con la que ya podremos comunicarnos. Lanza dos tipos de excepciones:

SQLException:
Cualquier tipo de error al interactuar con la base de datos, por ejemplo si el usuario no existe, o no tiene permisos, etc.
ClassNotFoundException:
Si no se ha podido obtener la clase del driver de conexión. Vamos, que no hemos incluido la librería necesaria o que no hemos puesto bien el nombre de la misma.

Obteniendo la conexión

Mi ejemplo va a ser muy sencillo. Voy a crear una clase llamada OperacionesBD.groovy. La cual en el constructor realiza la conexión, y mediante el resto de métodos interactúa con la base de datos.

De esta forma el constructor queda:


public OperacionesBD(String urljdbc, String usuario, String password) {
  super();
  this.connection = Sql.newInstance(urljdbc,usuario,password,Constantes.JDBC_DRIVER);
 }

siendo connection un atributo:

private Sql connection;

Insertando datos

Para ejecutar instrucciones la clase Sql dispone del método execute. Los dos siguientes métodos crean una tabla y insertan valores en ella:


 public void createTablePersons(){
  connection.execute(Constantes.TABLE);
 }



 public void insertValueTest(){
  connection.execute(Constantes.INSERT,[1,'Carlos','M']);
  connection.execute(Constantes.INSERT,[2,'Juan','M']);
  connection.execute(Constantes.INSERT,[3,'María','F']);
  connection.execute(Constantes.INSERT,[4,'Elena','F']);
  connection.execute(Constantes.INSERT,[5,'Pedro','M']);
  connection.execute(Constantes.INSERT,[6,'Rosa','M']);
 }


Mostrando u obteniendo datos

Con el método eachRow se puede iterar sobre los resultados de la consulta sql. El método showFemales imprime en consola todas las mujeres de la tabla person.

 public void showFemales(){
  connection.eachRow(Constantes.FEMALES, {
   println "id: ${it.id}, Nombre: ${it.name}"
   } );
 }

Por consola obtenemos:

 id: 3, Nombre: María
 id: 4, Nombre: Elena
 id: 6, Nombre: Rosa

El método getFemales devuelve una lista de maps con la consulta para realizar un tratamiento posterior.

 public List < Map < Integer,String > > getFemales(){
  List < Map > l = new LinkedList< Map >();
  connection.eachRow(Constantes.FEMALES, {
      Map < Integer,String > m = new HashMap < Integer,String >();
      m.put(it.id.toInteger(), it.name.toString());
      l.add(m);
      } );
  return l;
 }

Actualizando datos

La actualización de datos es bastante sencilla con executeUpdate:

 
public void update(int id, String newName){
  connection.executeUpdate(Constantes.UPDATE, [newName,id]);
 }

Pues esto es todo para este post. A continuación pongo las clases completas del ejemplo.

Fichero de constantes - Constantes.java


package es.test;

public class Constantes {

 protected static String JDBC_DRIVER = "org.postgresql.Driver";
 
 protected static String JDBC_URL = "jdbc:postgresql://localhost:5432/GroovyTest";
 
 protected static String DROP =  "DROP TABLE IF EXISTS  person";
 
 protected static String TABLE = "CREATE TABLE \"person\" "+
       "("+
        " id integer NOT NULL,"+
        " \"name\" character varying(30),"+
        " gender character(1),"+
        " CONSTRAINT pk PRIMARY KEY (id) "+
        ")";

 protected static String INSERT = "INSERT INTO person(id,name,gender)  VALUES (?,?,?)";

 protected static String FEMALES = "SELECT * FROM person WHERE gender = 'F'";
 
 protected static String UPDATE = "UPDATE person SET name=? WHERE id=?";
}

Lógica Groovy - OperacionesBD.groovy


package es.test

import groovy.sql.Sql;

public class OperacionesBD {

 
 private Sql connection;

 
 public OperacionesBD(String urljdbc, String usuario, String password) {
  super();
  
  this.connection = Sql.newInstance(urljdbc,usuario,password,Constantes.JDBC_DRIVER);
  connection.execute(Constantes.DROP);
 }
 

 
 public void createTablePersons(){
  connection.execute(Constantes.TABLE);
 }
  
 public void insertValueTest(){
  connection.execute(Constantes.INSERT,[1,'Carlos','M']);
  connection.execute(Constantes.INSERT,[2,'Juan','M']);
  connection.execute(Constantes.INSERT,[3,'María','F']);
  connection.execute(Constantes.INSERT,[4,'Elena','F']);
  connection.execute(Constantes.INSERT,[5,'Pedro','M']);
  connection.execute(Constantes.INSERT,[6,'Rosa','F']);
 }
 
 
 public void showFemales(){
  connection.eachRow(Constantes.FEMALES, {
      println "id: ${it.id}, Nombre: ${it.name}"
      } );
 }
 
 
 public List < Map < Integer,String > > getFemales(){
  List < Map > l = new LinkedList< Map >();
  connection.eachRow(Constantes.FEMALES, {
     Map < Integer,String > m = new HashMap < Integer,String >();
     m.put(it.id.toInteger(), it.name.toString());
     l.add(m);
     } );
  return l;
 }
 
 
 public void update(int id, String newName){
  connection.executeUpdate(Constantes.UPDATE, [newName,id]);
 }
 

}

Clase principal para probar el ejemplo - Main.java

package es.test;

import java.util.List;
import java.util.Map;

public class Main {

 /**
  * @param args
  */
 public static void main(String[] args) {

  OperacionesBD obd = new OperacionesBD(Constantes.JDBC_URL, "postgres", "postgres");
  
  obd.createTablePersons();
  
  obd.insertValueTest();
  
  obd.showFemales();
  
  List < Map < Integer,String > > l = obd.getFemales();
  
  for(Map < Integer,String > item:l){
   System.out.println(item.toString());
  }
  
  obd.update(6, "Rosa Rosae");
  
  obd.showFemales();  
 }
}

Y por último os comento que el código fuente completo se puede bajar de mi repositorio público de Git.


Referencias

La idea de este post surgió por un problemilla con Groovy, que solucioné gracias a este enlace.

Saludos.

martes, 26 de marzo de 2013

Lectura de archivos XML en Java. Uso de JaxB.

En mi anterior post sobre Groovy realicé un ejemplo que leía un archivo xml. En este post voy a leer casi el mismo archivo xml usando JAXB.

Archivo personas.xml (modificado), la diferencia es que a la etiqueta persona le voy a añadir un namespace, quedando el archivo así:


 

  
   1
   Carlos G. González
   Sin ley
   
  
  
   2
   M. Rajoy
   
   Mamoncete
  
  
   3
   ZP
   
   Engañabobos
  


JAXB son las siglas de Java API for XML Binding. Con JAXB podemos serializar objetos java y archivos xml. ¿Y esto qué significa? Pues que podemos tener una clase java con atributos y relacionar esa clase con un archivo xml. También podemos cargar los valores del archivo xml en dicha clase, con lo cual facilitamos mucho la lectura del mismo. En realidad la unión de la clase java no se va a realizar con el archivo xml que contiene los datos que queremos leer, sino con el archivo de definición del mismo, es decir, con el XSD (XML Schema Definition).

Ejecutando xjc

Como personas.xml fue un ejemplo creado a mano para el post mencionado, no tengo su archivo xsd. Eclipse permite crear este tipo de archivos de forma rápida, autocompletando, etc. Tras un par de minutos mi xsd quedaría:







 
  
 



 
  
  
  
  
 
 




Aunque yo para este ejemplo he picado el xsd a mano, existen herramientas que lo pueden generar a partir de clases java (eclipse) o de archivos xml (Microsoft tiene una que mola mucho). El libro Profesional Java JDK 6 de Anaya multimedia dedica varias páginas a este tema, por lo que lo recomiendo si alguien quiere profundizar más.

Ahora lo que vamos a hacer es crear las clases java asociadas al xsd. Hasta la versión 5 del jdk había que bajarse el paquete JWSDP, el cual contenía el ejecutable que nos hace falta para esta tarea. A partir de la versión 6 del jdk, dicho paquete se incluyó en el jdk, por lo que ya no es necesario bajarse nada independiente.

El ejecutable xjc es el que nos permite generar las clases a partir del archivo xsd. La opción –d permite indicar el directorio en el que queremos generar las clases, en mi caso “.\src “. El otro directorio escrito es la ruta hacia el archivo xsd.

En mi caso la sentencia es:

c:\Java(x86)\jdk1.6.0_21\bin\xjc.exe -d .\src src\xml\Personas.xsd

Existen otros parámetros para indicar el nombre de los paquetes a generar… pero no los he usado para no complicar el ejemplo.

Tras ejecutar la sentencia, en el paquete org.example.personas he obtenido cuatro clases:

  • ObjectFactory.java
  • package-info.java
  • Persona.java
  • Personas.java

Aún falta un paso para que la unión entre el xsd y las clases esté finalizada, y es que a veces el elemento raíz del xsd no queda marcado en las clases java. En mi caso hay que añadir la anotación @XmlRootElement a la clase Personas.java, quedando así:

@XmlRootElement (name="personas")
public class Personas {…}

El problema parece estar relacionado con información incompleta en los xsd o en los xml. Si se quiere obtener más información sobre este problema, en los siguientes links comentan la jugada:

Enlace a magicmonster.com.

Enlace a weblogs.java.net.

Usando las clases obtenidas

La siguiente clase es muy sencilla y muestra como se realizaría la lectura del xml:

import java.io.FileInputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.example.personas.Persona;
import org.example.personas.Personas;


public class ReadXMLwithJAXB {

 public static void main(String[] args) {

  JAXBContext ctx;
  try {
   ctx = JAXBContext.newInstance(Personas.class);
   Unmarshaller u = ctx.createUnmarshaller();
   
   Personas root = (Personas) u.unmarshal(new FileInputStream("C:/Users/Carlos/workspace/ReadXML/src/xml/personas.xml"));
   for(Persona p:root.getPersona()){
    System.out.println(p.getNombre());
   }
   
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

El resultado obtenido es:

Carlos G. González
M. Rajoy
ZP

Y una vez montado todo este tinglado, sinceramente, ¿no mola mucho más Groovy?

Saludos.

jueves, 7 de marzo de 2013

Api Reflection en Java. Ejemplo de uso

El otro día necesité usar reflection en java. Es el típico api que no uso muy a menudo, por lo que siempre tiro de documentación. Personalmente suelo recurrir al documento Introducción al API Reflection (Reflexión) de Java por Eneko González Benito (Keko) , alojado en JavaHispano. Antes tiraba de google, pero este documento está bastante bien para ser una introducción.

Aún así, pongo aquí un ejemplo rápido de uso, el cual es bastante intuitivo.


Código

Clase que vamos a usar de ejemplo.

class Persona{
  private String nombre;
  private String apellido;
  
  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;
  }
  @Override
  public String toString() {
   return "Persona [nombre=" + nombre + ", apellido=" + apellido + "]";
  }
}

Clase que va a instanciar a la anterior usando el API Reflection. Responde a la pregunta... ¿Cómo coño se hacía...? :D

public class ReflectionTest {
 
 public static void main(String[] args) {
  try {
   Class p = Class.forName("Persona");
   
   try {
    Persona pp = (Persona) p.newInstance();
    
    pp.setNombre("Carlos");
    pp.setApellido("G. González");
    
    System.out.println(pp.toString());
    
   } catch (InstantiationException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   }
   
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

Y el resultado:

Persona [nombre=Carlos, apellido=G. González]

Documentación relacionada

martes, 5 de marzo de 2013

Pasar en Solr de query en string a query en CmsSolrQuery


String solrQuery = "fq=type:MyType&sort=MyOtherField asc&rows=15";

Map < String, String[] > pm = CmsRequestUtil.createParameterMap(solrQuery);

CmsSolrQuery cmsSolrQuery = new CmsSolrQuery(getCmsObject(),pm);

String SOLR_INDICE_ONLINE = "Solr Online";
CmsSearchManager manager = OpenCms.getSearchManager();
CmsSolrIndex index = manager.getIndexSolr(SOLR_INDICE_ONLINE);
index.setRequireViewPermission(false);


CmsSolrResultList results = index.search(adminCmsObject, cmsSolrQuery,true);
 for (CmsSearchResource item: results){
  // TODO tratamiento
 }
    
   

viernes, 22 de febrero de 2013

Enviando emails con Java 6 y tomcat 7. DCH for MIME type multipart/mixed

Si la aplicación no puede enviar emails, mostrando un error tal como

Caused by: javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; 
 boundary="----=_Part_4_26855300.1361447126169"
 at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:877)
 at javax.activation.DataHandler.writeTo(DataHandler.java:302)
 at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1403)
 at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1745)
 at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:636)
 ... 50 more

La solución es copiar las librerías activation-1.1.1.jar y mail-1.4.1.jar a la carpeta lib de tomcat. Unos post de stackoverflow me ayudaron a dar con la solución, pero dando pistas sobre el error, sin dar solución concreta.

sábado, 9 de febrero de 2013

Hola mundo con Groovy

Tanto oir hablar de Groovy, y yo aún no había podido trabajar con él. Así que me he puesto manos a la obra a ver si hacía un hola mundo en condiciones.

¿Y Groovy que puñetas es? pues es un lenguaje de scripting para java que está disponible en la especificación JSR 241: The Groovy Programming Language.

Para poder usar Groovy con eclipse, hay que bajarse el plugin que se encuentra aquí.

La instalación se realiza como en todos los plugins de eclipse.

Instalación del plugin de Groovy en eclipse.

Lo primero que me ha tocado las narices de esta instalación es que después de instalar el plugin, tras reiniciar eclipse, he obtenido un bonito error Could not create the Java virtual machine.

Could not create the Java virtual machine. Después de instalar el plugin de Groovy en eclipse.

El problema es que tras la instalación del plugin, el eclipse.ini fue modificado. Concretamente se afectaron las líneas de la versión de java y las que referencian al directorio de java. ¡WTF!.

-Dosgi.requiredJavaVersion=1.6

La solución la encontré en este post.

Y mi pregunta, ¿por qué hizo esto el plugin?. A ver si alguien me lo aclara.

Pasado el susto, es hora de seguir con cosas más interesantes. Una vez instalado el plugin y corregido el error, voy a realizar un HolaMundo en groovy que leerá un archivo XML y mostrará en consola varios valores.

El Xml a leer:



  
   1
   Carlos G. González
   Sin ley
   
  
  
   2
   M. Rajoy
   
   Mamoncete
  
  
   3
   ZP
   
   Engañabobos
  

El primer paso será crear un proyecto groovy con una única clase de ejemplo (ReadXmlPersons.groovy).

package es.test

class ReadXmlPersons {

 static main(args) {
 
   
  def personas = new XmlSlurper().parse(new File("C:/compartido/personas.xml"))
  
  personas.persona.nombre.each( 
         { println it }
         )
 }

}

Si ejecutamos esta clase vemos que se muestra en consola lo que queremos.

Esto ha molado bastante, ya que la lectura del XML se ha simplificado mucho, por lo menos si lo comparamos con JAXB. ¿Y si lo adaptamos a nuestras necesidades?

Si modificamos la clase groovy anterior, podemos encapsular los valores en una lista. Después podemos hacer una clase java que lea esa lista y los muestre por consola.

La clase groovy quedaría:

package es.test

class ReadXmlPersons {

 public static List < String > getNombres(){
  
  List < String > l = new LinkedList< String >();
  
  def personas = new XmlSlurper().parse(new File("C:/compartido/personas.xml"))
  
  personas.persona.nombre.each(
         { l.add(it) }
         )
  
  return l;
  
 }
 
 static main(args) {
 }

}

Y la clase java:

package es.test;

import java.util.List;

public class Main {

 /**
  * @param args
  */
 public static void main(String[] args) {

  List< String > l =  ReadXmlPersons.getNombres();
  
  System.out.println(l);
  
 }

}

Bueno, pues yo creo que como HolaMundo está bastante bien. A ver si tengo un poco más de tiempo para darle caña a Groovy y hacer cosas más interesantes.

Saludos.

sábado, 19 de enero de 2013

Inicializando un hashmap en una clase de constantes

Esta semana he necesitado instanciar un Map en un fichero constantes. El truco no es mio, sino de esta fuente.


public static final Map < Integer, String >  MAPA= Collections.unmodifiableMap(
              new HashMap< Integer, String >(){
                   {
                    put(0,"");
                    put(1,"");
                   }
               });

martes, 8 de enero de 2013

Reiniciando el pool de conexiones de Oracle 11g a lo bestia

La semana pasada me encontré con un problema en el entorno de desarrollo, el pool de conexiones de Oracle. El problema en concreto es que el pool se llena demasiado rápido y hay que estar reiniciando Oracle constantemente. Por defecto Oracle admite 20 conexiones de pool, aunque este valor se puede incrementar.

¿Pero que pasa si hay varias máquinas de desarrollo (tomcat + eclipse) apuntando al mismo oracle? Pues que aunque subamos el pool al final del día vuelve a estar lleno y es necesario vaciarlo.

La forma bonita sería entrar como SYSDBA y ejecutar:

SYS as SYSDBA:
SQL> EXEC DBMS_CONNECTION_POOL.stop_pool;
SQL> EXEC DBMS_CONNECTION_POOL.start_pool;

Pero claro, ¿qué ocurre si no tenemos el password del usuario? ¿ o si no están los listener necesarios configurados? ¿o simplemente si queremos hacerlo "de otra forma" pero que sea más rápida?.

Mi solución ha sido un poco bestia, como matar moscas a cañonazos, pero efectiva.

Viendo los procesos del sistema

ps aux|grep oracle

me di cuenta de había procesos con la nomenclatura oracle+SID, en mi caso oracleorcl.

ps aux|grep oraceorcl

Por tanto se pueden matar procesos a mano (kill -9) para liberar pool. Pero claro, 20 ó 30 procesos a mano es un poco pesado. Googleando un poco y combinando post nos sacamos de la manga el comando:

ps aux|grep oracleorcl| awk '{print $2}' |xargs kill –KILL

y matamos a todos de golpe :D

Lo malo es que tiramos las conexiones activas (vamos, que podemos joder al personal), así que hay que avisar a los compañeros antes, pero es un mal menor.

Y la pregunta clave, ¿todo esto para qué? Pues simplemente ganamos un poco te tiempo y ya no es necesario reiniciar Oracle, y porque me divirtió investigar este tema, por supuesto ;D

Por cierto que este problema de pools al parecer sólo se da en java, ya que el driver de oracle no libera las conexiones pilladas.

saludos

lunes, 10 de diciembre de 2012

Problemas con WSGEN. Métodos duplicados en el wsdl

Hoy al generar un ws con wsgen, el wsdl me ha dado el warning:

cvc-identity-constraint.4.2.2: Duplicate key value [getCuentas] declared for identity constraint "message" of element 
 "definitions".

Lo que pasaba es que en el archivo wsdl, uno de los métodos me aparecía duplicado. Este problema estaba causado porque había definido la interfaz en la forma:

 @WebService(targetNamespace = "http://xxx.xxx.com", name = "XxxxWSInterface")
@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL)
public interface BcieWSInterface {

Casualmente me fijé que el método que salía por duplicado era el que devolvía Tipo_dato. En realidad no sé porqué estaba ese tipo declarado en la interfaz, creo que dejé a eclipse arreglar algo y me lo añadió.

Al arreglar la interfaz y dejarla sin el Tipo_dato

 @WebService(targetNamespace = "http://xxx.xxx.com", name = "XxxxWSInterface")
@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.LITERAL)
public interface BcieWSInterface {

y volver a generar se creó el wsdl correctamente :D En fin, una cagada mia, que menos mal que resolví en poco tiempo.

Saludos

jueves, 6 de diciembre de 2012

json.parse: bad control character in string literal

Hoy haciendo una aplicación con ajax el navegador me ha dado un error "json.parse: bad control character in string literal".
Imagen de error con el firebug

El error lo daba la llamada
json = $.parseJSON(string);
El problema era que yo estaba generando un objeto json desde java dentro de una stringbuilder, y una cadena contenía el carácter retorno de carro "\n". Buscando por internet encontré cientos de post que comentaban el problema y hacían perder el tiempo, pues daban soluciones que no funcionaban. En este en concreto se habla del api de json y se especifica que otros caracteres pueden fallar. Al final la solución era crear un objeto json desde java. Este es el trozo de código final en la jsp que llama el js.
Map obj = new HashMap();
obj.put("id", new Long(id_mensaje));
obj.put("cuerpo",mensaje.getCuerpo());
obj.put("fechaRecibido",MensajesUtil.formatDate(mensaje.getFechaEnvio()));
obj.put("usuarioOrigen",MensajesUtil.getName(mensaje.getUsuarioOrigen(), cms));
obj.put("usuarioOrigenId",mensaje.getUsuarioOrigen());
String jsonText = org.json.simple.JSONValue.toJSONString(obj);
out.println(jsonText);
Saludos.
Related Posts Plugin for WordPress, Blogger...