Vamos a finalizar la presentación de las direcciones donde lo dejamos en la anterior publicación en el último apartado, recordemos que teníamos que resolver la presentación de las direcciones (CbAddresses) al crear una nuevo cliente (CbCustomer) ya que con el desarrollo inicial no era posible, esta fue la solución planteada:

  1. Crear siempre una entidad CbAddresses al crear cada nuevo cliente.
  2. Ocultar a nivel de creación las direcciones hasta que exista un CbAddresses asociado el cliente, y así, tener un funcionamiento correcto.

 

OpenXava Fin de la primera parte

Definiendo vistas diferentes para crear y actualizar la entidad para mejorar la presentación siguiendo la extensa documentación proporcionada por OpenXava en este caso en el OpenXava How to.Código Xules

 

1. Crear siempre una entidad CbAddresses al crear cada nuevo cliente

 

Vamos a repasar lo explicado al final del capítulo anterior para así tener una visión completa del problema planteado. Empezamos recordando la creación de retrollamadas de OpenXava, esto nos permitirá obtener un funcionamiento más o menos correcto, dejando la creación de las direcciones del cliente para después de su creación ya que no se podrán añadir hasta que el cliente haya sido creado, pero si después, ya que en la creación le vamos a asociar al cliente un idaddresses de la entidad CbAddresses automáticamente, veamos como.

Con @PreCreate se pueden marcar métodos que serán ejecutados antes de persistir algún objeto, en nuestro caso antes de crear CbCustomer nos interesa crear un CbAddresses que se le asignará así automáticamente al cliente CbCustomer. Ahora definimos el método dentro de la clase CbCustomer que vamos a utilizar:

    /**
     * Cuando creamos el cliente creamos la entidad de CbAddresses que lleva
     * asociada, para que después se pueda añadir la dirección al actualizar
     * el cliente.
     */
    @PreCreate
    public void onPreCreate() {
        if (getCbAddresses() == null) {
            CbAddresses cbAddressesAux = new CbAddresses();
            cbAddressesAux = XPersistence.getManager().merge(cbAddressesAux);
            setCbAddresses(cbAddressesAux);
        }
    }

 

2. Ocultar a nivel de creación las direcciones

Lo que nos planteábamos para resolver nuestro problema era ocultar a nivel de creación las direcciones, hasta que exista un CbAddresses asociado el cliente, y así, tener un funcionamiento correcto.

Se puede deducir fácilmente que para conseguir esto vamos a tener que definir dos vistas diferentes una para Crear y otra para Actualizar, esto no lo podemos hacer directamente en las anotaciones y para ello tendremos que modificar el controlador usado por defecto y definir las clases donde les indiquemos las vistas a utilizar en cada caso.

Una vez llegada a esta conclusión la solución parece fácil, pero he de decir que no lo fue, ya que creí que no estaba utilizando correctamente @AsEmbedded, esto implica que vamos a crear un controlador propio, en esto profundizaré en la segunda parte del tutorial, pero ahora necesitamos resolver este problema, así que, lo vamos a explicar.

Del atolladero en que me encontraba me ayudó a salir la extensa y buena documentación de OpenXava, por casualidad consultando el OpenXava How to, llegué a la solución de mi problema en la segunda entrada ¿Cómo usar una vista diferente para crear y para actualizar?, siguiendo sus instrucciones elaboré la mía.

 

Definimos las vistas diferenciadas

Tenemos que definir un vista para crear y otra para actualizar:

@Views({
    @View(name="Crear", members="  .... "),
    @View(name="Actualizar", members=" ... ")
})
public class MiEntidad { ...

Lo que buscamos es no tener en la vista de creación (Crear) la dirección representada por CbAddresses, y si tenerla en la vista de actualización (Actualizar), para ello definimos así las nuevas vista:

@Entity
@Views({
	@View(
			name="Crear",
			members = 	// Vista que usamos para crear el cliente sin la dirección (CbAddresses)
			"customer;"
			+ "customername;"
			+ "cbEnterprise;"
			+ "customeralias;"
			+ "contact;"
			+ "sale, customerpayer, cbPaymentmethod; " +
			"customerstate;"
			+ "identitynumber;"
			+ "cbLanguage; cbCountry; cbCurrency;"
			),
	@View(	name="Actualizar",
			members = 	// Vista que vamos a utilizar cuando ya esté creado la entidad cliente para mostrar la dirección  (CbAddress).
				"customer;"
				+ "customername;"
				+ "cbEnterprise;"
				+ "customeralias;"
				+ "contact;"
				+ "sale, customerpayer, cbPaymentmethod; " +
				"customerstate;"
				+ "identitynumber;"
				+ "cbLanguage; cbCountry; cbCurrency;"
				+ "cbAddresses;"),
	...
})
...
@Table(name = "cb_customer")
public class CbCustomer {

 

Una vez creadas las vistas, donde la única diferencia es que en la de Crear no aparece + «cbAddresses;», necesitamos reflejar los cambios que queremos en nuestro controlador, y para eso, editamos el fichero controladores.xml.

La definición básica de un controlador es la siguiente:

<controladores>
    <var-entorno ... /> ...    <!-- 1 -->
    <objeto ... /> ...         <!-- 2 -->
    <controlador ... /> ...    <!-- 3 -->
</controladores>

 

  • var-entorno (varias, opcional): variable que contienen información de configuración. Estas variables pueden ser accedidas desde las acciones y filtros, y su valor puede ser sobreescrito para cada módulo.
  • objeto (varios, opcional): define objetos Java de sesión del usuario.
  • controlador (varios, obligado):l os controladores son agrupaciones de acciones.
    • nombre (obligatrio): Nombre del controlador en nuestro caso será: MiCustomerControlador .
    • hereda-de (varios, opcional): permite usar herencia múltiple, aquí hacemos la herencia de Typical.
    • accion (varios, obligada): Definición de la lógica a ejecutar cuando el usuario pulse un botón o vínculo. Aquí vamos a definir nuestras dos nuevas acciones: «new» y «search»

Si quieres saber más en la documentación de OpenXava Controladores se explica detalladamente, puedes ver todas la sintaxis de las acciones en el apartado Controlador y sus acciones, no voy a entrar más en detalle porque quería profundizar en este tema en la segunda parte de mi tutorial.

Finalmente, esto implicar refinar la acción new para escoger la vista Crear y la acción search para escoger la vista Actualizar. Primero, definamos nuestro propio controlador, en controladores.xml en la carpeta xava, así:

    <controlador nombre="MiCustomerControlador">
        <hereda-de controlador="Typical" />
        <accion nombre="new" clase="org.xulescode.customerdb.actions.MiAccionNuevo"             imagen="images/new.gif" al-iniciar="true" atajo-de-teclado="F2">
            <usa-objeto nombre="xava_view" />
        </accion>
        <accion nombre="search" por-defecto="si-posible" oculta="true"             clase="org.xulescode.customerdb.actions.MiAccionBuscar"             atajo-de-teclado="F8">
            <usa-objeto nombre="xava_view" />
        </accion>
    </controlador>

 

Asignamos el controlador al módulo

Y ahora asignamos este controlador a nuestro módulo, y definimos la acción de búsqueda para el módulo. Escribimos nuestro módulo de esta manera en aplicacion.xml en la carpeta xava:

    <modulo nombre="CbCustomer">
        <var-entorno nombre="XAVA_SEARCH_ACTION" valor="MiCustomerControlador.search" />
        <modelo nombre="CbCustomer" />
        <controlador nombre="MiCustomerControlador" />
    </modulo>

 

Definimos la lógica de nuestras acciones

Una vez descrito el controlador y el módulo, vamos a escribir la lógica para las clases que hemos indicado, creamos un paquete separado para agrupara nuestras acciones org.xulescode.customerdb.actions. Para MiAccionBuscar vamos a escribir:

package org.xulescode.customerdb.actions;

import org.openxava.actions.*;
import java.util.*;

public class MiAccionBuscar extends SearchByViewKeyAction {
    public void execute() throws Exception {
        Map clave = getView().getKeyValuesWithValue(); // 1
        getView().setViewName("Actualizar"); // 2
        getView().setValues(clave); // 3
        super.execute();
    }
}

 

«Los valores de la clave se han de capturar (1) para que puedan ser restaurados (3) después de la inicialización que hace el método setViewName(…)«, así de claro lo explican en el OpenXava How to
Y para MiAccionNuevo:

package org.xulescode.customerdb.actions;

import org.openxava.actions.*;

public class MiAccionNuevo extends NewAction {
    public void execute() throws Exception {
        getView().setViewName("Crear");
        super.execute();
    }
}

El resultado es el siguiente, al crear un nuevo cliente, se cargará la vista Crear y la pantalla se mostrará así:

Creación de un nuevo cliente cargando la vista Crear

Creación de un nuevo cliente cargando la vista Crear

Una vez creado podemos ir a editar el cliente, y añadir la dirección, con los cambios que hemos realizado se cargará la vista Actualizar con los datos de las direcciones:

Al cargar un cliente ya creado se carga la vista Actualizar

Al cargar un cliente ya creado se carga la vista Actualizar

 

Con esto doy por finalizado la primera parte del Tutorial OpenXava. Espero que te haya sido útil.Código Xules