Desarrollé una aplicación con servicios web mediante el framework Apache CXF. Localmente funcionaba bien, lo probé mediante maven y el jetty-maven-plugin, con la ayuda de SoapUI para invocar a los servicios.

Pues cuando hice el deploy en un viejo Application Server de Oracle que utiliza OC4J, me arrojaba varios errores de que no encontraba ciertas clases (NoClassDefFoundException). El problema es que cuando ejecutas una aplicación en un contenedor, esta hereda el classpath de este. Así que,si OC4J cargó una versión vieja de log4J -por ejemplo- y utilizas una función disponible sólo en versiones más recientes, tendrás estos problemas.

Normalmente deberás haber incluído las dependencias en la carpeta WEB-INF/lib (ya sea mediante maven o manualmente). Para indicarle al contenedor que deseamos utilizar las librerías que hemos incluído en esta carpeta -desde la consola Enterprise Manager- al hacer el deploy desactiva la opción “Inherit parent application’s shared library imports”. Ó puedes crear un EAR que contenga tu WAR y agrega un archivo META-INF/orion-application.xml con el siguiente contenido

</pre>
<?xml version="1.0" encoding="UTF-8"?>
<orion-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd"
deployment-version="10.1.3.4.0" default-data-source="jdbc/OracleDS"
component-classification="external" schema-major-version="10"
schema-minor-version="0">

<imported-shared-libraries>
<remove-inherited name="*"></remove-inherited>
</imported-shared-libraries>

</orion-application>
<pre>

Fuentes:
logging – Oracle application server deployed application throwing an error – NoClassDefFoundError – Stack Overflow
.
http://docs.oracle.com/html/E13979_01/classload.htm#CIHJHADG

Anuncios

JAXB – Mapping interfaces

octubre 19, 2012

Unofficial JAXB Guide – Mapping interfaces — Java.net.

http://www.attivio.com/blog/56-java-development/636-configuring-java-interfaces-to-work-with-jaxb-and-web-services.html

Al abrir un reporte en Eclipse Juno (en el cual instale BIRT por separado) no me mostraba el diálogo para ingresar los parámetros. Me arrojaba el siguiente error:

HTTP ERROR: 500

Problem accessing /viewer/parameter. Reason: Plug-in “org.eclipse.birt.report.viewer” was unable to instantiate class “org.eclipse.birt.report.servlet.BirtEngineServlet”.

En el log me mostraba también la causa de la excepción:

NoClassDefFoundError: org.apache.axis.transport.http.AxisServlet

Después de mucho intentar y no encontrar una solución, decidí probar con otra instancia de Eclipse. Así que instale -descomprimí- Eclipse IDE for Java and Report Developers (Juno 4.2). Y con eso ya pude abrir el reporte e ingresar los parámetros.

Pero ahora tengo otro problema, me arroja la excepción

Cannot get the type for parameter: 1.

    org.eclipse.birt.report.data.oda.jdbc.JDBCException: Cannot get parameter type.

SQL error #1:Unsupported feature;

java.sql.SQLException: Unsupported feature

Al parecer este error ya fue arreglado, sólo tengo que esperar a que liberen la actualización 😦

Por lo pronto usare Eclipse Indigo (3.7.2) para modificar los reportes :S

Para obtener el tipo de dato de las propiedades de un objeto podemos utilizar la reflexión.

Por ejemplo si tenemos las siguientes clases

public class Libro{
String isbn;
String titulo;
Autor autor;
}
public class Autor{
String id;
String nombre;
Date fechaNacimiento;
}

Un método para obtener el tipo de dato de una propiedad, incluso propiedades anidadas, sería el siguiente

private Class<?> getPropertyType(Class<?> clazz,String property){
 try{
 LinkedList<String> properties=new LinkedList<String>();
 properties.addAll(Arrays.asList(property.split("\\.")));
 Field field = null;
 while(!properties.isEmpty()){
 field = FieldUtils.getField(clazz,properties.removeFirst(),true);
 clazz=field.getType();
 }
 return field.getType();
 }catch(Exception e){
 throw new RuntimeException(e);
 }
}

Lo invocaríamos de la siguiente manera

Class<?> type=getPropertyType(Libro.class,"autor.fechaNacimiento");
System.out.println(type.toString()); //imprime java.util.Date

Notesé el uso de la clase FieldUtils de la librería Apache Commons Lang, cuyo método getField busca el campo recursivamente en la jerarquía de las clase y sus interfaces. Para agregar la librería a nuestro proyecto hay que agregar la siguiente dependencia


<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.1</version>
 </dependency>

Para listar todas las propiedades de un objeto recursivamente podemos utilizar como ejemplo el código de la clase FieldUtils.

Con la librería Jackson podemos obtener un esquema JSON de cualquier objeto. El detalle es que los tipos de datos que obtendríamos serían sólo los permitidos en JSON (string, number, boolean, object, array, null).

ObjectMapper mapper=new ObjectMapper();
System.out.println(mapper.generateJsonSchema(Libro.class));

Fuentes:
http://stackoverflow.com/questions/11125409/find-the-field-type-using-jackson-json
http://stackoverflow.com/questions/3567372/access-to-private-inherited-fields-via-reflection-in-java
http://wiki.fasterxml.com/JacksonJavaDocs
http://jackson.codehaus.org/1.8.8/javadoc/org/codehaus/jackson/map/ObjectMapper.html#generateJsonSchema(java.lang.Class)
http://wiki.fasterxml.com/JacksonTreeModel

En orientación a objetos la herencia es, después de la agregación o composición, el mecanismo más utilizado para alcanzar algunos de los objetivos más preciados en el desarrollo de software como lo son la reutilización y la extensibilidad. A través de ella los diseñadores pueden crear nuevas clases partiendo de una clase o de una jerarquía de clases preexistente (ya comprobadas y verificadas) evitando con ello el rediseño, la modificación y verificación de la parte ya implementada. La herencia facilita la creación de objetos a partir de otros ya existentes e implica que una subclase obtiene todo el comportamiento (métodos) y eventualmente los atributos (variables) de su superclase.

En nuestros objetos es fácil implementar la herencia, basta con agregar la palabra clave extends y específicar la clase padre. Pero en una base de datos relacional no siempre queda claro cómo debemos implementar la herencia. Datanucleus (JDO) nos ofrece 4 opciones:

  1. Cuando cada clase tiene su propia tabla en la base de datos: new-table
  2. Cuando los campos de la clase padre son almacenados en la tabla del hijo: subclass-table
  3. Cuando los campos del hijo son almacenados en la tabla del padre: superclass-table
  4. A partir de JDO3.1, cuando cada clase tiene su propia tabla y esta contiene todos los campos (incluídos los de la clase padre): complete-table

Supongamos que tenemos la entidad Trabajador de la cual derivan las entidades Empleado y Meritorio. Nuestras clases quedarían de la siguiente manera:

public abstract class Trabajador {
   private String id;
   private String departmento;
}
public class Empleado extends Trabajador {
   private float salario;
}
public class Meritorio extends Trabajador {
   private Date fechaTermino;
}

Las tablas para las distintas estrategias que ofrece Datanucleus (JDO) serían:

new-table

Trabajador
id departamento
Empleado
idTrabajador salario
Meritorio
idTrabajador fechaTermino

subclass-table

Empleado
id departamento salario
Meritorio
id departamento fechaTermino

superclass-table

Trabajador
id departamento tipo salario fechaTermino

complete-table

Trabajador
id departamento
Empleado
id departamento salario
Meritorio
id departamento fechaTermino

Finalmente mostraré cómo anotar nuestras clases para implementar la estrategia superclass-table, que es el caso particular que se me presentó.

@PersistenceCapable
@Discriminator(strategy=DiscriminatorStrategy.VALUE_MAP, column="tipo")
public abstract class Trabajador {
   private String id;
   private String departmento;
}
@PersistenceCapable
@Inheritance(strategy=InheritanceStrategy.SUPERCLASS_TABLE)
@Discriminator(value="EMPLEADO")
public class Empleado extends Trabajador {
   private float salario;
}
@PersistenceCapable
@Inheritance(strategy=InheritanceStrategy.SUPERCLASS_TABLE)
@Discriminator(value="MERITORIO")
public class Meritorio extends Trabajador {
   private Date fechaTermino;
}

Fuentes:

http://www.datanucleus.org/products/datanucleus/jdo/orm/inheritance.html#superclasstable
http://www.datanucleus.org/products/accessplatform/jdo/orm/inheritance.html
https://developers.google.com/appengine/docs/java/datastore/jdo/dataclasses#Inheritance
http://es.wikipedia.org/wiki/Herencia_(programaci%C3%B3n_orientada_a_objetos)

Uitlizo Jackson para serializar objetos al formato JSON y enviarlos al cliente mediante servicios REST. A veces olvido, sobretodo al inicio de un proyecto, que por default Jackson intenta serializar mis objetos con un BeanSerializer. Esto significa que mi clase debe ser un JavaBean, es decir, tener un constructor sin argumentos y ‘getters’ y ‘setters’ para las propiedades que me interesa sean incluídas en la respuesta. Si tu clase no cumple estas condiciones, te arrojará la siguiente excepción:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class mx.com.apestudio.videohaus.server.model.Video and no properties discovered to create BeanSerializer

Recientemente actualizamos nuestro servidor de aplicaciones -JBoss- a la versión 7.1.0. Ésta versión tiene muchisímas mejoras en comparación con la que teníamos. El problema es que la estructura del servidor sufrió varios cambios que debes tomar en cuenta si quieres migrar tus aplicaciones de JBoss AS5 o AS6 a JBoss AS7.

A nosotros nos aparecía un error parecido al siguiente:

Class Path entry ridl.jar in “/content/tsj.web.os.war/WEB-INF/lib/jurt-2.3.0.jar”

La librería que menciona, jurt-2.3.0.jar, es una dependencia de la librería JODConverter que utilizamos para convertir documentos RTF a PDF.
El problema es que dicha librería contiene la siguiente línea en el archivo de manifesto -indicando que deben cargarse ciertas librerías para su correcto funcionamiento-

Class-Path: ridl.jar unoloader.jar ../../lib/ ../bin/

La solución al error es remover dicha línea. No olvides dejar una línea en blanco al final del archivo despúes de modificarlo.