Buscar
Social
Ofertas laborales ES
miércoles
mar162011

Vídeo resumen del Spring I/O 2011

Hemos publicado el vídeo resumen del Spring I/O que celebramos en Madrid el pasado febrero. Estamos trabajando para editar los vídeos de las charlas y subirlos pronto a Parleys.com.

Por lo mientras, podéis daros una idea de como ha ido el evento con el vídeo. Muchas gracias a todos los asistentes y a los patrocinadores.

Vídeo resumen Spring I/O 

miércoles
mar162011

El JSR 342 (Java EE 7) ha sido aprobado por el Java Community Process

El JSR 342 (la especificación que definirá Java EE 7) ha sido aprobado por el Java Community Process con un 100% de votos positivos (ninguna atención, ningún voto negativo). De entre los votantes, sólo IBM ha realizado un comentario (el ya típico en los últimos años) afirmando que su voto positivo se debe a los méritos técnicos de la especificación, y no a las condiciones de licenciamiento (con las cuales no está de acuerdo).
miércoles
mar162011

Microsoft anuncia Internet Explorer 9

Desde hace unas pocas horas, Internet Explorer 9 está disponible para descarga. Esta nueva versión mejora considerablemente el soporte de características de HTML 5 respecto a su predecesor. Además, es más ligero y rápido que su predecesor y tiene una interfaz más simple inspirada en la interfaz de Chrome.


Internet Explorer 9 obtiene una puntuación de 95% en el test Acid 3. Cuenta con un JIT de JavaScript que mejora considerablemente su rendimiento. También cuenta con aceleración por hardware para la reproducción de video en formato H.264.

 

Internet Explorer 9 está disponible para Windows Vista y 7, pero no para Windows XP. Y parece ser que Microsoft no tiene intención de sacar una versión para este sistema operativo. 


Esta versión de Internet Explorer ve la luz dos años después que su predecesor, Internet Explorer 8. Esto sucede en un momento en el cual Chrome se actualiza continuamente y de modo transparente para el usuario (primer navegador web en optar por esta opción) y en el que FireFox ya ha dicho que su versión 4.0 (que está a la vuelta de la esquina) será la "última gran versión" del navegador. A partir de ese momento seguirán el modelo de Chrome de actualizaciones continuas y transparentes para el usuario. ¿Cuando hará Internet Explorer lo propio?

 

 

martes
mar152011

Java Easy Persistent Layer - JEPLayer

JEPLayer es una sencilla pero poderosa API encima de JDBC basada en listeners que controlan opcionalmente el ciclo de vida de un proceso JDBC en múltiples puntos. 

http://jeplayer.googlecode.com

JEPLayer es de código abierto con licencia Apache v2

¿Por qué otra herramienta basada en JDBC?

JEPLayer nació para proporcionar

    1. Una API sencilla para evitar las tareas tediosas de JDBC
    2. Varios listeners opcionales para personalizar completamente el ciclo de vida de la persistencia de JDBC
    3. Métodos para construir DAOs simples y complejos
    4. Una manera muy sencilla, automática, configurable y libre de errores para demarcar las transacciones
    5. No sustituye a JDBC, en lugar de ésto, los objetos JDBC están expuestos para cuando sea necesario
    6. Siempre usando PreparedStatement, siempre seguro
    7. Los objetos PreparedStatement son automáticamente almacenados en caché y reutilizados

¿Qué es diferente en JEPLayer?

JEPLayer es más sencillo que JdbcTemplate de Spring y tiene una potencia similar, el ciclo de vida persistente puede ser totalmente configurable, ofreciendo más puntos de intercepción, no trata de sustituir al JDBC y las transacciones JDBC están implícitas.

JEPLayer es programático con toda la libertad y capacidad de reutilización que eso supone en lugar del camino declarativo que ha tomado iBatis/MyBatis.

JEPLayer permite sacar el máximo partido de la base de datos sin pérdida de rendimiento y sin pérdida de control típico de los ORMs de persistencia transparente.

Ejemplo de llamadas sencillas (MySQL)

DataSource ds = ...;
JEPLDataSource jds = new JEPLBoot().createJEPLDataSource(ds);
JEPLDAL dal = jds.createJEPLDAL();
dal.executeUpdate("DROP TABLE IF EXISTS PERSON");
dal.executeUpdate("DROP TABLE IF EXISTS COMPANY");
dal.executeUpdate("DROP TABLE IF EXISTS CONTACT");
dal.executeUpdate(
"CREATE TABLE CONTACT (" +
" ID INT NOT NULL AUTO_INCREMENT," +
" EMAIL VARCHAR(255) NOT NULL," +
" NAME VARCHAR(255) NOT NULL," +
" PHONE VARCHAR(255) NOT NULL," +
" PRIMARY KEY (ID)" +
")" +
"ENGINE=InnoDB"
);

Un sencillo DAO

public class Contact 
{
protected int id;
protected String name;
protected String phone;
protected String email;
public Contact(int id, String name, String phone, String email)
{
this.id = id;
this.name = name;
this.phone = phone;
this.email = email;
}
public Contact() { }
/* ... gets and sets ... */
}
public class ContactDAO extends JEPLDAOBase implements JEPLResultSetDAOListener
{

public ContactDAO(JEPLDataSource ds)
{
super(ds);
}

@Override
public void setupJEPLResultSet(JEPLResultSet jrs, JEPLTask task) throws SQLException
{
}

@Override
public Contact createObject(JEPLResultSet jrs) throws SQLException
{
return new Contact();
}

@Override
public void fillObject(Contact obj, JEPLResultSet jrs) throws SQLException
{
ResultSet rs = jrs.getResultSet();
obj.setId(rs.getInt("ID"));
obj.setName(rs.getString("NAME"));
obj.setPhone(rs.getString("PHONE"));
obj.setEmail(rs.getString("EMAIL"));
}

public void insert(Contact contact)
{
int key = insert("INSERT INTO CONTACT (EMAIL, NAME, PHONE) " + "VALUES (?, ?, ?)",
                 int.class, contact.getEmail(), contact.getName(), contact.getPhone());
contact.setId(key);
}

public void update(Contact contact)
{
executeUpdateOne("UPDATE CONTACT SET EMAIL = ?, NAME = ?, PHONE = ? WHERE ID = ?",
              contact.getEmail(), contact.getName(), contact.getPhone(), contact.getId());
}

public boolean delete(Contact obj)
{
return deleteById(obj.getId());
}

public boolean deleteById(int id)
{
// Only if there is no "inherited" rows or declared ON DELETE CASCADE
return executeUpdateZeroOrOne("DELETE FROM CONTACT WHERE ID = ?", id);
}

public int deleteAll()
{ // Only if "inherited" tables are empty or declared ON DELETE CASCADE
return executeUpdate("DELETE FROM CONTACT");
}

public List selectAll()
{
return selectList("SELECT * FROM CONTACT");
}

public JEPLResultSetDAO selectAllResultSetDAO()
{
return selectResultSetDAO("SELECT * FROM CONTACT");
}

public Contact selectById(int id)
{
return selectOneById("SELECT * FROM CONTACT WHERE ID = ?", id);
}

public List selectByNameAndEMail(String name, String email)
{
return selectList("SELECT * FROM CONTACT WHERE NAME = ? AND EMAIL = ?", name, email);
}

public int selectCount()
{
return selectOneRowAndField("SELECT COUNT(*) FROM CONTACT", int.class);
}
}

 

Añadimos un método más complejo a este DAO para proporcional limitación "al vuelo" del número de resultados

    public List selectAllStatementListenerMaxRows(final int maxRows)
{
JEPLPreparedStatementListener> listener = new JEPLPreparedStatementListener>()
{
public void setupJEPLPreparedStatement(JEPLPreparedStatement jstmt, JEPLTask> task) throws SQLException
{
PreparedStatement stmt = jstmt.getPreparedStatement();
int old = stmt.getMaxRows();
stmt.setMaxRows(maxRows);
try
{
List res = task.exec();
}
finally
{
stmt.setMaxRows(old); // Restore
}
}
};
return selectList("SELECT * FROM CONTACT",listener);
}

 

Otro método para cargar resultados entre dos filas especificadas por índices

 

    public List selectAllExplicitResultSetListenerRange(final int from,final int to)
{
JEPLResultSetDAOListener listener = new JEPLResultSetDAOListener()
{
@Override
public void setupJEPLResultSet(JEPLResultSet jrs, JEPLTask task) throws SQLException
{
ResultSet rs = jrs.getResultSet();
rs.absolute(from);
}

@Override
public Contact createObject(JEPLResultSet jrs) throws SQLException
{
return new Contact();
}

@Override
public void fillObject(Contact obj, JEPLResultSet jrs) throws SQLException
{
ResultSet rs = jrs.getResultSet();
obj.setId(rs.getInt("ID"));
obj.setName(rs.getString("NAME"));
obj.setPhone(rs.getString("PHONE"));
obj.setEmail(rs.getString("EMAIL"));
int row = rs.getRow(); // Now returned value is the "next row"
if (row == to) jrs.stop();
}
};
return selectList("SELECT * FROM CONTACT",listener);
}

Agrupando acciones persistentes (el Connection es obtenido al principio a partir del DataSource y liberado al final).

    final JEPLDataSource jds = ...;
JEPLTask task = new JEPLTask()
{
@Override
public Contact exec() throws SQLException
{
Contact contact = new Contact();
contact.setName("A Contact object");
contact.setPhone("9999999");
contact.setEmail("contact@world.com");
ContactDAO dao = new ContactDAO(jds);
dao.insert(contact);
Contact contact2 = dao.selectById(contact.getId());
return contact2;
}
};
Contact contact = jds.exec(task);

Por supuesto con un simple boolean (autoCommit=false) el mismo código es ejecutado dentro de una transacción JDBC

La transacción es automaticamente "commited" al final o "rollbacked" en caso de error.

    final JEPLDataSource jds = ...;
JEPLTask task = new JEPLTask()
{
@Override
public Contact exec() throws SQLException
{
...
}
};
Contact contact = jds.exec(task, false );

Puede ser que necesites un mayor control del ciclo de vida de la transacción

    JEPLDataSource jds = ...;
JEPLTask task = new JEPLTask() { ... };
jds.exec(task,new JEPLConnectionListener()
{
public void setupJEPLConnection(JEPLConnection con,JEPLTask task) throws SQLException
{
con.getConnection().setAutoCommit(false); // transaction
try
{
task.exec();
con.getConnection().commit();
}
catch(Exception ex)
{
con.getConnection().rollback();
                    throw new SQLException(ex);
}
}
}
);

A veces puede que necesites disponer de un objeto similar al ResultSet pero que devuelva objetos del modelo cargados bajo demanda de la base de datos a medida que iteramos

Añadiendo a ContactDAO este método:

public JEPLResultSetDAO selectAllResultSetDAO() 
{
return selectResultSetDAO("SELECT * FROM CONTACT");
}

Ahora este código es posible (dentro de una JEPLTask):   

    ContactDAO dao = ...; 
JEPLResultSetDAO resSetDAO = dao.selectAllResultSetDAO();
if (resSetDAO.isClosed()) throw new JEPLException("WRONG");
while(resSetDAO.next())
{
Contact contact = resSetDAO.getObject();
System.out.println("Contact: " + contact.getName());
}
// Now we know is closed
if (!resSetDAO.isClosed()) throw new JEPLException("WRONG");

 

Afortunadamente JEPLResultSetDAO es también un List que carga los objetos también bajo demanda

    ContactDAO dao = ...; 
List resSetDAO = dao.selectAllResultSetDAO();
if (((JEPLResultSetDAO)resSetDAO).isClosed()) throw new JEPLException("WRONG");
for(Contact contact : resSetDAO) // Uses Iterator
{
System.out.println("Contact: " + contact.getName());
}
// Now we know is closed
if (!((JEPLResultSetDAO)resSetDAO).isClosed()) throw new JEPLException("WRONG");

 

El Manual de Referencia  contiene un ejemplo de herencia de tres clases basado en tres tablas sin atributo discriminador.

 

Aunque se me ocurren más ideas, la librería por ahora se quedará así, tengo cosas más importantes que hacer :)

Que la disfruteis.

 

martes
mar152011

Sculptor 2.0

Sculptor es un framework que combina conceptos de diseño "Domain-Driven" y DSL para intentar incrementar la productividad de los desarrolladores Java. Está construido sobre frameworks Java como JPA, Hibernate y Spring Framework y han construido un plugin que integra el framework con Eclipse.


Sculptor está bastante orientado a crear aplicaciones CRUD de un modo simple y rápido. Por ejemplo, esto es todo el código DSL que  necesitamos para tener una aplicación CRUD completa de "planetas":

Application Universe {   
 basePackage=org.helloworld
    Module milkyway {        
       Entity Planet {          
         scaffold            
         String message          
 }    
   }
 }

 


Aquí tenéis un video introductorio al framework. Y aquí está el tutorial del hola mundo. Recientemente han liberado la versión 2.0 de Sculptor, con soporte para REST y Spring Remoting, entre otras nuevas características. El framework se distribuye bajo licencia Apache 2.0. 

 

¿Alguno de vosotros conocía Sculptor? ¿Alguien se anima a hacer una comparativa con OpenXava