Java – Log4J xml vs properties configuration

Para saber cuáles son las ventajas y desventajas entre un formato y otro, puedes ver la siguiente discusión

http://stackoverflow.com/questions/1256835/why-chose-xml-over-properties-files-for-log4j-configuration

Desde mi punto de vista, deberíamos usar el formato XML.

Aquí dejo un ejemplo de un archivo de configuración properties y su equivalente en xml que encontré en esta página.

log4j.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<!-- A1 is set to be a ConsoleAppender -->
 <appender name="A1" class="org.apache.log4j.ConsoleAppender">
 <!-- A1 uses PatternLayout -->
 <layout class="org.apache.log4j.PatternLayout">
 <param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n"/>
 </layout>
 </appender>

<root>
 <!-- Set root logger level to DEBUG and its only appender to A1 -->
 <priority value ="debug" />
 <appender-ref ref="A1" />
 </root>

</log4j:configuration>

Java – Obtener el tipo de dato de las propiedades de un objeto

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

Java – Archivo de propiedades con valores multilínea

En java puedes utilizar un archivo de propiedades para almacenar información de configuración de la aplicación o cosas por el estilo. El formato de dicho archivo, con extensión .properties, es el siguiente:

variable-1=valor-1
variable-2=valor-2
variable-3=valor-3

Donde cada línea nos representa una variable y su valor.

Hay algunos valores que son más legibles cuando utilizamos saltos de línea, para ello tienes que utilizar la diagonal invertida ‘\’ (backslash) como lo muestro en el siguiente ejemplo:

jdbc.url=jdbc:oracle:thin:@ (DESCRIPTION = \
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172..0.0.1)(PORT = 1521)) \
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.0.0.2)(PORT = 1521)) \
    (LOAD_BALANCE = yes) \
    (CONNECT_DATA = \
      (SERVER = SHARED) \
      (SERVICE_NAME = mydomain.com) \
      (FAILOVER_MODE = \
(TYPE = SELECT) \
(METHOD = BASIC) \
(RETRIES = 180) \
(DELAY = 5) \
      ) \
    ) \
  )

Fuentes:
http://www.rgagnon.com/
http://www.java2s.com/

SmartGwt – RestDataSource Update

Estoy tratando de utilizar servicios REST en un proyecto. Como también utilizo SmartGwt, es bueno saber que tengo disponible la clase RestDataSource.
Cabe aclarar que cómo es un proyecto nuevo, he creado mis servicios REST para que funcionen con esta clase. Así, sólo tengo que indicarle la URL y el formato de mi servicio para que se enlacen los datos.
El problema que tuve fue en el servidor, ya que la clase RestDataSource envía los cambios en 2 atributos: «data» que contiene solo las propiedades modificadas y «oldValues» con todasl las propiedades antes de los cambios. Debido a que serializó estos atributos a un Objeto, necesito que esten «mezclados». Estuve buscando como combinar las propiedades de 2 objetos de la misma clase en Java (lado del servidor) pero no tuve éxito. Lo siguiente que intenté fué combinar las propiedades en el lado del cliente (javascript) y lo logré con ayuda de un ejemplo que utiliza la clase GwtRpcDataSource.
El código para combinar las propiedades de 2 objetos en javascript (GWT) es el siguiente:

@Override
protected Object transformRequest(DSRequest dsRequest) {
 if(dsRequest.getOperationType()==DSOperationType.UPDATE){
 JavaScriptObject newData=JavaScriptObject.createObject();
 JavaScriptObject oldValues=dsRequest.getAttributeAsJavaScriptObject("oldValues");
 JSOHelper.apply(oldValues, newData);
 JavaScriptObject data=dsRequest.getData();
 JSOHelper.apply(data, newData);
 dsRequest.setData(newData);
 }
 return super.transformRequest(dsRequest);
}