Para cualquier tipo de URI el formato es:
protocol://usuario:clave@server:port/path
Ejemplos
http://user:clave@xxx.com/paginaSegura
ftp://user:clave@xxx.com/directorioSeguro
http://user:clave@xxx.com/paginaSegura
Para cualquier tipo de URI el formato es:
protocol://usuario:clave@server:port/path
Ejemplos
http://user:clave@xxx.com/paginaSegura
ftp://user:clave@xxx.com/directorioSeguro
http://user:clave@xxx.com/paginaSegura
Adhoc es el nombre del sistema de creación de informes directamente por el usuario final en cuatro pasos.
Modificación de la presentación:
El primer punto se cambiar los css $PENTAHO_HOME$/adhoc/styles:
Las imágenes está en en $PENTAHO_HOME$/adhoc/images
El html principal es el siguiente waqr.html. Sobre éste los js modifican en tiempo de ejecución su contenido, mostrando y ocultando DIVs o cambiando el contenido de los DIVs.
Los js, están agrupados de la siguiente manera contraoller, modelo y ui. Modelo-vista- controlador y un paquete extra (common) donde hay utilidades auxiliares como : leer xml, tratar cadenas, mostrar por pantalla,….
Gran parte del texto que aparece se puede configurar en el archivo message_strings.js del directorio en $PENTAHO_HOME$/adhoc/js/ui/messages/nls/
Recomendaciones:
Si sólo se quiere cambiar un poco la presentación sólo es necesario modificar los css, images y message_strings.js.
Modificación de la presentación de Pentaho:
El primer punto se cambiar los css.
También se puede modificar el estilo el menú
Para modificar el contenido del menú se necesario modificar los archivos:
Para añadir un idioma hay que ir a
Como última opción se puede modificar la plantilla general %PENTAHO_HOME%/jsp/index.jsp y otros archivos para la administración de pentaho.
Para configurar el datasource de una aplicación web para el Tomcat 5.5 desde eclipse.
Configurar server.xml
<Resource name="jdbc/miDS" auth="Container" type="javax.sql.DataSource"
maxActive="20" maxIdle="5" maxWait="10000"
username="sa" password="" driverClassName="org.hsqldb.jdbcDriver"
url="jdbc:hsqldb:hsql:localhost:1666"/>

configurar server.xml
Configurar web.xml
<resource-ref>
<res-ref-name>jdbc/miDS</res-ref-name>
<res-type>javax.sql.DataSource </res-type>
<res-auth> container </res-auth>
</resource-ref>
Acceder al datasource desde el código
InitialContext jndiContext = new InitialContext();
DataSource ds =
(DataSource)jndiContext.lookup("java:comp/env/jdbc/miDS");
Configurar el resource se puede hacer en otros sitios, pero también hay que configurar eclipse para decirle de dónde coje la información de la configuración del tomcat.
Mientras la gente de JUnitPerf no desarrolle una nueva versión de su extensión de JUnit, compatible con los test desarrollados en JUnit 4 con el JDK 1.5, la extensión JUnitPerf no funciona correctamente con este tipo de test.
El equipo de Junit ya vió venir este problema y creó un adaptador para ayudar a la integración de estas extensiones mientras no se actualicen.
A continuación pongo un ejemplo de cómo se crearía una suite para JUnitPerf teniendo en cuenta que MyTest está desarrollado con JUnit 4, anotations, etc.
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new LoadTest(new JUnit4TestAdapter(MyTest.class),
1 /* user */, 10 /* iterations */));
suite.addTest(new LoadTest(new JUnit4TestAdapter(MyTest.class),
10 /* user */, 1 /* iterations */));
return suite;
}
Si no conoces JUnitPerf y quieras hacer pruebas de carga y rendimiento en tus test de unidad, míratelo.
Por los posibles comenarios sobre JUnitPerf y si es relevante hacer pruebas de carga en test de unidad, quiero comentar que para mi no son especialmente válidos estos test y mucho menos si lo utilizas para medir tiempos o hacer pruebas de que una determinada funcionalidad responde en X segundos, pero si lo que quieres hacer es comprobar que una determinada funcionalidad, se ejecuta correctamente cuando es accedida por N usuarios, JUnitPerf es una buena herramienta para ello.
Como me convenció bastante Grails he dedido seguir trabajando un poco en la aplicación.
He añadido un campo autocomplete y un calendario para las fechas.
He usado el plugin richui y en total he dedicado 3 horas.
A mejorar:
Localización de los mensajes y formatos. Sería interesante que se completara el plugin con los mensajes de otros idiomas.
En general creo que los tags que ofrece este plugin se pueden mejorar, pero tiempo al tiempo.
Referencias:
Documentación RichUI plugin : http://docs.codehaus.org/display/GRAILS/RichUI+Plugin
Otros plugins : http://docs.codehaus.org/display/GRAILS/Plugins
Grails usa un sistema denominado “convention” que yo traduciría por “acuerdo”, en vez de usar el clásico sistema de configuración con XML y esta es una de sus claras ventajas a la hora de conseguir un rápido desarrollo. Además usa Groovy, un lenguaje de scripting basado en Java, lo cual reduce la cantidad de código necesaria.
Pero no sólo eso, hay otros elementos que ayudan a un desarrollo rápido. El sistema de plugins permite entre otras cosas, instalar un plugin usando simplemente el comando “grails install-plugin XXX” y empezar a utilizarlo sin tener que configurar nada. Hay plugins para muchas cosas, por ejemplo RIA, entendido como usar librerías javascript para mejorar la presentación o hacer llamadas AJAX, también puedes incorporar jasper reports o hacer la presentación con FLEX.
También es muy interesante el uso de plantillas, aunque lo permite, no es necesario generar todo el código necesario para un mantenimiento, o CRUD como dicen algunos, puedes tenerlo definido como plantillas tanto para archivos groovy (controlador) como para archivos gsp (vista).
Para aprender he decido hacer una pequeña aplicación de gestión de las compras de casa. Básicamente es una aplicación para mantener 7 tablas, una de ellas con una relación maestro detalle.
Para desarrollar la aplicación completa he necesitado 4 horas incluyendo en este tiempo la instalación de Grails. Lo que da una medida de la mejora de productividad que conlleva.
Cosas a mejorar:
Facilitar el desarrollo en IDE: Me refiero a syntax highlight, autocompletado, refactor y esas cosas. Hay un plugin para eclipse pero aún le falta mucho. IntelliJ IDEA puede que tenga un entorno de desarrollo mejor para Groovy pero no lo he probado.
Mejorar el control de errores: Como pasa en muchos frameworks los mensajes de error no son claros ni completos o incluso despistan más que ayudan.
Riesgos:
Se trata de un framework muy joven, la versión 1.0 es de febrero de 2008, lo cual implica que es muy dinámico, que hay cosas que pueden cambiar en el futuro o que tu aplicación o tu plugin deje de funcionar dramáticamente si actualizas la versión por un bug del framework. Quiero añadir que este tipo de cosas ha pasado al actualizar a Grails 1.0.2.
Referencias:
Grails : http://grails.org/
Documentación Grails : http://dist.codehaus.org/grails/
Tutorial IBM : http://www.ibm.com/developerworks/java/library/j-grails01158/index.html
Groovy : http://groovy.codehaus.org/
A continuación se describe este procedimiento siguiendo el orden numérico de las distintas fases y los posibles caminos alternativos:
Componente.submittedValue –> Componente.value –> Bean.attribute
El atributo ‘immediate’ de los componentes de un formulario está presente en la mayoría de las fases del ciclo de vida.
Ya en la primera fase del ciclo se comprueba el valor de dicho atributo. Si vale true, el ciclo avanza hasta la tercera fase, saltándose las validaciones pertinentes. En caso contrario, se continúa el ciclo normal hacia la fase 2.
Es importante señalar en este punto que si ‘immediate’ no se indica su valor es false, ya que así está definido en la declaración de atributos de JSF. Y además es importante saber que el hecho de asignarle el valor true implica no tener acceso a los valores de los campos del formulario así como a los errores que se hubieran producido.
Componente: elemento que forma parte del formulario y provee funcionalidades para interactuar con el usuario. Puede ser de diferentes tipos (caja de texto, botón, control de selección…) y el usuario “completa” el formulario a través de su modificación.
Converter: se utiliza cuando es necesario convertir el dato introducido por el usuario al tipo apropiado. Por ello hay que indicar como nombre el de una clase bean que implemente la interfaz Converter.
Evento: acción que queremos que se produzca al cambiar el valor del componente. Por ejemplo, el caso de un selectOneMenu cuando cambiamos la opción marcada del menú desplegable. Solemos indicar estas acción a través de los atributos ‘onchange’, ‘onblur’, ‘onclick’, etc. en el código jsp.
Evento de acción: acción declarada en el atributo ‘action’ de un componente. A cada botón que exista en una página le corresponde una acción (no necesariamente distinta a las demás), y que nosotros solemos denominar con los nombres “doXxxAction” o “goXxxAction”. Por ejemplo: doActualizarAction(), goAtrasAction().
Nota: JSF entiende ‘evento’ como cualquier acción realizada por el usuario. Por ejemplo: pulsar en un botón, hacer clic sobre un link, escribir en un inputText, etc. Como se lee un poco más arriba, nosotros distinguimos entre ‘eventos’ propiamente dichos, y ‘eventos de acción’.
SubmittedValue: valor introducido por el usuario en el formulario.
Validator: responsable de asegurar que el valor ingresado por un usuario es aceptable. Uno o más validadores pueden ser asociados con un solo componente y se definen en clases Java independientes.
Mi agradecimiento a Inma Molina por la edición de este artículo y el diseño de la imagen.
Spring 2.0 introduce dos nuevos scope para quienes desarrollamos aplicaciones web.
Esta nueva funcionalidad simplifica un trabajo tan arduo como la gestión de auditoría.
Para que el ejemplo quede más claro, como gestión de auditoría vamos a enteder que se indique en el log qué usuario ha realizado una determinada acción.
Realizar esta tarea sin Spring, consistiría principalmente en pasar un nuevo argumento a cada uno de los métodos de la lógica de negocio inidicando el usuario.
Existen otras formas que no voy a discutir, como poner la información en ThreadLocal.
A continuación, indicaré los pasos para crear un bean de sessión en Spring y hacer que un servicio singleton lo reciba, y de esta manera pueda hacer log del usuario y la acción.
Configurar web.xml (fragmento)
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Crear el bean con la información del usuario
package sadiel.rrhhsas.model.comun.objnegocio;
public class UsuarioSession implements Serializable, IUsuario {
String usuario; // Código del usuario
// getters y setters
// ..
}
Crear el servicio
package sadiel.rrhhsas.model.adm.usu.service.impl;
public class UsuarioServiceImpl implements IUsuarioService {
IUsuario usuario; //Usuario de session
// the logger for this class
private Log logger = LogFactory.getLog(this.getClass());
/**
* Valida a un usuario a partir de su usuario y su clave.
* Introduce el usuario en la session para que sea accesible por otros servicios
* @param clogin
* el usuario que usamos
* @param cclave
* la clave que usamos
* @return true
*/
public boolean login(String clogin, String cclave)
throws UsernameNotExistException {
// Valido al usuario
// ...
// Informo en el usuario de sessión el código del usuario conectado
usuario.setUsuario(user.getCUsuario());
return true;
}
/**
* @see IUsuarioService#actualizar(Object o)
*/
public void actualizar(Object o) {
this.logger.debug("El usuario "+usuario.getCUsuario() +
" modifica el objeto "+o);
// Resto del servicio
// ..
}
/**
* Set the user in session
* It will be used by the Spring IOC container.
* @param usuario the usuario to set
*/public void setUsuario(IUsuario usuario) {
this.usuario = usuario;
}
}
Configurar applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="Usuario"
class="sadiel.rrhhsas.model.comun.objnegocio.UsuarioSession"
scope="session">
<aop:scoped-proxy/> <!-- Esto hay que incluirlo en los beans
con scope="session" si los queremos
utilizar en otros bean singleton -->
</bean> <bean id="iUsuarioService"
class="sadiel.rrhhsas.model.adm.usu.service.impl.UsuarioServiceImpl" >
<property name="usuario">
<ref bean="Usuario" />
</property>
</bean></beans>Por supuesto si quisieramos que todos los servicios recibieran al usuario, lo que habría que hacer es definir un servicio abstracto y hacer que todos los servicios fueran hijos de este, pero de eso bloquearé otro día.Y eso es todo, algún comentario sería apreciado.
En este ejemplo nos vamos a concentrar en la configuración del SessionFactory de Hibernate y las diferentes alternativas que nos ofrece el sistema de abstracción de recursos para simplificar la configuración y mantener distintas configuraciones.
A continuación veamos una configuración básica del sessionFactory de Spring para Hibernate con conexión a Oracle.
<bean id=“sessionFactory”
class=“org.springframework.orm.hibernate3.LocalSessionFactoryBean”>
<property name=“dataSource”>
<ref bean=“dataSource” />
</property>
<property name=“hibernateProperties”>
<props>
<prop key=“hibernate.dialect”> org.hibernate.dialect.Oracle9Dialect
</prop>
<prop key=“hibernate.show_sql”> false</prop>
<prop key=“hibernate.cglib.use_reflection_optimizer”> true
</prop>
</props>
</property>
<property name=“mappingResources”>
<list> <value>sadiel/rrhhsas/model/adm/usu/objnegocio/Perfil.hbm.xml</value> <value>sadiel/rrhhsas/model/adm/usu/objnegocio/Usuario.hbm.xml</value> <value>sadiel/rrhhsas/model/adm/usu/objnegocio/UsuarioPerfil.hbm.xml</value>
</list>
</property>
</bean>
El primer problema que podemos ver es que la lista de mappingResources va a crecer continuamente y se hará muy extensa. Cualquiera ha trabajado en un proyecto con 100 tablas o más.
Afortunadamente LocalSessionFactoryBean tiene otra propiedades de tipo Resource[] que no va a permitir solucionar este problema. Y la configuración quedaría de este modo.
<property name=“mappingLocations”>
<!– Cargamos todos los ficheros hibernate que haya en el classpath dentro del paquete –>
<value>classpath:sadiel/**/*.hbm.xml</value>
</property>
Quizás más sutil, pero tampoco parece coherente tener una configuración compleja como la configuración de hibernate, dentro de la configuración de la aplicación. Sobretodo pensando que podemos tener distintas configuraciones para entornos diferentes, o para clientes diferentes.
En este caso LocalSessionFactoryBean no nos puede ayudar directamente ya que no tiene una propiedad de tipo Resource para configurar las propiedades de hibernate. Sin embargo si que podemos hacer referencia a otro bean que contenga estas propiedades.
<bean id=“sessionFactory”
class=“org.springframework.orm.hibernate3.LocalSessionFactoryBean”>
<property name=“dataSource”>
<ref bean=“dataSource” />
</property>
<property name=“hibernateProperties”>
<ref bean=“hibernateProperties” />
</property>
<property name=“mappingLocations”>
<value>classpath:sadiel/**/*.hbm.xml</value>
</property>
</bean>
<bean id=“hibernateProperties”
class=“sadiel.rrhhsas.model.comun.util.ResourcePropertiesUtil”>
<property name=“propertiesLocations”>
<value>classpath:hibernate.properties</value>
</property>
</bean>
De esta manera volvemos a usar el tradicional archivo de configuración hibernate.properties.
La implementación de ResourcePropertiesUtil es muy sencilla, pero la incluyo por completitud.
package sadiel.rrhhsas.model.comun.util;
public class ResourcePropertiesUtil extends Properties {
private Resource[] propertiesLocations;
public void setPropertiesLocations(Resource[] propertiesLocations) throws IOException {
this.propertiesLocations = propertiesLocations;
for (Resource resource : propertiesLocations) {
super.load(resource.getInputStream());
}
}
}
Suponiendo que tenemos que mantener diversas configuraciones, podríamos definir el bean con diferentes propiedades y obtener una de ellas según otro parámetro de configuración.
Existen otras propiedades que pueden aprovechar esta aproximación de la configuración. Trabajando con Spring 1.1 sólo era posible definir la caché de segundo nivel de Hibernate en cada uno de los fichero hbm. Pero desde la versión de Spring 1.2 es posible informar la caché de clases en la propiedad entityCacheStrategies y la caché de colecciones en la propiedad collectionCacheStrategies, ambas de tipo Properties.
Dejo el resto a vuestra imaginación.
Referencias
http://www.springframework.org/docs/reference/resources.html