viernes, 29 de junio de 2007

DataModelSelection en Conversation context problem

Después de mucho probar me he dado cuenta que el datamodelselection funciona en un contexto de session

jueves, 28 de junio de 2007

Interceptar toda la aplicacion en Seam

Podemos utilzar la filosofía de Seam de interceptar todo, para cronometrar nuestra aplicación y comprobar en que métodos se producen retardos.

  1. Creamos una clase que extienda de org.jboss.seam.ejb.SeamInterceptor es decir la clase que utiliza Seam para interceptar los componentes de la aplicacion:
    • public class MiaoInterceptor extends SeamInterceptor {

      @AroundInvoke
      public Object aroundInvoke(InvocationContext invocation) throws Exception
      {

      if(invocation.getTarget().getClass().getPackage().toString().contains("es.miao")){
      long l = System.currentTimeMillis();

      String invocacion=invocation.getTarget().getClass().getSimpleName()+"."+invocation.getMethod().getName()+"()";
      System.out.println("INICIANDO: "+invocacion);

      Object o = invocation.proceed();
      long ll = System.currentTimeMillis();

      System.out.println("FINALIZANDO: "+invocacion+" Tiempo total: "+(ll-l)+" milisegundos");

      return o;
      }
      return invocation.proceed();
      }

      }
  2. Cambiar en el ejb-jar.xml el interceptor de seam por el nuestro
    • <?xml version="1.0" encoding="UTF-8"?>
      <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
      version="3.0">
      <interceptors>
      <interceptor>
      <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
      </interceptor>
      <interceptor>
      <interceptor-class>es.miao.MiaoInterceptor</interceptor-class>
      </interceptor>
      </interceptors>
      <assembly-descriptor>
      <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
      </interceptor-binding>
      <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>es.miao.MiaoInterceptor</interceptor-class>
      </interceptor-binding>
      </assembly-descriptor>
      </ejb-jar>

InstantiationException: Configurar intelli jidea para correr pruebas de seam

Un problema es que el seam necesita que en el directorio donde se copian todos los recursos empleados exista el security.drl, y esto se hace settings>compiler>resource patterns e incluir ?*.drl;

además hay que copiar persistence-text.xml a persistence.xml, esto lo hace el archivo ant del seam, pero hay que indicarselo al intellijidea. se puede hacer configurando la prueba para que corra una tarea ant antes de arrancar.

miércoles, 27 de junio de 2007

Alta de autonomo en epigrafe de programador en sevilla

Hacienda al lado de la casa de la moneda
La seguridad social en calle castelar mapa

  1. darse de alta en el IAE (Impuesto de actividades económicas)
    • Mostrador 16 pedir modelo 036
    • pedir número para declaración censal
    • entregar modelo cumplimentado
      • epigrafe 762 Programador
  2. ir a la seguridad social
    • fotocopiar el 036 sellado
    • llevar el numero de cuenta para domiciliación
    • llevar el número de la seguridad social
    • el epigrafe en seguridad social es el 72210:Edición de programas

martes, 26 de junio de 2007

jbpm en seam

primer ejemplo a seguir el numberguess example de seam aunque también está el dvd-store

hay que definir el componente de la definición del proceso en el components.xml:

<component class="org.jboss.seam.core.Jbpm">
<property name="pageflowDefinitions">
<value>pageflow.jpdl.xml</value>
<value>cheat.jpdl.xml</value>
</property>
</component>


y posteriormente la definición del proceso en este caso de cheat.jpdl

<pageflow-definition xmlns="http://jboss.com/products/seam/pageflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://jboss.com/products/seam/pageflow http://jboss.com/products/seam/pageflow-1.2.xsd"
name="cheat">

<start-page name="confirm" view-id="/confirm.jspx">
<transition name="yes" to="cheat">
<action expression="#{numberGuess.cheated}"/>
</transition>
<transition name="no" to="end"/>
</start-page>

<page name="cheat" view-id="/cheat.jspx">
<redirect/>
<transition to="end"/>
</page>

<page name="end" view-id="/numberGuess.jspx">
<redirect/>
<end-conversation/>
</page>

</pageflow-definition>


y en el pages.xml arrancamos el pageflow

<pages>
<page view-id="/numberGuess.jspx">
<begin-conversation join="true" pageflow="numberGuess"/>
</page>
<page view-id="/confirm.jspx">
<begin-conversation nested="true" pageflow="cheat"/>
</page>
</pages>

aunque también se puede arrancar desde el componente

@Create
@Begin(pageflow="numberGuess")
public void begin(){
...

}


pages.xml navegacion

Entre las razones de elegir el pages.xml para definir la navegación se encuentran:

  1. la posibilidad de especificar valores del request en la redirección
  2. comenzar o acabar una conversación desde la evaluación de una regla
  3. avaluar cualquier expressión de tipo EL

Para ver el empleo del pages.xml se puede ojear lo que produce el seam-jems generate-entities



Utilizar reglas de navegacion con pages.xml

lo que en faces-config.xml se escribiría así:

<navigation-rule>
<from-view-id>/editDocument.xhtml</from-view-id>
<navigation-case>
<from-action>#{documentEditor.update}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/viewDocument.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>


lo que en pages.xml quedaría así:

<pageview-id="/editDocument.xhtml">
<navigationfrom-action="#{documentEditor.update}"
evaluate="#{documentEditor.errors.size}">
<ruleif-outcome="0">
<redirectview-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>


o incluso

<pageview-id="/editDocument.xhtml">
<navigationfrom-action="#{documentEditor.update}">
<ruleif="#{documentEditor.errors.empty}">
<redirectview-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>

Gestión de errores en Seam

Con la etiqueta "restrict" me parece que se produce una redirección una vez que se salva la condición?

Ejemplo de Seam util para investigar: blog,
en este no se recoge la excepción en el pages.xml, unicamente la clase de excepción EntryNotFoundException tiene las etiquetas:
@ApplicationException(rollback=true)
@HttpError(errorCode=HttpServletResponse.SC_NOT_FOUND)
y entonces y con el web.xml:

<error-page>
<error-code>404</error-code>
<location>/seam/404.xhtml</location>
</error-page>

directamente busca el 404.xhtml

Las excepciones heredan de RuntimeException
y se producen en la invocación de un metodo jsf, es decir metodo público que no devuelve nada.
ejemplo metodo jsf que lanza excepción:
public void buscar(){
....
thrown new RuntimeException("algo ha fallado");
....
}

ademas se pueden producir a través del pages.xml con la etiqueta "restrict" o con "action" dentro de "page"

<page view-id="/gestion/*">
<restrict>#{authenticator.admin}</restrict>
</page>

<exception class="es.miao.MiaoExcepcion">
<redirect view-id="/error.xhtml">
<message>ha funcionado la runtime exception</message>
</redirect>
</exception>


Se supone que al entrar en cualquier pagina que se corresponda con el patrón "/gestion/*" es decir todas aquellas que se encuentren en la carpeta gestion, serán restringidas a que el componente authenticator responda afirmativamente al metodo isAdmin().
De lo contrario la etiqueta restrict se encarga de llevar a la página de error correspondiente.

<exception class="org.jboss.seam.security.NotLoggedInException">
<redirect view-id="/login.xhtml">
<message>#{messages.masInfo}</message>
</redirect>
</exception>

Con "restrict" es el componente Identity el que se encarga de evaluar la expressión y lanzar la correspondiente excepción, también podríamos obtener una excepción de la etiqueta "action"
<action execute="#{catalogoAction.disminuye}" />

Se supone que las acciones jsf no devuelven nada como resultado return void. Sin embargo la etiqueta restrict espera un boolean [boolean isAdmin(), ó , boolean isChecked()]



Seam componentes (traduccion de seam tutorial)

Existen 4 tipos de componentes:

  1. EJB 3.0 stateless session beans
  2. EJB 3.0 stateful session beans
  3. EJB 3.0 entity beans
  4. JavaBeans
  5. EJB 3.0 message-driven beans
Los EJB 3.0 stateless session beans:
Beans sin estado, se suelen usar como jsf listeners.
Contexto: stateless context

Los EJB 3.0 stateful session beans:
Son componentes con estado
Por defecto su contexto es de conversación, unicamente no puede estar en el contexto de página o stateless context.
Cuando están es contexto de sessión son siempre serializados por Seam

Los EJB 3.0 Entity Beans:
Son los beans que representan a las entidades persistentes.
Debido a que tienen una identidad en el contexto de seam y además una entidad en la persistencia, se suelen instanciar en el propio código java en lugar de instanciarlos Seam.
Estos beans no soportan la biyección.
Por defecto son de Contexto de conversación. No pueden ser stateless (Sin estado).

...




(Interceptores)Factorias de session que se recargan según eventos:

De esta forma no recargamos las llamadas a la base de datos:

@Stateful
@Scope(SESSION)
@Name("bookingList")
@Restrict("#{identity.loggedIn}")
@TransactionAttribute(REQUIRES_NEW)
public class BookingListAction implements BookingList, Serializable
{
.......

@Factory
@Observer("bookingConfirmed")
public void getBookings()
{
bookings = em.createQuery("select b from Booking b where b.user.username = :username order by b.checkinDate")
.setParameter("username", user.getUsername())
.getResultList();
}
........
}
@Stateful
@Name("hotelBooking")
@Restrict("#{identity.loggedIn}")
public class HotelBookingAction implements HotelBooking
{
...

@End
public void confirm()
{
em.persist(booking);
facesMessages.add("#{messages.gracias}, #{user.name}, your confimation number for #{hotel.name} is #{booking.id}");
log.info("New booking: #{booking.id} for #{user.username}");
events.raiseTransactionSuccessEvent("bookingConfirmed");
}
...
}

Pages.xml param converter Entity Id as Page Parameters

Al utilizar el seam framework:entity-home
<framework:entity-home name="empresaCasa" entity-class="es.miao.Empresa" >
<framework:id >#{param.empresaId}</framework:id>
</framework:entity-home>


Me daba un error de hibernate de conversión, se esperaba un long (el id de empresa) y se recibe un string. En la documentación de Seam viene que se pueden añadir conversores a los parametros recibidos, en este caso había que aclarar en el pages.

<page view-id="/gestion/empresa.xhtml">
<param name="empresaId" value="#{empresaCasa.id}" converterId="javax.faces.Long" />
</page>

lunes, 25 de junio de 2007

Hibernate anotar una enumeracion

public enum Status {OPEN,CANCELLED,PROCESSING,SHIPPED}

@Column(name="STATUS")
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}

viernes, 22 de junio de 2007

Conversaciones en Jboss Seam

Se puede entender por una conversación en Seam algo muy parecido de lo que hacemos cuando conversamos entre personas.
Existe un lugar (AplicationContext), un tiempo (SessionContext) y después una serie de objetos implicados en la conversación. Entre los objetos implicados en la conversación se encuentra el usuario, que participa a través de eventos, de tipo:

  • JSF
  • jBMP
  • Seam page actions
  • Seam component-drive events
Los eventos implican manejar las excepciones que se derivan de estos , novedad en el seam 1.6


El objeto ConversationEntry tiene una serie de propiedades que usaremos al cambiar de conversación. Entre elllas el viewId, es decir en nuestro caso, la página jsf. Igualmente tiene el metodo select(), que cambia la conversación seleccionada a la conversación actual.



Las clases implicadas son:
org.jboss.seam.core.ConversationEntry
org.jboss.seam.core.ConversationList
org.jboss.seam.core.Manager

jueves, 21 de junio de 2007

interesante en seam

Limitaciones/validaciones en inputs jsf y seam:
@NotNull(message="Credit card number is required")
@Length(min=16, max=16, message="Credit card number must 16 digits long")
@Pattern(regex="^\\d*$", message="Credit card number must be numeric")



Añadir un mensaje a un control jsf a través del componente facesMessages de Seam

facesMessages.addToControl("verify", "Re-enter new password");
facesMessages.addToControl("username", "Username #{user.username} #{messages.traducciones}");
* notar que podemos hacer referencia a un componente a traves del lenguaje EL

Añadir un contador con interceptores
esto se hace a través del pages.xml

<page view-id="*">
<action execute="#{blog.hitCount.hit}"/>
</page>

Obtener la pagina actual desde cualquier componente
javax.faces.context.FacesContext.getCurrentInstance().getViewRoot().getViewId()

Obtener info del contexto para upload y directorios de imgs
facesContext.externalContext.requestContextPath

i18n, se puede acceder a través de la clase java, y el mismo properties puede tener referencias EL
facesMessages.addFromResourceBundle("Hello");
Hello=Hello,#{user.firstName}#{user.lastName}

Inyectar de forma dinámica objetos en cada contexto (extraído de ejemplo de DVD Store)
@In Context sessionContext;
private static final String USER_VAR = "currentUser";
function void xxx(){
Object found=dao.get(xx)
sessionContext.set(USER_VAR, found);
}
ya está inyectado el objeto found en el contexto de session.











miércoles, 20 de junio de 2007

Obtener el hibernate Session desde EntityManager

javax.persistence.EntityManager ---------> org.hibernate.Session

Para utizar la API de hibernate desde el EntityManager inyectado desde Seam

@PersistenceContext
private EntityManager em;


Session session = ((HibernateEntityManager) em.getDelegate()).getSession();

lunes, 18 de junio de 2007

UnifiedExpressionLanguage operador &&

El operador "&&" se cambia a "and"

http://java.sun.com/javaee/5/docs/tutorial/doc/JSPIntro7.html


not empty
empty

la expresión quedaría de la siguiente forma: #{empty cart.cart}

Convertir byte[] a archivo

File file = new File(name);
file.createNewFile();
FileInputStream fileInputStream = new FileInputStream(name);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData);
OutputStream outputStream = new FileOutputStream(
name);
int data;
while ((data = byteArrayInputStream.read()) != -1) {
outputStream.write(data);
}

fileInputStream.close();
outputStream.close();

jueves, 14 de junio de 2007

s:link uso de esta etiqueta de seam

<s:link value="#{msg.title}" action="#{messageManager.select}"/>


@Stateful
@Scope(SESSION)
@Name("messageManager")
public class MessageManagerBean implements Serializable, MessageManager
{
public void select()
{
if (message!=null) message.setRead(true);
}

}

miércoles, 13 de junio de 2007

Ejemplo heritance jpa

package es.miao;

import java.io.Serializable;
import javax.persistence.*;

import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;

@Entity
@Table(name = "color_primaria")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="tipo", discriminatorType=DiscriminatorType.STRING, length=3)
@DiscriminatorValue(value="PRI")
public class CombinacionColorPrimaria implements Serializable {

//seam-gen attributes (you should probably edit these)
private Long id;
private Integer version;
private Color color;

//add additional entity attributes

//seam-gen attribute getters/setters with annotations (you probably should edit)

@Id @GeneratedValue
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@Version
public Integer getVersion() {
return version;
}

private void setVersion(Integer version) {
this.version = version;
}

@ManyToOne
public Color getColor() {
return color;
}

public void setColor(Color color) {
this.color = color;
}


}


package es.miao;

import java.io.Serializable;
import javax.persistence.*;

import org.hibernate.validator.Length;

@Entity
@DiscriminatorValue(value="SEC")
public class CombinacionColorSecundaria extends CombinacionColorPrimaria implements Serializable {






}

DiscriminatorColumn problem

@DiscriminatorColumn(name="tipo", discriminatorType=DiscriminatorType.STRING, length=20)
@DiscriminatorValue(value="PRIM")

No hay que poner en la clase java la propiedad!

anotaciones colecciones persistencia

@OneToMany(mappedBy="aplicacion", cascade=CascadeType.ALL)
public List getPiezas() {
return piezas;
}

@ManyToOne
public Aplicacion getAplicacion() {
return this.aplicacion;
}



@ManyToMany(targetEntity=GrupoMusica.class)
@JoinTable(name="MUSICOSENGRUPO",
joinColumns=
@JoinColumn(name="musico_ID", referencedColumnName="id"),
inverseJoinColumns=
@JoinColumn(name="grupo_ID", referencedColumnName="id"))
public List getGrupos() {
return grupos;
}


@ManyToMany(targetEntity=Musico.class)
@JoinTable(name="MUSICOSENGRUPO",
joinColumns=
@JoinColumn(name="grupo_ID", referencedColumnName="id"),
inverseJoinColumns=
@JoinColumn(name="musico_ID", referencedColumnName="id"))
public List getMusicos() {
return musicos;
}


s:convertEntity: Utilizar un selectitems en seam 1.2

<h:selectOneMenu id="aplicacion" value="#{piezaHome.instance.aplicacion}" >
<f:selectItems value="#{aplicacionList.resultList}"/>
<s:convertEntity />
</h:selectOneMenu>

aplicacionList.resultList nos devuelve el listado de aplicaciones disponibles, es decir un list de objetos, solo que la clase Aplicacion extiende de SelectItem y sobreescribe los siguientes metodos de estos:

@Transient
public String getLabel() {
return getName(); //To change body of overridden methods use File | Settings | File Templates.
}

@Transient
public Object getValue() {
return this; //To change body of overridden methods use File | Settings | File Templates.
}

Entonces hay que fijarse que al obtener el value lo que obtenemos es una referencia al objeto(return this), y en el jsf incorporamos la etiqueta de seam s:convertEntity para la conversión ya que de lo contrario nos genera un error de cast exception



martes, 12 de junio de 2007

configurar IntelliJ Idea con seam para TestNG

settings>proyect structure
modules>actualModule

  1. addContentroot
    • add jbossseam folder
    • mark lib as sourcefolder
  2. actual module
    • sourceFolders:
      • embedded-ejb/conf
      • resources
      • src/action
      • src/model
    • testFolders:
      • src/test

Dependencies:
  • proyectDependencies:
    • addClasses: actualModule/lib/*



References to resources outside module: relative



Si te da un error
javax.naming.NameAlreadyBoundException
puede ser que la librería jboss-seam.jar y el source seam/src/main estén arrancando el datasource dos veces!!!


mirar en ejemplos del SEAM!!!

Create the jboss-seam Eclipse project with the following directories
in your source path:

src/main/
examples/blog/src/
examples/blog/resources/
embedded-ejb/conf/

And all jar files from the following directories in your classpath:

lib/
embedded-ejb/lib

3. Run examples/blog/src/org/jboss/seam/example/blog/test/testng.xml
using the TestNG plugin.

lunes, 11 de junio de 2007

package-info jdk6 con clases compiladas con jdk5

clean all
ant run build del seam
ant run build del example

A package-info class contains annotated package and annotation type. These classes are compiled using JDK 6 compiler with target 1.5. JDK 5 fails to load the generated package-info with the following error:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6553734

viernes, 8 de junio de 2007

Idioma japones arreglado

he colocado esto en la cabecera de las páginas correspondientes:
<%@ page contentType="text/html; charset=utf-8" pageEncoding="UTF-8"%>

y en la definicion de los campos de la base de datos:
column charset: utf8
column collate:utf8_bin


EN LOCAL FUNCIONA ok
TENGO QUE IMPORTAR INFO A LOCAL Y EXPORTAR TODO ESQUEMA A SERVER

jueves, 7 de junio de 2007

Tail for Win32

un programa para windows que hace como el tail -f de linux

miércoles, 6 de junio de 2007

deleted object would be re-saved by cascadE

La excepción que lanza es la siguiente:
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [es.cafs.model.RecursoProfesorImpl#33]

y ocurría la segunda vez que intentaba borrar un item(RecursoProfesorImagen) de un Set de un Objeto(Profesor), y además el scope era de Conversation, así que el error era que había que refrescar la entidad principal una vez que se volvia a seleccionar la entidad hija.

lunes, 4 de junio de 2007

Obvio en action script

El archivo y el nombre de clase que la contiene debe coincidir el nombre
Clase Cuadrado debe existir en el path correspondiente pero siempre en un archivo llamado Cuadrado.as

viernes, 1 de junio de 2007

Cambiar el log en jboss console

Hay que editar {JBOSS_HOME}/server/default/conf/log4j.xml
Este es el appender por defecto:

<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="INFO"/>
<param name="Target" value="System.out"/>

<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}:%L] %m%n"/>
</layout>
</appender>

Y habría que cambiar la class de appender por:org.apache.log4j.ConsoleAppender poner el nivel del log a debug para que veamos todos los debug excepto los que no queramos que lo especificamos incluyendo las siguientes categorías

<category name="org.jboss">
<priority value="INFO"/>
</category>

<category name="org.hibernate">
<priority value="WARN"/>
</category>

<category name="javax">
<priority value="WARN"/>
</category>