Tuesday 31 January 2012

Curso ADF 11g - Parte 3

Tema : Personalización de Componentes Entidad.

Si ha culminado con éxito las 2 primeras partes del curso, probablemente se estará  preguntando en que momento se programará. Bien tal como se ha visto en las primeras lecciones prácticamente hemos usado el asistente para generar los componentes. Esos pasos fueron vitales, porque nos brinda el esqueleto de lo que será nuestra aplicación.  Lo que toca ahora, es personalizar los componentes.

Este paso, no sólo implicará programar, sino principalmente tratar de apoyarnos al máximo en las funcionalidades  del framework para  solucionar funcionalidades recurrentes con configuraciones sencillas.  En este post cubriremos las personalizaciones de los componentes Entidad. Posteriores post, mostrarán personalizaciones sobre los View Objects y los módulos de aplicación.

Requerimiento:

  • Oracle Jdeveloper 11g. 11.1.1.3
  • Oracle Database Express 11g
  • Haber culminado la parte 2 del tutorial. Ir al capitulo 2.

Capítulos Anteriores

Parte 1: Creación del Modelo de Datos.

Parte 2: Creación de Componentes de Negocio

Opcional : 

Si no culmino los capítulos anteriores y quiere empezar desde este capítulo, puede descargar el siguiente código para continuar el curso.

 Código previo.

 

Generalmente en los proyectos que desarrollo hay requerimientos comunes que generalmente lo soluciono con la herramienta. Estos son :

  • Inicializar los valores de los identificadores únicos. (Primary Key de las tablas). Es decir, inicializar con un correlativo este campo. Para eso, usaremos un objeto sequencial en la base de datos que es la mejor práctica en estos casos.
  • Inicializar campos de fecha. Existen muchas veces campos fecha, en nuestros desarrollos, que los usuarios nos piden que se inicialice, por ejemplo, con la fecha actual. Bueno existe una manera sencilla de hacer esto que lo explicamos en este post.
  • Validaciones.  Nuestra aplicación maneja Movimientos y Detalles. Eso implica que un movimiento podría tener algún detalle. Se imagina un movimiento sin detalle?. Eso implicaría información inconsistente y obviamente debemos evitarlo en nuestra aplicación. Bueno también veamos como hacer esa validación con la herramienta.
  • Nuestra entidad Movimiento (Padre), tiene un atributo total, que debería acumular los subtotal de todos sus detalles. En este post mostraremos como programar esta regla.

Bien vemos como  implementar fácilmente estas reglas.

INICIALIZAR CORRELATIVO

1. Como comentamos al inicio, una de las actividades más comunes en el desarrollo de una aplicación, es inicializar los datos correlativos que están asociados generalmente a la PK de una tabla. En esta caso, la mejor práctica es hacer uso de un objeto sequence de la base de datos, que no asegurará usar un único valor para estos atributos. Bien empecemos creando los objetos sequence en nuestra BD.

Ejecutemos los siguientes comandos en la BD (conectado con el usuarios ventas):

create sequence cliente_seq start with 100;

create sequence producto_seq start with 100;

create sequence movimiento_seq start with 100;

 

image

2. Ahora en la bd crear triggers que actualice la pk de la tabla Cliente;


create or replace trigger insert_cliente_id
  BEFORE INSERT ON cliente
  FOR EACH ROW
DECLARE
    new_id number;
  BEGIN
    SELECT cliente_seq.NextVal
     INTO new_id from Dual;
    :new.cliente_id := new_id;
  END;

 

image

Por favor repita lo mismo para crear los triggers asociados a la tabla Producto y Movimiento

 

3. Bien, regresemos a la aplicación ADF y haga doble clic sobre la entidad Cliente.

imagen1

4. En la parte izquierda se mostrará una pantalla con la configuración asociada a la entidad Cliente. Note que la sección Attributes muestra los atributos de los clientes. Si hacemos doble clic sobre el atributo ClienteId se abrirá otra pantalla que permitirá configurar las propiedades de ese atributo.

image

Existen muchos indicadores en esta pantalla, parece una consola de avión, pero con un poco de calma podemos entender las más  importantes.

Region Attribute.

Type: No es necesario hacer una explicación larga sobre esto, sin embargo es importante destacar que el asistente define el tipo de dato adecuado según el tipo de BD  de la columna asociada.

Value Type y Value: Algunas veces queremos inicializar un atributo con un valor especifico ó en base a una formula. Bien estos campos justamente ayudan a eso. El “Value Type” determina el tipo de inicialización que usaremos, si es “Literal”, esperará un valor fijo en el campo “Value”, por el contrario si seteamos el valor a “Expression”, se esperará una formula (Se puede usar groovy) para asignar un valor.

Persisten: Indica que el atributo es persistente contra la BD, es decir hay una columna que almacenará los valores de ese atributo. La sección inferior “Database Column”, brinda la configuración asociada a esta propiedad.

Mandatory: Significa Obligatorio.

Region Updatable

Acá se determina si se permitirá laa actualización de este campo. Los valores Always y Never son evidentes en su uso. En el caso de While New indicará que ese atributo sólo se actulizará cuando ingresemos un nuevo registro. Es decir no permite actualizarse.

Region Refresh After

Algunas veces los valores de los atributos, se cargarán posteriormente a una acción de la BD. En esa región se indica después de que operación se volverá a actualizar este valor.

 

5. Bien, luego de la explicación teórica, apliquemos lo aprendido. Para asociar el atributo ClienteId con el resultado del triger de BD simplemente cambiemos su propiedad Type por DBSequence. Pulse Apply.

image

Analicemos que ha cambiado con esta configuración.

 

Region Atributte.

Se han desabilitado los campos Persitent  y PrimaryKey. Obviamente al ser campos asociados a un correlativo de BD ambas propiedades se asumen como requeridas para este cambio.

El campo mandatory se ha “ des seleccionado”, porque se hace esto?, bueno se asume que el valor de este atributo provendrá de la BD posterior a la inserción. Es decir el usuario no colocará ningún valor durante el ingreso de datos y en consecuencia la aplicación no debe validar si este campo esta vacío ó requerido.

Region Updatable

La herramienta ha colocado esta propiedad en “While New”, tiene sentido?. Pues si, porque este campo será sólo completado durante la inserción. Es decir no debe ser modificable. Es como si dejáramos modificar una Pk de base de datos.

Region Refresh After.

Se seleccionó Insert. Esto significa que el valor de atributo se actualizará posterior al ingreso de datos. Cuando vamos a crear un nuevo cliente, lo que va a pasar es que vamos a crear una instancia de la entidad, como un objeto, bien esa instancia mediante alguna acción volcará su contenido contra la tabla cliente, despues de insertarse entonces el valor del campo CLIENTE_ID de la tabla será regresado al objeto para actualizar el atributo cliente id de la instancia de la entidad. (Refresh After Insert).

 

Pulse Ok para regresar al editor.

 

6. Para probar este funcionamiento, ejecute el módulo de aplicación. Clic derecho sobre él y RUN.

image

 

7. Elija la Vista ClienteVO y pulse el boton (+)

image

 

8. Complete los datos. Note que el campo ClienteId se ha cargado con un valor temporal (-2) en este ejemplo. Es decir, no es necesario llenarlo.

Pulse el boton Commit image

image

 

9. Notará que una vez que se grabo el registro se cargó el verdadero valor del atributo ClienteId, lo que demuestra que nuestra configuración ha sido correcta.

image

 

Por favor, repita los pasos, desde el punto 3 para inicializar los atributos ProductoId de la entidad Producto y MovimientoId de la entidad Movimiento.  Cuando termine de realizar estos ejercicios puede continuar con el siguientes instrucciones del curso. No continúe si no terminar los ejercicios por que pasos posteriores requerirán que se haya culminado estos ejercicios.

 

ASIGNAR FECHA

10. Nuestra siguiente actividad, consiste en inicializar el atributo Fecha de la entidad movimiento con la fecha actual.

Bien, esta actividad es sencilla. Haga dobhe clic sobre la entidad Movimiento.

 

image

 

11. A continuación, seleccione la categoría Attributes y haga doble clic sobre el atributo Fecha.

image

 

12. La pantalla que se muestra permite configurar las propiedades del atributo Fecha. Tal como se explicó en el paso 4, podemos usar las propiedades “Value Type” y “Value” para definir los valores iniciales que tendrá las instancias de la entidad. En este caso usaremos Groovy, que es un lenguaje de Scripting, y que ADF puede usar para elaborar expresiones que se evalúan en tiempo de ejecución. Puede conocer más del uso de Groovy en ADF en el siguiente enlace.

http://radio-weblogs.com/0118231/2007/05/22.html

13. Entonces, los pasos que haremos será elegir “Expression” en la propiedad  Value Type y en el campo Valor colocará adf.currentDate. Pulse Ok.

image

 

14. Realicé el paso 6, para probar los componentes. Elija ahora la vista MovimientoVO.

image

 

15. Pulse el botón image para agregar un nuevo registro y note que se ha inicializado el campo Fecha con el valor actual.

image

 

VALIDAR MOVIMIENTO

16. En este escenario, lo que tenemos que lograr es evitar data inconsistente entre el movimiento y el detalle. La regla es que debemos evitar que un movimiento se grabe sin detalles. Esta última regla,determina una relación de dependencia entre ambas entidades que se logra por medio de una relación de composición.  Vamos a personalizar a la entidad la relación de Movimiento-Detalle a una de tipo composición. Haga doble clic sobre la Relación DetalleMovimientoFkAssoc

image

17. En el editor, elija la categoría “Relationship” y en la sección Beahivior seleccion la casilla “Composition Association”

image

 

El colocar una relación como composición brinda muchos beneficios, por ejemplo  si se realiza una transacción en la que estén involucradas las entidades movimiento y detalle, primero persistirá los datos del movimiento(padre) y luego de los hijos. Otra ventaja es que abre la posibilidad de utilizar validaciones que involucren ambas entidades. Justamente en esta caso aprovecharemos de esta configuración para validar que los movimientos tengan por lo menos un detalle.

 

18. Ahora haga clic sobre la entidad Movimiento, seleccione la categoría  “Business Rules”. En esta pantalla se puede colocar validaciones de manera declarativa sobre cualquier entidad. Las validaciones declarativas pueden aplicarse a nivel de atributo y entidad. Por ejemplo podría validar que el precio de un producto sea mayor a 0 ó aplicar un expresión con groovy para realizar esta validación.

Si quiere conocer más de este tipo de validaciones puede ir al siguiente enlace.

http://docs.oracle.com/cd/E15586_01/web.1111/b31974/bcvalidation.htm

 

Bien en esta caso hagamos clic  derecho sobre la sección “Entity Validators” y elija la opción New Validators.

 

image

 

19. La siguiente pantalla permite definir la validación que queremos aplicar sobre la entidad.  Las validaciones están compuestas de tres tabs que tienen la siguiente finalidad.

El primero “Rule Definition”, permite definir que regla determina que el dato procesado es Valido.

El segundo “Validation Execution ” determina alguna condición  para aplicar esa regla de validacíon.

El tercero “Failure Handling” ayuda a personalizar el mensaje que queremos lanzar al usuario cuando la validación no ha sido cumplida.

 

Los cambios para la primera pestaña, será : el tipo de regla será Collection y la operación que usaremos será “Count”. Además, el Operator será Greater Than, el  campor Compare With “Literal Value” y el valor colocado en el Literal Value será 0.

Que significa todo esto?. Que se hará una validación del operador count de la relación, es decir del conteo de los detalles. Luego, se espera que el valor obtenido “Sea Mayor que” un valor literal que ingresemos. En este caso 0.

image

 

20. Ahora elija la pestaña “Failure Handling” y coloque el mensaje que se disparará cuando no se cumpla la validación.

 

image

 

21. Pulse Ok, grabe los cambios y ejecutemos el modulo de aplicación, como en el paso 6, para probar este cambio. Haga clic sobre el View Link MovimientoDetalleVL, para ver la un movimiento con sus detalles.

image

22. Ahora para ver el efecto de validación. Pulse el botón image a nivel del movimiento.

 

image

23. El movimiento no tiene detalles, así que  pulsemos el botón Commit para intentar Grabar la transacción. Note que aparecerá el mensaje que se definió previamente y de esta manera se realizó correctamente la validación.

image

 

CALCULO DE UN ATRIBUTO TOTAL EN BASE A DETALLES.

24. Toca ahora realizar el calculo del atributo “Total” de la entidad Movimiento (Padre), en base a la sumatoria de los atributos “Subtotal” de la entidad Detalle (Hijo).  Esta regla es lógica, pues se supone que si usted maneja una factura que puede incluir muchos detalles de venta, esperaría que la sumatoria de todos los detalles (subtotales) se consoliden en un atributo asociado a la entidad Padre (Movimiento), llamada Total.

Si bien existe una relación entre ambas entidades aún será necesario colocar instrucciones que permitan actualizar el campo Total del Padre. Bien en este caso si requeriremos programar, y para eso necesitamos una clase que permita colocar esas reglas. Sin embargo, como habrá notado prácticamente no hemos tenido acceso a clase java alguna que nos permita hacer esa programación. Eso se debe a que el framework por default utiliza descriptores “inicialmente”  asociados a los componentes construidos. Eso lo puede usted comprobar expandiendo el componente Movimiento, por ejemplo, y descubriendo que tiene asociado un archivo XML que justamente representa dicho componente.

image

 

25. Bueno, en nuestra situación necesitaremos programa el componente Movimiento, así que habilitaremos un clase Java asociada a dicho componente. Para eso haga doble clic sobre dicho componente, elija la categoría Java y haga clic sobre la opción “Edit java options”

 

image

 

26. Bien , esta consola ofrece la opción de asociar una clase java a la entidad y personalizar su comportamiento vía código. Seleccione la opción “Generate Entity Object Class” y también la casilla de Accesors.

 

image

 

27. Note que ahora la entidad Movimiento ya no tiene asociado sólo un xml, sino que ahora hay una clase java (MovimientoImpl.java)  asociada que usaremos para modificar su comportamiento. La clase también tiene los métodos geters y setters de la entidad, por lo que podríamos hacer operaciones sobre estos métodos.

 

image

 

28. Haga doble clic sobre la clase MovimientoImpl.java y agreguemos el siguiente método.

 

public void calcularTotal(){

  float totalDetalle=0;
  RowIterator iteDetalle = this.getDetalle();
 
  while(iteDetalle.hasNext())
  {
      Row filaDetalle = iteDetalle.next();
      totalDetalle = totalDetalle + ((Number)filaDetalle.getAttribute("Subtotal")).floatValue(); 
  }
 
  this.setTotal(new Number(totalDetalle));

}

 

Analicemos el código que hemos colocado. Esté método se encuentra en la entidad movimiento y lo que hace es :

Recorrer todos los detalles asociados y  acumular sus subtotales en la variable totalDetalle

float totalDetalle=0;
RowIterator iteDetalle = this.getDetalle();
while(iteDetalle.hasNext())
{
Row filaDetalle = iteDetalle.next();
totalDetalle = totalDetalle + ((Number)filaDetalle.getAttribute("Subtotal")).floatValue();
}

 

Finalmente asignamos el valor calculado en el atributo Total de la entidad Movimiento.

this.setTotal(new Number(totalDetalle));

 

29. Este método permite actualizar el atributo Total del Movimiento. Sin embargo,  esté método no se ejecutará automáticamente, será necesario ubicar alguna acción que provoque este método. Si analizamos bien, esté cálculo se debe realizar cuando se agrega, modifica o elimina un detalle. Veamos como provocamos esto.

Haga doble clic sobre la entidad Detalle, de manera similar al paso 25, para habilitar la creación de clases. Tal como se muestra a continuación.

image

 

Revisemos que significa cada uno de sus checks.

  • Generate Entity Object Class: Esto permite asociar una clase Java a la entidad.

Sobre esta clase se crearán los métodos que se indican a continuación.

  • Accesors: Crea los métodos get y set de cada atributo. Habilítalo.
  • Data Manipulations Method: Crea el método doDML(). Este es un método muy útil que se invoca cada vez que se realiza una operación de INSERT,UPDATE ó DELETE contra la Base de datos.  Justamente en la implementación de este método colocaremos la invocación al método de calculoTotal().Habilítalo

Nota adicional: Nosotros ejecutamos este método cuando pulsamos el botón de guardar cambios en la base de datos (image) desde el módulo de aplicaciones.

  • Create Method. Crea el método Create(), que es un metodo que se dispara cuando se instancia un nuevo registro de la entidad. Es similar a un constructor de la entidad. No lo habilite.

Nota adicional: Nosotros ejecutamos este método cuando pulsamos el botón de Adicionar un nueva Fila (image) desde el módulo de aplicaciones.

  • Remore Method. Crea el método remove() que como su nombre indica cuando se elimina una instancia de la entidad. No lo habilite

Nota adicional: Nosotros ejecutamos este método cuando pulsamos el botón de Eliminar una Fila (image) desde el módulo de aplicaciones.

Pulse Ok y Grabe los cambios.

 

30. Bien, haga doble clic sobre la clase DetalleImpl.java y ubíquese en el método doDML(). Sobre escríbalo de la siguiente manera.

 

protected void doDML(int operation, TransactionEvent e) {
    this.getMovimiento().calcularTotah();
    super.doDML(operation, e);
  
}

 

31. Notemos lo siguiente, el método doDML se ejecuta cada vez que el usuario confirma una acción de agregar modificar o eliminar sobre la entidad detalle. Nosotros hemos incluido la siguiente línea

this.getMovimiento().calcularTotal();

Que lo que hace es calcular los detalles del movimiento asociado y actualizar el atributo total del mismo.

 

image

32. Probemos este último cambio. Ejecute el modulo de aplicación y ubíquese en el viewlink que permite ver los datos del movimiento y detalle,

image

 

33. Agregué un nuevo detalle usando el botón de Agregar Fila sobre los detalles

 

image

 

34. Ingrese valores pertinentes a ese detalle.

 

image

 

35. Finalmente, aplique los cambios de toda la transacción.

 

image

 

36. Finalmente notemos que el valor del total del movimiento se ha actualizado correctamente.

image

 

37. Felicitaciones, ha culminado la personalización de las entidades en su aplicación ADF. Capítulos posteriores permitirán personalizar las vistas y el módulo de aplicación. Si quiere comparar su resultado, con nuestro código puede descargarlo del siguiente enlace.

CODIGO FUENTE.

21 comments:

  1. informacion muy util que cuesta encontarla tan simplificada Gracias

    ReplyDelete
  2. Un muy buen curso, muy explicativo. Me puedes ayudar con esta duda: Estoy trabajando con Oracle JDeveloper 11g Release 2(11.1.2.2.0), cuando le di generar clase movimiento, por ejemplo getTotal venia: public BigDecimal getTotal, y en ClienteId venia con integer, y claro al poner tu codigo me generaba error, entonces comparando los 2 codigos fuentes me di cuenta, es por la nueva versión? o porque hay que configurar algo para que tome todo Number?. Eso mismo vi que me paso en lo de fecha cuando vi el atributo en lo tuyo decia Date pero en el mismo por defecto aparecia Timestamp. Gracias de antemano por la ayuda

    ReplyDelete
    Replies
    1. Caroll, a veces cuando se migran proyectos de versiones o bien de equipo (desconozco la razón) los tipos de datos en nuestros BCs pierden este tipo de referencias. Bueno, si lo que quisieras es cambiar los datos así como Plinio va mostrando en el paso a paso de su tutorial, deberás de dar click en el botón “Browse…” que aparece después de Type. Todos los tipos de datos que utiliza Plinio en este tutorial los encuentras en el paquete “oracle.jbo.domain” bastará con que localices los tipos de datos los selecciones y vuelvas a compilar tu proyecto. Saludos

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Buenas, te quería hacer una pregunta, tengo el problema que al actualizar algun dato d ela entidad (campo, valor por defecto, etc) no puedo hacer que la página tome el cambio, me podrías decir como prodecer una vez que se hace un cambio en una entidad que ya está siendo utilizada, como hacer para que los cambios repercutan en las páginas???

    muchas gracias

    ReplyDelete
    Replies
    1. Pablo,
      Debes entender que cualquier cambio en la entidad NO impacta automaticamente sobre las paginas. Existe 2 capas adicionales que tienes que actualizar.
      1. El View Object.
      2. Los bindings de la página. (previo refresco del data Control)

      Algunas veces es más facil volver a arrastrar el componente a la pagína. Sin embargo,te recomiendo estudiar los view objetos y los bindigns para que tengas una mayor comprension del framework

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Estimado Plinio estoy tratando de correr este codigo, pero me muestra el error abajo descrito, podrias ayudarme a ver la solucion. atte.
    public void calcularTotal(){

    float totalDetalle=0;
    RowIterator iteDetalle = this.getDetalle();

    while(iteDetalle.hasNext())
    {
    Row filaDetalle = iteDetalle.next();
    totalDetalle = totalDetalle + ((Number)filaDetalle.getAttribute("Subtotal")).floatValue();
    }

    this.setTotal(new Number(totalDetalle));

    }

    Project: C:\Plinio\Blog\codigo\ventas\Model\Model.jpr
    C:\Plinio\Blog\codigo\ventas\Model\src\com\ventas\model\entities\MovimientoImpl.java
    Error(298,7): reached end of file while parsing
    Error(296,34): java.lang.Number is abstract; cannot be instantiated

    ReplyDelete
    Replies
    1. Hola Amigo.

      Verifica que estes importando la clase Number de Oracle.

      coloca en la cabecera import oracle.jbo.domain.Number.

      Con eso deberia solucionarse. Sino, puedes descargarte la solucion del problema y comparar los imports con los tuyos.

      Suerte

      Delete
  7. Hola Plinio.

    Cuando selecciono la opción Update while New del Entity Object, al momento de crear la forma de captura en el jsff, el input text aparece como read only. ¿Es posible que se vea deahabilitado y no como read only?

    Saludos.

    ReplyDelete
    Replies
    1. Si es posible. En ese caso, cambia la propiedad Updatable en la entidad de ese campo por Always
      Luego, sobre el mismo control, en la propiedad Disabled colocalo en true.


      Saludos

      Delete
  8. Hola!
    Les dejo el código del cálculo para JDeveloper 12c con JDK7
    public void calcularTotal(){
    float totalDetalle=0;
    RowIterator iteDetalle = this.getDetalle();
    while(iteDetalle.hasNext()){
    Row filaDetalle = iteDetalle.next();
    totalDetalle = totalDetalle + ((Number)filaDetalle.getAttribute("Subtotal")).floatValue();
    }
    this.setTotal(new BigDecimal(totalDetalle));
    }

    ReplyDelete
  9. Hola que tal Plinio, estoy tomando el curso y no habia tenido problemas hasta este punto cuando ingreso el código para actualizar el Total. El problema es que no me actualiza el total, estoy debugueando el código y solamente entra una vez al ciclo while, es decir, solamente trae el valor del subtotal que acabo de insertar

    ReplyDelete
  10. Hola de nuevo :) ya resolví el problema. No se por qué, pero JDeveloper 12, cuando generé MovimientoImpl agrega dos referencias Detalle; es decir, Detalle y Detalle1 y en DetalleImpl agrega dos referencias Movimiento, Movimiento y Movimiento1 ademas el ENUM no trae los métodos de get y put para cada propiedad.

    Lo que tuve que hacer generar esos metodos para el ENUM y en vez de llamar al metodo getMovimiento llamé a getMovimiento1

    Alguna opinion acerca de por qué me pone dos referencias Detalle y movimiento??

    ReplyDelete
  11. Hola que tal,


    Pues como comentaba en otro foro. Estoy trabajando con este esquema de base de datos pero con MySQL. El problema este:

    Al ejecutar la operación CreateInsert sobre la entidad de Detalle que esta en relación con la entidad de Movimiento marca la excepción:


    La entidad de detalle Detalle con la clave de fila oracle.jbo.Key[0 null ] no se puede encontrar o invalida su entidad propietaria.


    Esta excepción sólo ocurre cuando lo ejecuto sobre una vista, ya sea JSF o jspx, si ejecuto el mismo procedimiento pero sobre el AppModule funciona correctamente, inserta la(s) fila(s) sobre Detalle y puedo hacer commit. Mi aplicación la tengo configurada de la sig. manera:

    1. La Base de Datos que estoy usando es MySQL, por lo tanto en el campo de MovimiendoId lo tengo como autoincremental pero en la aplicación lo tengo como Integer. Usando MySQL me parece que ADF no proporciona un campo de tipo autoincremental asi que para darle funcionalidad completa, en la Clase implementadora de la Entidad de Movimiento al hacer la operacion DML_INSERT en el metodo doDML ejecuto un metodo que una vez insertado el registro en la tabla de la BD ejecuta un selex max para obtener el id asignado para el registro de movimiento y una vez que obtenido le hago un setAttribute para que en pantalla actualize el MovimiendoId.

    2. Tengo una asociacion entre las entidades de Movimiento con Detalle con una cardinalidad de 1 a muchos. En la asociación tengo seleccionado el checkbox de "Composition asociation" y el de "Cascade update key attributes".

    3. Tengo un ViewLink que conecta las entidades Movimiento con Detalle a traves de MovimientoId de Uno a Muchos respectivamente.

    He intentado hacer la operación CreateInsert mediante:

    a. Haciendo la operación en un Taskflow.
    b. Creando la operacion como un binding.
    c. A traves de código en un metodo en la clase implementadora del Appmodule:

    ViewObject viewMov = findViewObject("MovimientoVo");
    Row movExt = viewMov.first();
    RowIterator itMov = (RowIterator)movExt.getAttribute("DetalleVo");
    Row newLine = itMov.createRow();

    itMov.insertRow(newLine);
    newLine.setAttribute("MovimientoId",new Integer(0)); newLine.setAttribute("ProductoId",new Integer(1));

    Pero de la tres formas marca el mismo error. Dentro de mi vista tengo un boton para hacer el CreateInsert de la entidad Movimiento y otro para hacer el CreateInsert de Detalle, y el error se lanza unicamente cuando primero hago el CreateInsert de movimiento. Si primero hago un CreateInsert de Detalle se inserta correctamente la fila.

    Otra forma en la que trabaja de manera correcta es desactivando el checkbox de "Composition association" pero así pierde funcionalidad. Espero poder aver sido lo más preciso.

    ReplyDelete
    Replies
    1. Hola definitivamente el problema radica en el Id del detalle (PK). En oracle cuando cuando usas un DBSequence se genera un valor temporal en memoria el cual finalmente se estable al hacer commite en un Store Procedure.

      No he trabajado con MySql, pero podria recomendarte cambiar tu modelo para que la Primary Key del Detalle no dependa del Pk del Movimiento.

      Luego pienso que podrias probar 2 cosas.

      1. En el metodo "Create" de la clase Detalle, puedes incluir la lógica para generar el Id de Detalla al momento de instanciar cada objeto detalle.

      2. Trasladar toda la logica de creacion del Id del detalle al metodo doDML pero del DETALLE.

      Por favor prueba estas opciones y me avisas si se pudo resolver.

      Saludos

      Delete
  12. This comment has been removed by the author.

    ReplyDelete
  13. Hola Plinio,

    Pes ya se solucionó el problema. Ya desde mi vista puedo insertar detalles y hacerles commit.

    Lo que tuve que hacer es debuguear el código que puse en el comentario principal y solamente así vi que el MovimientoId trae un valor por default de 0. Aún no se por que le da ese valor, en el defaultvalue de la entidad de Movimiento no trae nada que pueda darle ese valor de 0.

    Entonces lo que hice al codigo fue:

    Row movExt = viewMov.first();
    movExt.setAttribute("MovimientoId",0);

    Pero le puedo pasar cualquier valor, no únicamente 0 y funciona. Y posteriormente inserto la fila:

    RowIterator itMov = (RowIterator)movExt.getAttribute("DetalleVo");
    Row newLine = itMov.createRow();

    itMov.insertRow(newLine);

    Y todo funciona perfectamente. Quiero creer que este problema fue por que estoy usando el campo movimiento_id en la tabla Detalle como foreign key de la tabla Movimiento.

    Le agradezco enormemente su ayuda y su tiempo. Muchas gracias, saludos.

    PD.
    ¿Todavía se va a realizar el taller de ADF en Junio?

    ReplyDelete
  14. Perfecto!, El taller lo estamos planeando, pero tan pronto tengamos info lo publicamos por nuestro sitio web.

    ReplyDelete
  15. Hola buenas a todos.

    Soy novato en Adf y Java. Estoy siguiendo tu tutorial al pie de la letra.
    Hasta ahora todo perfecto pero al intentar escribir codigo se me presenta el primer problema.

    Intento añadir un metodo a la clase y no me deja, en structure me da un error: Expecting Class

    He copiado el codigo del ejemplo y si que me deja incluir el metodo, añadiendolo tambien en structure.

    Se que sera una chorrada pero estoy encallado y no hay manera.
    Trabajo con jdeveloper 12c no se si tendra algo que ver.

    Gracias de antemano.

    Un saludo!!!!!

    ReplyDelete
    Replies
    1. puedes mandarnos el mensaje de error?. saludos

      Delete