#316 Componente Duplicado al usar @OneToOne y @OnChange en un atributo de una entidad referida

v4.8.1
closed
nobody
None
5
2013-11-14
2012-12-20
No

He detectado un problema al usar @OneToOne y @OnChange en un atributo de una entidad y tratar de cargar el modulo de la entidad referida en el atributo; para aclarar no es cargando el módulo de la entidad con la anotación @OnChange.

A continuación pongo un caso de ejemplo con dos entidades: Cheque y Transaccion relacionadas @OneToOne con el mappedBy en cheque y con una anotación @OnChange en Transaccion. Lo que ocurre es que cuando se intenta cargar el módulo de Cheque openxava genera la excepción org.openxava.util.XavaException: Componente duplicado: Cheque

Si se elimina la anotación @OnChange no se produce la excepción. El código de ejemplo a continuación:

/////////////////////////////////////////////////////////////
package com.siger.model;

import javax.persistence.*;
import org.openxava.annotations.*;

@Entity
@View(members = "codigo")
@Tab(properties = "codigo")
public class Cheque {

    @Id @Column(length=3)
    @Required
    private int codigo;

    @OneToOne(mappedBy = "cheque", optional=true)
    private Transaccion transaccion;

    public int getCodigo() {
        return codigo;
    }
    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }
    public Transaccion getTransaccion() {
        return transaccion;
    }
    public void setTransaccion(Transaccion transaccion) {
        this.transaccion = transaccion;
    }    
}
/////////////////////////////////////////////////////////////
package com.siger.model;

import javax.persistence.*;

import org.openxava.annotations.*;
import com.siger.action.*;

@Entity
@View(members = "codigo; cheque")
@Tab(properties = "codigo")
public class Transaccion {

    @Id @Column(length=3) 
    @Required
    private int codigo;

    @OneToOne(optional = true, cascade=CascadeType.ALL)
    @DescriptionsList(descriptionProperties = "codigo")
    @OnChange(TransaccionOnChangeAction.class)
    private Cheque cheque;

    public int getCodigo() {
        return codigo;
    }
    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }
    public Cheque getCheque() {
        return cheque;
    }
    public void setCheque(Cheque cheque) {
        this.cheque = cheque;
    }    
}
/////////////////////////////////////////////////////////////
package com.siger.action;

import org.openxava.actions.*;

public class TransaccionOnChangeAction 
       extends OnChangePropertyBaseAction {
    public void execute() throws Exception {
        System.out.println(getClass().getName() + "execute()");
    }
}
/////////////////////////////////////////////////////////////

Otras cosas que pude investigar es que el MetaComponent de Cheque se crea y carga por primera vez a través de Transaccion como atributo de Cheque por medio del processAnnotations de la anotación @OnChange de Transaccion, y luego cuando le toca cargar a Cheque en sí falla porque ya esta cargado en MetaComponent.components ...

Tentativamente veo un posible arreglo verificando que el pojo registrado en MetaComponent no sea el mismo para lanzar la excepción, pero como no conozco la arquitectura de OpenXava es posible que el arreglo sea mejor hacerlo en el código que procesa la anotación OnChange, de todas formas a continuación escribo la solución que veo, cambiando la linea 69 de MetaComponent.get así:

- throw new XavaException("duplicate_component", name);

+ MetaComponent prev = (MetaComponent) previous;
+ if (!prev.getMetaEntity().getPOJOClassName().equals(r.getMetaEntity().getPOJOClassName())) {
+     throw new XavaException("duplicate_component", name);
+ }

Discussion

  • Javier Paniza
    Javier Paniza
    2013-08-27

    • status: open --> closed
    • Group: v4.5.1 --> v4.8.1