domingo, 27 de diciembre de 2015

Configurar PovRay en Ubuntu

Configurar PovRay en Ubuntu

Una configuracion

Vamos a probar una configuracion por defecto, a partir de la instalacion mediante APT,

 sudo apt-get install povray* 
, instala los paquetes "povray-include, povray-examples, povray" version 3.7

 

Configurar el perfil y añadir variables de entorno

En el directorio $HOME se creara ".povray/{version}/" alli incluiremos el fichero povray.conf,que se encuentra en "/etc/povray/" , vemos que necesita la variable INSTALLDIR por defecto apunta a "/usr/share/povray-{version}/" tambien indicamos los directorios de Lectura/Escritura.

"/usr/share/povray/3.7/scripts", se encuentran scripts que permiten renderizar los ficheros .pov de una forma mas sencilla.

  
povray -h
povray: /home/david/.povray/3.7/povray.conf: 57: the user setting 'allowed' for [Shellout Security] is less restrictive than the system 'forbidden' setting in '/etc/povray/3.7/povray.conf': using system setting
Persistence of Vision(tm) Ray Tracer Version 3.7.0.unofficial (g++ 4.8 @
 i686-pc-linux-gnu)
export PATH=$PATH:/usr/share/povray-3.7/scripts  //añadir a .bashrc
cp /etc/povray/3.7/povray.conf ~/.povray/3.7/
 geany ~/.povray/3.7/povray.conf &
 mkdir .povray/3.7/in      
 cp /usr/share/doc/povray/examples/objects/* ~./povray/3.7/in/
 mkdir .povray/3.7/out
 sudo render_scene.sh  .povray/3.7/out   .povray/3.7/in/primitiv.pov  
 ll ~/.povray/3.7/out
 okular ~/.povray/3.7/out/primitiv.png &

En out obtenemos:

// This work is licensed under the Creative Commons Attribution 3.0 Unported License.
// To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/
// or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
// California, 94041, USA.

// Persistence Of Vision raytracer version 3.5 sample file.
//
// -w320 -h240
// -w800 -h600 +a0.3
#version 3.7;
global_settings { assumed_gamma 1.0 }
#default{ finish{ ambient 0.1 diffuse 0.9 }} 

#include "colors.inc"

#declare Radius =2.5;
#declare RowSpace=1.0;
#declare ColSpace=1.0;
#declare Dist=-1.25;
#declare Row3= 2;
#declare Row2=Row3+Radius*RowSpace*2;
#declare Row1=Row2+Radius*RowSpace*2;
#declare Col1= -Radius*ColSpace*3;
#declare Col2= Col1+Radius*ColSpace*2;
#declare Col3= Col2+Radius*ColSpace*2;
#declare Col4= Col3+Radius*ColSpace*2;
#declare Col5= Col4+Radius*ColSpace*2;

// perspective (default) camera
camera {
  location  <0.0, 5.0, -17.5>
  look_at   <0.0, 7.0,  0.0>
  right     x*image_width/image_height
  angle 65 
}
// create a regular point light source
light_source {
  0*x                  // light's position (translated below)
  color rgb <1,1,1>    // light's color
  translate <200, 500, -500>
}
 
//otro punto de luz
light_source {
  100*x                  // light's position 
  color rgb <1,0.5,0.2>    // light's color
  translate <25, 200, 200> //desplazamiento 
  
}

background { 
color rgb<0.1,0.1,0.1>
 
 } 

#declare ThisBlue = color rgb<0.1,0.5,0.8>; 

#declare Fade=
texture {
   pigment {
      gradient <1,1,0>
      color_map {
         [0.0 color ThisBlue]
         [0.3 color ThisBlue]
         [0.5 color Clear]
         [1.0 color Clear]
      }
      rotate z*45
   }
   finish {phong 1}
   scale 5
}

#declare Solid=
texture {
   pigment {ThisBlue}
   finish {phong 1}
}

bicubic_patch {
   type 1 flatness 0.01 u_steps 4 v_steps 4,
   <0, -1.5, 2>, <1, -1.5, 0>, <2, -1.5, 0>, <3, -1.5, -2>,
   <0, -0.5, 0>, <1, -0.5, 0>, <2, -0.5, 0>, <3, -0.5,  0>,
   <0,  0.5, 0>, <1,  0.5, 0>, <2,  0.5, 0>, <3,  0.5,  0>,
   <0,  1.5, 2>, <1,  1.5, 0>, <2,  1.5, 0>, <3,  1.5, -2>
   texture {Solid}
   rotate    -45*y
   translate 
}

blob {
   threshold 0.6
   component 1.0, 1.0, < 0.75,   0,       0>
   component 1.0, 1.0, <-0.375,  0.64952, 0>
   component 1.0, 1.0, <-0.375, -0.64952, 0>
   texture {Solid}
   translate 
}

box {
   <-1, -1, -1>, <1, 1, 1>
   texture {Solid}
   rotate <-25, 15, 0>
   translate 
}

cone {
   x,0.5,
   -x,1.0
   rotate  y*30
   texture {Solid}
   translate 
}

cylinder {
   x,-x,1.0
   rotate  y*30
   texture {Solid}
   translate 
}

...

plane {
   z, 0
   hollow on
   texture {Fade}
   clipped_by{box{<-1,-1,-1>,<1,1,1> scale 3}}
   translate 
}
...

quartic {
   //xxxx         xxyy    xxzz  -2(rr+RR)xx
   <1, 0, 0, 0, 2, 0, 0, 2, 0, -2.5,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

   //yyyy     yyzz  -2(rr-RR)yy
   1, 0, 0, 2, 0    1.5,     0, 0, 0,  0,

   //zzzz   -2(rr+RR)zz    (rr-RR)(rr-RR)
   1, 0,    -2.5,       0, 0.5625>
   texture {Solid}
   rotate -45*x
   translate 
}


 

viernes, 18 de septiembre de 2015

Asociaciones "many-to-many" en Hibernate

Asociaciones en Hibernate

Mapeo de asociaciones

En los ejemplos anteriores se ha realizado el mapeo de una sola entidad hacia una única tabla. A continuación ampliaremos los ejemplos teniendo en cuenta los distintos tipos de asociaciones entre clases. Tomaremos como ejemplo Personas que participan una serie de Eventos.

1.2.1. Mapeo de la clase Person

Una primera implementación de la clase  Person.java seria la siguiente:

	  package org.hibernate.tutorial.domain;

		public class Person {
		private Long id;
		private int age;
		private String firstname;
		private String lastname;

		public Person() {} // Accessor methods for all properties, private setter for 'id'

	}

Person.hbm.xml

<hibernate-mapping package="org.hibernate.tutorial.domain">
<class name="Person" table="PERSON">
<id name="id" column="PERSON_ID">
<generator class="native" />
</id>
<property name="age" />
<property name="firstname" />
<property name="lastname" />
</class>
</hibernate-mapping>

Dentro de hibernate.xml:

<mapping resource="org/hibernate/tutorial/domain/Event.hbm.xml" />
<mapping resource="org/hibernate/tutorial/domain/Person.hbm.xml" />

De esta manera hemos configurado la asociación bi-direccional entre ambas entidades. Los principios de diseño importantes a tener en cuenta son la direccionalidad, cardinalidad y el tipo de Collection que necesitamos.

1.2.2. Asociación uni-direccional basada en Set

Al añadir la collection de eventos a la clase  Person , es posible acceder a cada uno de los eventos para una instancia de persona, sin tener que ejecutar de forma explícita la consulta - llamada a  Person#getEvents. Hibernate mapea las asociaciones multi-valuadas a traves de una de las distintas implementaciones de Java Collection Framework; en este caso escogemos java.util.Set ya que no deseamos tener en cuenta elementos repetidos, ni su ordenación, en los ejemplos:

 public class Person {
	private Set events = new HashSet();

	public Set getEvents() {
		return events;
	}

	public void setEvents(Set events) {
		this.events = events;
	}
}
 

Antes de realizar el mapeo de la asociación, vemos que es posible permitir la bi-direccionalidad, creando otra colección de Person dentro de  Event. Esto no tiene por qué estar especificado desde el punto de vista funcional. Es posible implementar una consulta que de forma explicita obtenga todos los participantes dado un evento. Esta parte corresponde al diseño, de momento uni-direccional. Lo que ha de quedar claro, es que la asociación configurada implica una multiplicidad de muchos-a-muchos. Como vemos en el mapping Hibernate siguiente:

<class name="Person" table="PERSON">
<id name="id" column="PERSON_ID">
<generator class="native" />
</id>
<property name="age" />
<property name="firstname" />
<property name="lastname" />
<set name="events" table="PERSON_EVENT">
<key column="PERSON_ID" />
<many-to-many column="EVENT_ID" class="Event" />
</set>
</class>

Dentro del rango de mapeo a Collection,  set suele ser el más utilizado. Para las asociaciones muchos-a-muchos, y relaciones  n:m entre entidades, es necesaria la existencia de la tabla de asociacion. Dicha tabla se crea usando el nombre del atributo table del elemento set . La clave primaria en la tabla de asociación, se indica mediante el atributo key , los nombres de cada columna que se crean a partir de la entidad Event mediante el atributo column  de la configuración many-to-many. Hibernate acepta tambien que la declaracion de dicha collection sea tipada.

El esquema resultante del mapping sería el siguiente:

   _____________        __________________     |             |      |                  |       _____________   
     |EVENTS    |      |   PERSON_EVENT   |      |             |     |_____________|      |__________________|      
	 |PERSON   |     |             |      |                  |      |_____________|     | *EVENT_ID   |
   <--> 
   | *EVENT_ID        |      |             |     |  EVENT_DATE |      | *PERSON_ID       | 
   <--> 
   | *PERSON_ID  |     |  TITLE      |      |__________________|      |  AGE        |     |_____________|                                |  FIRSTNAME |                                                    |  LASTNAME   |                                                    |_____________|   
 

1.2.3. Trabajando sobre la asociation many-to-many

Creamos una clase EventManager que nos permita realizar ciertas operaciones sobre las entidades:

  	private void addPersonToEvent(Long personId, Long eventId) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Person aPerson = (Person) session.load(Person.class, personId);
		Event anEvent = (Event) session.load(Event.class, eventId);
		aPerson.getEvents().add(anEvent);
		session.getTransaction().commit();
	}
   

Actualizaremos los valores de la colección a través de los métodos que ofrece. Como vemos, no existe una llamada explicita a los métodos  update() o save(); el framework Hibernate detecta automaticamente que la colección se ha modificado y necesita actualizarse (update). A ésto se le llama "automatic dirty checking". Pasar a "dirty" es posible, por ejemplo, modificando cualquier atributo (name, date...) de cualquiera de los objetos entidad. Mientras esten en su estado persistent, reflejado en la session una Hibernate org.hibernate.Session correspondiente, el framework Hibernate controla cualquier cambio y ejecuta sentencias SQL de escritura en segundo plano. El proceso de sincronización del estado de la memoria con la base de datos, que normalmente se ejecuta al final de cada unidad de operación, se denomina flushing. En el código, la finalización de la unidad de operación, se corresponde con la llamada a commit, o ejecución de rollback, dentro de una transacción.

Es posible realizar la carga de los datos de una entidad person y sus events multiples unidades de operación. Además es posible actualizar un objeto fuera de su org.hibernate.Session , cuando no se encuentra en un estado "persistent" (si se encontraba en el estado persistent antes, este nuevo estado se denomina " detached"). En el estado "detached" es posible además modificar los datos de una colección (ej. Events):

  private void addPersonToEvent(Long personId, Long eventId) { 
  Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 		              session.beginTransaction(); //
Person aPerson = (Person)  session
.createQuery("select p from Person p left join fetch p.events where p.id = :pid")
.setParameter("pid", personId).uniqueResult();// Eager fetch the collection so we can use it detached  
   Event anEvent = (Event) session.load(Event.class, eventId); 		      session.getTransaction().commit();  // End of first unit of work        
    aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
    // Begin second unit of work            
     Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();       
     session2.beginTransaction(); 
	 sesion2.update(aPerson); // Reattachment of aPerson         
	 session2.getTransaction().commit();
}
	 	
   

La llamada al método update hace que el objeto pase de "detached" a "persistent" de nuevo, asociándolo a una nueva unidad de operación, de esta forma cualquier modificación que hubiesemos realizado cuando estaba en "detached", se guarda en la base de datos. Esto afecta a cualquier tipo modificación que se hubiese realizado (inserciones/borrados) a la colección (ej. events) de dicha entidad (ej. person).

Aunque no es de mucha utilidad en nuestro ejemplo, se trata de un concepto muy importante que debe ser tenido en cuenta a la hora del diseño. Completaremos el tutorial, añadirendo una nueva acción a la clase manager EventManager y realizaremos una llamada desde la linea de comandos. Para recuperar los identificadores de una persona y de un evento - el método save() devuelve el id:

   else if (args[0].equals("addpersontoevent")) { 
		Long eventId = mgr.createAndStoreEvent("My Event", new Date());
		Long personId = mgr.createAndStorePerson("Foo", "Bar"); 
		mgr.addPersonToEvent(personId, eventId);
		System.out.println("Added person " + personId + " to event " + eventId);       
		}

Este es un ejemplo de asociación entre dos clases de igual relevancia (es decir dos entidades). Como mencionabamos anteriormente, existen otros tipos de clases y tipos, dentro de un modelo, normalmente de menor relevancia en el diseño. Por ejemplo, podriamos tener una clase Address dentro de Person, o un tipo de valor long para Event indicando el timestamp en el que ocurre. Ambos valores dependen de su entidad.

En el diseño puede aparecer una entidad independiente como colección de valores estáticos. Lo cual es conceptualmente distinto a una collection referenciada entre entidades aunque parezca lo mísmo en código.

1.2.4. Añadir una colection de valores

Añadiremos la colección de direcciones email a la entidad  Person. Para ello usaremos java.util.Set de java.lang.String :

private Set emailAddresses = new HashSet();

	public Set getEmailAddresses() {
		return emailAddresses;
	}

	public void setEmailAddresses(Set emailAddresses) {
		this.emailAddresses = emailAddresses;
	}

El mapeo de la colección se realiza de la siguiente manera:

private Set emailAddresses = new HashSet();

	public Set getEmailAddresses() {
		return emailAddresses;
	}

	public void setEmailAddresses(Set emailAddresses) {
		this.emailAddresses = emailAddresses;
	}
	

La diferencia entre el mapeo anterior es la utilización de element lo que indica a Hibernate que dicha colección no referencia otra entidad sino que se trata de un conjunto de valores (en este caso de tipo string), mediante type=string indicamos el conversor de tipo. De igual manera el atributo table del elemento  set se corrresponde con el nombre de la tabla.  key indica el nombre de la columna que se usara como foreign-key en dicha tabal. El atributo column de  element nos indica el nombre de la columna en la que se almacenan los valores en base de datos.

Vemos el esquema resultante:

  _____________        __________________   |             |      |                  |       _____________   |   EVENTS    |      |   PERSON_EVENT   |      |             |       ___________________   |_____________|      |__________________|      |    PERSON   |      |                   |   |             |      |                  |      |_____________|      | PERSON_EMAIL_ADDR |   | *EVENT_ID   | 
   <-->
    | *EVENT_ID        |      |             |      |___________________|   |  EVENT_DATE |      | *PERSON_ID       | 
	<-->
	 | *PERSON_ID  | 
	 <--> 
	|  *PERSON_ID       |   |  TITLE      |      
	|__________________|      |  AGE        |      |  *EMAIL_ADDR      |   |_____________| 
	                               |  FIRSTNAME  |    
	  |___________________| |  LASTNAME   |                                         
	  |_____________|  
	   

Se puede ver que la primary key de la tabla de valores correspondiente a la colección es una clave compuesta de ambas columnas. Lo que implica que no pueden existir valores duplicados de email para una persona. Esto es lo que funcionalmente se deseaba y se indico con la Collection java.util.Set en Java.

Vemos la implementación de un método para añadir elementos a la colección, como se hizo anteriormente.

	private void addEmailToPerson(Long personId, String emailAddress) {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		Person aPerson = (Person) session.load(Person.class, personId); 
		aPerson.getEmailAddresses().add(emailAddress);
		session.getTransaction().commit();
	}
  

Esta vez no se ha utilizado  fetch query para initializar la colección. Viendo el log de la consulta, intentaremos optimizarlo mediante eager fetch.

1.2.5. Asociación bi-directional

A continuación realizaremos el mapping de una asociación bi-direccional. El esquema creado, no cambia, ya que necesitamos la multiplicidad many-to-many.

Importante

Tener en cuenta que en la navegabilidad es más flexible desde el punto de vista de acceso a una base de datos relacional que el caso de acceso de forma remota; en estos casos seria necesario tener en cuenta la navegabilidad, desde el punto de vista de rendimiento.

Añadimos, la colección de participants a la clase Event :

       private Set participants = new HashSet();

	public Set getParticipants() {
		return participants;
	}

	public void setParticipants(Set participants) {
		this.participants = participants;
	}
	   

Creamos el mapping para la asociación,  Event.hbm.xml

   <set name="participants" table="PERSON_EVENT" inverse="true">
<key column="EVENT_ID" />
<many-to-many column="PERSON_ID" class="Person" />
</set>

Realizamos dicho mapping a través de set en ambos ficheros. Como vemos, los nombres de las columnas dentro de  key y many-to-many, estan intercambiados en ambos documentos .hbm.xml. Lo más importante a tener en cuenta es el atributo inverse="true" dentro del elemento set para el mapping de Event.

Esto indica a Hibernate que ha de acceder a la clase Person , cada vez que necesite información acerca de la relación entre el Event en curso y los participantes.

1.2.6. Trabajando con asociaciones bi-directionales

Tengamos en cuenta que Hibernate no modifica la semantica de Java. Entonces, cómo se enlazan las clases Person y Event en el ejemplo de navegabilidad unidireccional? Al añadir una instancia de  Event a la colección events, dentro de una instancia Person. Si queremos que dicho enlace sea bi-directional, lo que debemos hacer es añadir en una referencia a una collection Person dentro de Event. "Crear un enlace en ambos lados" es absolutamente necesario si queremos que dicho enlace sea bi-direccional.

Su acceso bi-direccional en  Person:

 	protected Set getEvents() {
			return events;
			}

	protected void setEvents(Set events) {
		this.events = events;
	}

	public void addToEvent(Event event) {
		this.getEvents().add(event);
		event.getParticipants().add(this);
	}

	public void removeFromEvent(Event event) {
		this.getEvents().remove(event);
		event.getParticipants().remove(this);
	}
	   

Vemos que los métodos get y set para el manejo de la coleccion son protected. Esto permite que las clases del mismo paquete y sus subclases puedan acceder, evitando que clases fuera del paquete puedan modificarla. Esto se aplica tambien al otro lado (Event).

Respecto al atributo  inverse , en el caso de un enlace bi-directional se trata únicamente de establecer las referencias en ambos lados. Sin embargo, Hibernate necesita más información para realizar las operaciones de INSERT y UPDATE  (y así evitar constraint violations). Si establecemos uno de los lados como inverse  Hibernate lo considerará como  mirror (copia exacta del otro lado). Una vez indicado esto, Hibernate es capaz de resolver la transformación direccional de los objetos enlazados al esquema SQL. Esta configuración es fija: Toda asociación bi-direccional a de tener uno de los lados inverse.

domingo, 19 de abril de 2015

Interceptores en Struts2

Introduccion

Los interceptores procesan una invocacion a Action antes y despues de cada llamada. La mayor parte de la funcionalidad del framework esta implementada mediante interceptores. De esta manera se aplican los filtros ante multiples submits, conversion de tipos, propagacion de objetos, la validacion, el upload de ficheros, la preparacion de pagina y más. Es posible aplicar una pila especifica de ellos de manera que establezcamos que caracteristicas necesita soportar una Action.

Ciclo de vida de una Action

schema

 

Las clases de interceptor se declaran tambien en el fichero de configuración struts.xml utilizando un par clave valor. Los nombres especificados más abajo vienen predeclarados en el fichero struts-default.xml. Es posible declarar nuestros propios interceptores creados para lo cual indicamos el nombre y la clase dentro de la etiqueta.

Lista de Interceptores:

Interceptor

Name

Description

Alias Interceptor

alias

Transforma el nombre de parametros que se envían con distinto nombre en las distintas request.

Chaining Interceptor

chain

Hace que las propiedades de la Action anterior esten disponibles en la Action en curso. Se usa comúnmente con el <result type="chain"> (de la acción precedente).

Checkbox Interceptor

checkbox

Añade un código automático para gestionar los checkbox no inicializados y los añade como parámetros en la request con un valor por defecto (generamente "false"). Utiliza campos hidden para detectar campos que no se han marcado. Se puede modificar el valor que inicia al principio.

Cookie Interceptor

cookie

Inyecta una cookie con un par nombre-valor configurable en la accion (Since 2.0.7.)

CookieProvider Interceptor

cookieProvider

Inyecta cookies desde la acción hacia la response (Since 2.3.15.)

Conversion Error Interceptor

conversionError

Inyecta errores de tipo conversion errors from the ActionContext to the Action's field errors

Create Session Interceptor

createSession

Crea una sesión HttpSession automaticamente, útil con ciertos interceptores, por ejemplo para funcionar correctamente con el el interceptor de tipo TokenInterceptor

DebuggingInterceptor

debugging

Aporta varias plantillas de depuración para entender lo que ocurre detrás de la página.

DeprecationInterceptor

deprecation

Cuand devMode está activado, marca toda configuración desconocida o desestimada (deprecated) settings

Execute and Wait Interceptor

execAndWait

Ejecuta la Action en segundo plano y a continuación reenvia una respuesta hacia una página intermedia de espera.

Exception Interceptor

exception

Mapea las excepciones hacia un <result ...>

File Upload Interceptor

fileUpload

Un Interceptor que facilita el upload de ficheros.

I18n Interceptor

i18n

Guarda la configuración de locale guardada para una user's session.

Logger Interceptor

logger

Escribe el nombre de la Action hacia un <result...>.

Message Store Interceptor

store

Guarda y recupera mensajes de tipo "action messages / errors / field errors" para una acción que implemente la interfaz ValidationAware, dentro de la sesion.

Model Driven Interceptor

modelDriven

Si la Action implementa ModelDriven, apila el resultado de  getModel dentro del Value Stack.

Scoped Model Driven Interceptor

scopedModelDriven

Si la Action implementa ScopedModelDriven, el interceptor recupera ell modelo de la sesion, request, y lo copia en la Action en curso con la llamada setModel.

Parameters Interceptor

params

Establece los parametros de la request en la Action.

Prepare Interceptor

prepare

Si la Action implementa la interfaz Preparable, se realiza la llamada al método prepare.

Scope Interceptor

scope

Es un sencillo mecanismo para almacenar los parametros de la Action en distintos scopes.

Servlet Config Interceptor

servletConfig

Permite acceder a HttpServletRequest and HttpServletResponse.

Static Parameters Interceptor

staticParams

Establece los parametros declarados en struts.xml dentro de la Action. Estos se corresponden con <param> dentro de <action>.

Roles Interceptor

roles

Una Action solo se ejecutara si el usuario tiene el role de JAAS correcto.

Timer Interceptor

timer

Devuelve el tiempo que lleva la Action ejecutandose (incluido sus interceptores anidados y la vista)

Token Interceptor

token

Verifica la presencia de un token dentro de la Action, lo que previene de request con el mismo contenido (multiple submission).

Token Session Interceptor

tokenSession

Lo mísmo que el Interceptor de tipo Token, pero almacena los datos almacenados en la sesion cuando se ha interceptado un token invalido.

Validation Interceptor

validation

Realiza la validacion a partir de los validators declarados en  action-validation.xml

Default Workflow Interceptor

workflow

Llama el método validate en nuestra clase de tipo Action. Si los errores de tipo Action se crean entonces se devuelve la vista INPUT.

Parameter Filter Interceptor

N/A

Elimina parametros de la lista de parametros accesibles a la Action.

Profiling Interceptor

profiling

Activa el profiling entre parametros

Multiselect Interceptor

multiselect

Como el interceptor de tipo checkbox, detecta que no hay valores seleccionados para un campo con muchos valores (al igual que vimos en el Interceptor de tipo Checkbox).

Desde la version 2.0.7, los nombres de Interceptors y Results pasaron a camelCase. (El modelo principal model-driven es ahora modelDriven.) Los nombre antiguos se guardan como "alias" hasta la verion Struts 2.1.0. Las versiones que utilizan la notación hyphen no se listan aqui, pero pueden encontrarse en documentaciones anteriores.

miércoles, 21 de enero de 2015

Spring Portlet MVC (Introducción)

Introducción

La especificación JSR-168

Para mayor información en el API portlet, se recomienda revisar la documentación de Oracle "Introduction to JSR 168", y la propia especificación JSR-168 Specification.

Además de ofrecer soporte al desarrollo Web convencional basado en servlets, Spring ofrece la posibilidad de integrar el desarrollo de Portlets (JSR-168). En la medida de lo posible (como veremos), el framework Spring MVC Portlet es una imagen de Spring MVC (link to), y utiliza la misma capa de Abstracción e Integración Spring. Por ello es conveniente realizar un repaso a Spring Web MVC framework y View technologies antes de continuar con la documentación.

Tengamos en cuenta que aunque ambos frameworks provengan de las mísmas abstracciones, existen varias funcionalidades, como el workflow que ofrece JSR-168, que conviene tener en cuenta.

La principal diferencia entre el workflow que siguen los servlets es que una petición en un portlet tiene dos fases diferenciadas: la fase action y la fase de render. La fase action se ejecuta una sola vez y en ella es en la que cualquier cambio del modelo u otras acciones encadenadas suceden. La fase de render genera lo que debe ser mostrado al usuario (vista) cada a cada vez que se realiza un refresh. El punto crucial aqui es que, desde el punto de vista de una simple request, la fase "action" se ejecuta sólo una vez, mientras que la fase "render" puede ejecutarse varias veces. Esta caracteristica implica tener en cuenta la separación de cada una de las fases: por un lado la comunicación con el modelo, por otro la generación de la vista.

La dos fases de la request portlet es el punto fuerte de la especificación JSR-168. Supongamos el siguiente ejemplo, los resultados de una búsqueda pueden actualizarse de forma dinámica, sin que por ello el usuario tenga que lanzar de nuevo la petición. Como funcionalidad extra Spring Portlet, al contrario que otros frameworks que adaptan a una funcionalidad semejante lo más parecida al funcionamiento de los servlet, nos permite implementar ambas fasesde la especificación - para así ofrecer toda la potencia del uso de portlets. Spring MVC Portlet Framework, ofrece dos métodos que manejan la request: el primero para la fase "action", el segundo para la fase "render". Un ejemplo, para la versión servlet tenemos AbstractController con el método handleRequestInternal(..), la versión portlet de AbstractController contiene los métodos handleActionRequestInternal(..)y handleRenderRequestInternal(..).

El diseño se realiza a partir de DispatcherPortlet que asigna la request a los handlers, a partir de handler mappings configurables y resolución de la vista (forwards, redirect) de forma similar a como lo hace DispatcherServlet en el framework web. La mísma forma de proceder para request que manejan uploads de tipo file

La resolución de Locale y theme no estan soportadas por el framework - ya que estos aspectos conciernen a la generación de la vista por parte del contenedor portal/portlet y no se aplican al contexto Spring. Esto no afecta al tratamiento por parte de Spring de la Locale, (sino más bien a su modificación, sincronización con el contenedor portlet). Todos los mecanismos de Spring que tratan dicha Locale (internacionalización de mensajes), funcionaran correctamente ya que DispatcherPortlet expone la locale de la mísma manera que lo hace DispatcherServlet.

 Controladores en Spring Portlet MVC

El controlador por defecto es una sencilla interfaz, que ofrece 2 métodos:

  • void handleActionRequest(request,response)
  • ModelAndView handleRenderRequest(request,response)

El framework añade ademas la mayoría de las implementaciones de controller existentes, como AbstractController, SimpleFormController... El acceso a datos a través de objetos implementan el patrón command, manejo del modelo y resolución de la vista, de forma transparente, como si trabajasemos directamente con el api Servlet.

 Vistas en Spring Portlet MVC

La generación de la vista es semejante a la realizada con servlets, esto se consigue a través de un bridge llamado ViewRendererServlet. Al usar este servlet, la petición del portlet se convierte en una petición servlet y la vista se genera mediante servlets. Lo que lo hace compatible con generadores de vistas, como JSP, Velocity o Freemaker.

 Beans de scope-web

Beans cuyo ciclo de vida tiene se asocia a la duración de Request o Session. Esto no es una característica específica del framework Spring Portlet sino del contenedor Spring de WebApplicationContext. Más detalle sobre este tipo de bean en “Request, session, and global session scopes”

martes, 20 de enero de 2015

Me dejas el Tablet? (Achtung)

Tomar precauciones a la hora de compartir un dispositivo

(Karpersky Labs)

" Al Compartir un dispositivo aumentamos el riesgo de que sea infectado malware, pérdida de datos, robo de nuestra cuenta de usuario, algunas precauciones como realizar siempre copia de seguridad de ficheros importantes y borrar la información que pueda caer en otras manos (por ejemplo limpiar los historicos de autocompletar), establecer permisos adecuados para evitar acceso a información por otros..."