Acción perdida

2013-06-26
2013-07-10
  • gustavo navarro

    gustavo navarro - 2013-06-26

    hola, agradecería mucho a quien pueda colaborarme:

    tengo mi clase A que tiene una colección interna de la clase B, común y corriente, es decir, simplemente mi clase A me muestra los registros que tengo y cuando le doy en un registro, me lleva al edit, donde tengo dos pestañas, en la pestaña uno tengo los campos para visualizar y editar la información del registro al que le di click, y el la pestaña dos tengo una colección de los registros asociados a este.

    pues bien, en esta colección tengo mis acciones borrar y borrar seleccionados, hasta ahí perfecto, funcionan bien, el problema viene cuando yo, por requerimientos, le metí un PopUp personalizado, un showDialog o ventana modal, con el fin de confirmar la acción a realizar y dar una advertencia, en fin cosas del negocio; una vez que la persona lee el mensaje y acepta las "consecuencias", da clickl en el boton aceptar, este me redirige a la acción de borrado que tiene por defecto OX, RemoveSelectedInCollectionAction, pero aquí es donde me arroja el error, pues aquí se captura el registro al que se le dio eliminar, y lo elimina, o así debería hacerlo, pues como el dialog o alerta se mostro esta acción se pierde, y me arroja el error:

    Ha sido imposible ejecutar la acción Borrar: Es obligado que la vista represente a una colección para poder llamar al método getCollectionSelectedValues()

    y en la trasa me apunta a esta linea donde se produce el error:

    Collection selectedOnes = getMapsSelectedValues();

    Yo me hago a la idea de que como apareció la alerta o dialog, el registro que se capturo se pierde o algo por el estilo, por lo que cuando me redirige a la acción de borrado al intentar capturar el registro que se quiere eliminar no encuentra nada.

    necesito ayuda, si alguien puede ayudarme le agradecería mucho. como hago o como hacerlo mejor. y por especificaciones, no puedo quitar el dialog, pues necesito mostrar un mensaje personalizado, así que el confirm=true de la acción no me es de ayuda.

     
  • Javier Paniza

    Javier Paniza - 2013-06-28

    Hola Gustavo,

    eso ocurre porque la acción la ejecutas desde el diálogo, que es una vista que no contiene una colección.

    ¿Haces un closeDialog() en tu acción de aceptar, la encadena a la de borrar?

    Pon aquí el código tu acción de aceptar y te daré alguna pista más.

    Por simple curiosidad, ¿cuál es el mensaje personalizado que quieres sacar?


    Ayuda a otros en este foro como yo te ayudo a ti.
    ¿Necesitas más ayuda? Usa el soporte profesional de OpenXava

     
  • gustavo navarro

    gustavo navarro - 2013-06-28

    Hola Javier, gracias por responder.

    lo hice de la siguiente forma:

    Copie la clase de OX para eliminar elementos de una colección, RemoveSelectedInCollectionAction, la peguè dentro de mi proyecto y la edité de la siguiente forma:

    1. declaro 1 variable dentro de ella llamada "orden", que es de tipo "int".

    2. cree mi propio controlador, que es una copia del controlador "Collection.removeSelected", pero le agregué un setProperty para que le inserte un valorde "1" a la variable "orden" que creé en el paso anterior. asi quedó el controlador:

    <controller name="RutaRemoveInCollectionOptions">

        <action name="removeSelected" hidden="true" by-default="never"
            image="delete.gif" in-each-row="true"
            class="org.openxava.projectTucan.actions.MyClassRemoveSelectedInCollectionAction">
            <set property="orden" value="1" />
        </action>
    

    </controller>

    de esta forma llamo a mi clase pa remover el elemento y le seteo el valor de "1" a la variable orden.

    1. en mi clase MyClassRemoveSelectedInCollectionAction, agregué un condicional, si el valor de la variable "orden" es "1", me mostrara el dialog, la ventana modal.

    respondiendo a tu pregunta, el mensaje que se muestra es una simple alerta que advierte que si se borra ese elemento, se borraran los elementos que estén asociados a ella y se tendrán que editar nuevamente, ya que usare una función para borrarlos y crearlos nuevamente para cumplir con un requerimiento.

    el dialog se crea con una clase transitoria, que se encuentra totalmente vacía, así:

    public class Alerta {

    }

    y solo la utilizo para mostrar una addWarning, es decir que en esa ventana solo muestro un mensaje así:

    showDialog();
    getView().setTitleId("confirmar_accion_de_borrado");
    getView().setModelName("Alerta");
    addWarning("advertencia_borrado");
    setControllers("DialogButtons");

    como puedes ver le agrego botones o acciones, "setControllers("DialogButtons");", estos controladores son asi:

    <controller name="DialogButtons">

        <action name="borrarElemento" on-init="true"
            class="org.openxava.projectTucan.actions.MyClassRemoveSelectedInCollectionAction">
            <set property="orden" value="2" />
        </action>
    
        <action name="Cancelar" on-init="true"
            class="org.openxava.projectTucan.actions.CancelOptionAction" />
    
    </controller>
    

    de esta manera, se desplegara un dialog o ventana modal con una alerta tipo "Warning" y con dos botones, "Cancelar" y "borrarElemento", el botón "Cancelar"solo me lleva a una clase que me cierra el dialog, así:

    public class CancelOptionAction extends ViewBaseAction {

    public void execute() throws Exception {
        // TODO Auto-generated method stub
        closeDialog(); 
    }
    

    }

    y el botón "borrarElemento" me lleva nuevamente a mi clase MyClassRemoveSelectedInCollectionAction, pero esta ve le para a la variable "orden" el valor de "2", la cual tiene una condicion if que lo captura y lo interpreta, es decir: cuando trato de borrar un elemento, llamo a mi clase MyClassRemoveSelectedInCollectionAction, y le cargo a la variable "orden" el valor "1", esto hace que una condición "if" se ejecute y me muestre el dialog o ventana modal, que tiene dos botones y al oprimir el botón "borrarElemento" me llamara nuevamente a la clase MyClassRemoveSelectedInCollectionAction pero le cargara a "orden" el valor de "2" lo cual se interpreta en otra condición if que tiene la clase y se da por entendido que se ha aceptado el mensaje y se saben las "consecuencias" de borrar dicho elemento y se procede a ejecutar el borrado.

    cuando entra al segundo if de la clase, MyClassRemoveSelectedInCollectionAction, porque se le pasó el valor de "2" a la variable "orden", inmediatamente ejecuto un closeDialog(); para que cierre el mensaje y ya proceda a capturar los valores seleccionados y los elimine, pero aqui es donde esta el problema, puesto que el dialog apareció, aunque lo cerrara y se este visualizando la clase con la colección y los objetos seleccionados que se desean eliminar, me arroja el error que mencioné antes:

    Ha sido imposible ejecutar la acción Borrar: Es obligado que la vista represente a una colección para poder llamar al método getCollectionSelectedValues()

    y en la trasa me apunta a esta linea donde se produce el error:

    Collection selectedOnes = getMapsSelectedValues();

    te adjunto el codigo de la clase MyClassRemoveSelectedInCollectionAction para que lo veas:

    public class MyClassRemoveSelectedInCollectionAction extends CollectionBaseAction {

        public int orden;
    
    public void execute() throws Exception {
        try{                        
                        if (getOrden() == 1) {
                            showDialog();
                getView().setTitleId("confirmar_accion_de_borrado");
                getView().setModelName("Alerta");
                addWarning("advertencia_borrado");
                setControllers("DialogButtons");
                        }
                        if(getOrden() == 2) {
            Collection selectedOnes = getMapsSelectedValues();
            if (!selectedOnes.isEmpty()){
                Iterator it = selectedOnes.iterator();
                while(it.hasNext()){
                    Map values = (Map) it.next();
                    removeElement(values);
                }
                if (isEntityReferencesCollection() && !getCollectionElementView().getMetaCollection().isOrphanRemoval()) {    addMessage("association_removed", getCollectionElementView().getModelName(),getCollectionElementView().getParent().getModelName());
                }
                else {
                    addMessage("aggregate_removed", getCollectionElementView().getModelName());
                }
                getView().recalculateProperties();
                getCollectionElementView().collectionDeselectAll();
            }
        }
    

    }
    catch (ValidationException ex) {
    addErrors(ex.getErrors());
    }
    }

    /**
     * Is called for each selected row with the values that includes the key
     * values. <p>
     */
    protected void removeElement(Map values) throws Exception {
    MapFacade.removeCollectionElement(getCollectionElementView().getParent().getModelName(), getCollectionElementView().getParent().getKeyValues(), getCollectionElementView().getMemberName(), values);
    }
    

    public int getOrden() {
    return orden;
    }

    public void setOrden(int orden) {
        this.orden = orden;
    }
    

    }

    como mencioné, el error se presenta al obtener los valores seleccionados, ya que cuando aparece el Dialog como que se pierden o no los obtiene, también arroja errores al tratar de obtener las vistas, no logro manejarlas bien, intente utilizar getPreviousView, pero no tuve éxito, y otros intentos fallidos, eso es todo, si me puedes colaborar te lo agradecería mucho. gracias.

     
  • Javier Paniza

    Javier Paniza - 2013-07-01

    Hola Gustavo,

    El problema es que en cuando orden == 2 estás en el diálogo que es una vista sin colección por eso el código no te funciona. O bien cierras el diálogo, o bien reescribes el código para usar la vista "de abajo".

    Quizás la primera opción es la más sencilla, pruébala:

    if(getOrden() == 2) {
        closeDialog();
        Collection selectedOnes = getMapsSelectedValues();
    

    Ayuda a otros en este foro como yo te ayudo a ti.
    ¿Necesitas más ayuda? Usa el soporte profesional de OpenXava

     
  • gustavo navarro

    gustavo navarro - 2013-07-03

    Hola Javier, gracias por responder.

    por accidente borré esa linea, pero lo tengo tal como dices y aún así me sale el error, pero logre dar con una solución al declarar una variable estatica.

    no es muy bonita la solución, por ello quiero saber si hay una mejor manera de hacerlo.

    gracias.

     
  • Javier Paniza

    Javier Paniza - 2013-07-05

    Hola Gustavo,

    no es muy bonita la solución, por ello quiero saber si hay una mejor manera

    Dime como has usado esa variable estática e intentaré proponerte alguna alternativa.


    Ayuda a otros en este foro como yo te ayudo a ti.
    ¿Necesitas más ayuda? Usa el soporte profesional de OpenXava

     
  • gustavo navarro

    gustavo navarro - 2013-07-07

    asi lo hice:

    public class MyClassRemoveSelectedInCollectionAction extends CollectionBaseAction {

    public int orden;
    static Collection selectedOnes;//esta variabe me guarda los valores seleccionados, funciona parecido a un objeto de sesion
    static Map keyMyClass;//igual con esta, cuando entro por segunda vez, es decir, cuando en el popUp acepto el borrado 
    //y este me redirige a esta clase, los valores persisten, aun estan gurdados.
    
    public void execute() throws Exception {
        try {
            if (getOrden() == 1) {//cuando quierre borrar elementos el controler me settea el valor de uno a la variable orden y por ello entrará aquí              selectedOnes = getMapsSelectedValues();
                if (selectedOnes.isEmpty()) {
                    addWarning("seleccione_un_elemento_a_remover");
                } else {
                    getCollectionElementView().collectionDeselectAll();
                    showDialog();//me muestra el popUp
                    getView().setTitleId("confirmar_accion_de_borrado");
                    getView().setModelName("Alerta");
                    addWarning("advertencia_borrado_myclass");//esto me muestra un mensaje tipoWarning en el PopUp
                    setControllers("MyClassDialogOptions");
                }
            } else {//despues ver el mensaje en el popUp y aceptar las consecuencias, 
            //se settea el valor de dos a la variable orden y por ello entrara aqui.
    
                closeDialog();//se cierra el dialog
    
                if (!selectedOnes.isEmpty()) {//se valida que si se seleccionaron valores, 
                //creo que esto se prodria haber hecho primero y seria mejor pero por ahora lo dejo asi
                    Iterator it = selectedOnes.iterator();
                    while (it.hasNext()) {
                        Map values = (Map) it.next();
                        removeElement(values);
                    }
                    //despues de haber borrado todo ejecuto una funcion que hace unas acciones sobre la BD
                    getView().recalculateProperties();
                    getView().setModelName("MyClass");//creo que esta linea es innecesaria, creo.
                    getView().refresh();
                    MyClass myClass = (MyClass)MapFacade.findEntity("MyClass", getView().getKeyValues());
                    Query query = XPersistence.getManager().createNativeQuery("select * fcn_change_service_myclass(:idmyclass)");
                    query.setParameter("idmyclass", myClass.getId());
                    Boolean confirm = (Boolean) query.getSingleResult();
    
                    if(confirm){
                        System.out.println("exito en la ejecucion");
                    }else{
                        System.out.println("fallo en la ejecucion");
                    }
                }
            }
        } catch (ValidationException ex) {
            addErrors(ex.getErrors());
        }
    }
    
    /**
     * Is called for each selected row with the values that includes the key
     * values.
     * <p>
     */
    protected void removeElement(Map values) throws Exception {
    
        //System.out.println("values: " + values);
        MapFacade.remove("MyClassService", values);//cambie el codigo y hago un borrado directo, 
        //como mencioné antes, muchas variables que eran pedidas de la vista no las capturaba,
        //pues el popUp me borraba o hacia que se perdiera dicha informacion.
        addMessage("asociacion_borrada_con_exito");
    
    }
    
    public int getOrden() {
        return orden;
    }
    
    public void setOrden(int orden) {
        this.orden = orden;
    }
    

    }

     
  • Javier Paniza

    Javier Paniza - 2013-07-09

    Hola Gustavo,

    el problema de usar una variable estática no es de estilo, sino que ... bueno que te vas a hartar de reir cuando varios usuarios usen a la vez tu aplicación.

    Yo probaría primero usar getPreviousView(), algo así:

    Collection selectedOnes = getPreviousView().getCollectionSelectedValues();
    

    Y si esto no funciona usa un objeto de sesión que puedes inyectar en tus acciones con @Inject. Los objetos de sesión son locales para cada sesión de usuario, no como una variable de estática que es global para toda la VM.

    Por cierto, no he visto donde das valor a selectedOnes.


    Ayuda a otros en este foro como yo te ayudo a ti.
    ¿Necesitas más ayuda? Usa el soporte profesional de OpenXava

     
  • gustavo navarro

    gustavo navarro - 2013-07-10

    si tienes razón, probaré lo del elemento sesión, el selectedOnes si esta sino que como que como la pagina es angosta no se ve, corre la barra inferior del comentario todo hacia la derecha y lo veras; el interprete de la página no es perfecto y por eso me pego la linea del selectedOnes = getMapsSelectedValues(); a un comentario, por ello es que aparece como si fuera parte del comentario de arriba asi:

    public void execute() throws Exception {
    try {
    if (getOrden() == 1) {//cuando quierre borrar elementos el controler me settea el valor de uno a la variable orden y por ello entrará aquí selectedOnes = getMapsSelectedValues();

     

Log in to post a comment.