PO.save y beforeSave en libertya 9.10

Inicio Foros Foro principal Desarrolladores PO.save y beforeSave en libertya 9.10

  • Este debate está vacío.
Viendo 3 entradas - de la 1 a la 3 (de un total de 3)
  • Autor
    Entradas
  • #31313
    Javier Ader
    Participante

    Buenas. Estoy estudiando la parte de persistencia a objetos (basandome en cursos anteriores, el ej de los Juguetes) y cree una tabla en la base de datos, todos sus datos en el diccionario, ventanas, etc, todo eso ok. Despues cree la clase “X_” , y la clase “M” que heredan de PO.
    Ok, la intención era poner una validación en el beforeSave que retorne false bajo determinadas condiciones…
    El tema es que este beforeSave no logra ser llamado (hice un rebuild, supongo que por ahi no viene el tema). Mirando desde donde era llamado este metodo protegido me di cuenta que solo era llamadao desde PO.save; asi que puse un breackpoint en este y corri el proyecto. Entro en el breakpoint muy al inicio (incluso antes de loguearme) para salvar una fila en MSession; e.d, el save parececia ser llamado. Hice un resume, abri la ventana para crear un juguete o modificar un juguete y ni PO.save ni MJuguetes.beforeSave eran llamados!
    No se bien cual es la razón… y lo que mas me confunde es que para otras entidades si es llamado. El nombre de la clase parece estar correcto ya que el constructor de MJuguete es llamado (pero otra cosa que me parece rara es que es llamado, solo cuando uno guarda una modificación o guarda un juguete nuevo y no lo es cuando se leen los juguetes…).
    Hay algo que cambio en la version 9.10? o cual es la razón que no llame ni al PO.save ni al beforeSave para la entidades juguetes pero si para las otras? Habra algo en el diccionario de datos que modifique este comportamiento?

    AGREGO: mmm, al parecer hay algo raro o algo me esta faltando; mirando la consola se ve, al intentar guardar una modificación:

    Code:
    ===========> M_Table.getPO: (rs) – Table=M_Juguetes,Class=class org.openXpertya.model.MJuguetes [11]
    java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.openXpertya.model.M_Table.getPO(M_Table.java:528)
    at org.openXpertya.model.M_Table.getPO(M_Table.java:571)
    at org.openXpertya.model.MTable.dataSavePO(MTable.java:2191)
    at org.openXpertya.model.MTable.dataSave(MTable.java:1536)
    at org.openXpertya.model.MTab.dataSave(MTab.java:893)
    at org.openXpertya.apps.APanel.cmd_save(APanel.java:1662)
    at org.openXpertya.apps.APanel.actionPerformed(APanel.java:1492)
    at org.openXpertya.apps.AppsAction.actionPerformed(AppsAction.java:292)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    caused by: java.lang.IllegalStateException: No PK nor FK – M_Juguetes
    at org.openXpertya.model.PO.setKeyInfo(PO.java:1391)
    at org.openXpertya.model.PO.load(PO.java:1284)
    at org.openXpertya.model.PO.(PO.java:176)
    at org.openXpertya.model.PO.
    (PO.java:141)
    at org.openXpertya.model.X_M_Juguetes.
    (X_M_Juguetes.java:25)
    at org.openXpertya.model.MJuguetes.
    (MJuguetes.java:16)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.openXpertya.model.M_Table.getPO(M_Table.java:528)
    at org.openXpertya.model.M_Table.getPO(M_Table.java:571)
    at org.openXpertya.model.MTable.dataSavePO(MTable.java:2191)
    at org.openXpertya.model.MTable.dataSave(MTable.java:1536)
    at org.openXpertya.model.MTab.dataSave(MTab.java:893)
    at org.openXpertya.apps.APanel.cmd_save(APanel.java:1662)
    at org.openXpertya.apps.APanel.actionPerformed(APanel.java:1492)
    at org.openXpertya.apps.AppsAction.actionPerformed(AppsAction.java:292)

    ===========> M_Table.saveError: Error – Table=M_Juguetes,Class=class org.openXpertya.model.MJuguetes [11]
    ———–> MTable.dataSave: M_Juguetes – No Persistent Object [11]

    y al intentar guardar uno nuevo

    Code:
    ———–> M_Table.getPO: No transaction Constructor for class org.openXpertya.model.MJuguetes (null) [11]
    ===========> M_Table.getPO: (id) – Not found – Table=M_Juguetes, Record_ID=0 [11]
    ———–> MTable.dataSave: M_Juguetes – No Persistent Object [11]

    Me parece que el me tiene que estar faltando “el constructor de transaccion” y la api de reflexión obviamente no lo encuentra (que no se bien que sera este constructor… los dos constructores, el que toma el id y el que toma el resultSet, en MJuguetes están creados; estos simplemeente llaman al constructor de la clase padre con los mismos parámetros)

    #34141
    Federico Cristina
    Superadministrador

    Buenas,

    La clave del error está aca:

    Code:
    at org.openXpertya.model.M_Table.getPO(M_Table.java:528)

    O sea, no puede recuperar el PO correspondiente. Podés poner un brake ahí a ver que está ocurriendo. Corroborá además algunas cosas:

    1) Si la tabla se llama M_Juguetes, la clase debe llamarse MJuguetes (a veces se nos escapa una S final).

    2) La tabla creada deberá tener los campos obligatorios: M_Juguetes_ID (respetar mayusculas y minusculas!), CreatedBy, AD_Client_ID, etc…

    3) A nivel SQL deberás setear la PK de M_Juguetes.

    Saludos,
    Federico

    #34142
    Javier Ader
    Participante

    Así era nomás: M_Juguetes_ID estaba en el diccionario en minúsculas (y eso que lo advirtieron bastantes veces jajaja…). Lo que me confundió fue más que nada el segundo error, ya que el constructor ERA llamado y por lo tanto encontrado via reflexión (tanto en un update como en un insert), y obviamente MJuguetes.java era encontrado lo más bien. También, aún cuando se muestra este error (en la consola, no en la aplicación), los cambios realmente se persisten; supongo que antes estos casos se recurre a otro mecanismo de persistencia que “bypasa” a PO y sus descendientes.
    En M_Table.getPO (528) se encuentra:

    Code:
    try {

    Constructor constructor = clazz.getDeclaredConstructor(new Class[] { Properties.class, ResultSet.class, String.class });
    PO po = (PO) constructor.newInstance(new Object[] { getCtx(), rs, trxName });

    return po;

    } catch (Exception e) {

    log.log(Level.SEVERE, “(rs) – Table=” + tableName + “,Class=” + clazz, e);
    errorLogged = true;
    log.saveError(“Error”, “Table=” + tableName + “,Class=” + clazz);
    }

    y pienso que lo que falla ahí no es el GetDeclaredConstructor, si no que la invocación (constructor.newInstance) en la linea siguiente dispara una excepción, porque el constructor en PO (invocado desde el constructor de MJuguetes) no encuentra la clave primaria y dispara una excepción…
    La clave entonces creo que esta en (que dicho sea de paso, aparece en la traza, pero no entiendo porque en el “medio” de la misma)

    Code:
    caused by: java.lang.IllegalStateException: No PK nor FK – M_Juguetes
    at org.openXpertya.model.PO.setKeyInfo(PO.java:1391)
    at org.openXpertya.model.PO.load(PO.java:1284)
    at org.openXpertya.model.PO.(PO.java:176)

    PO.setKeyInfo (1381-1391)

    Code:
    // Search for Parents
    ArrayList columnNames = new ArrayList();
    for (int i = 0; i < p_info.getColumnCount(); i++) { if (p_info.isColumnParent(i)) columnNames.add(p_info.getColumnName(i)); } // Set FKs int size = columnNames.size(); if (size == 0) throw new IllegalStateException("No PK nor FK - " + p_info.getTableName());

    el size == 0 era true al parecer porque p_info.isColumnParent daba false para todas las columnas. Supongo que para p_info una columna es “parent” si es un ID o un clave foranea (segun el diccionario de datos). La info de la columnas creo que es precomputada en POInfo.loadInfo… pero este metodo simplemetne hace un select de de inner joins sobre AD_Table, AD_Column y un par de tablas mas… y isParent para la columna termina siendo lo que diga AD_Column.IsParent en la base de datos… asi que para seguir rastreando porque no me marca algo como “parent” cuando no se respeta al convención de nombres hay que ir a mirar por otros lados (en particular el codigo que modifica el diccionario de datos)… pero bueno ya el rastreo se hace muyyyyyyy largo; obviamente en algún lugar se tiene que hacer respetar la convención…
    En cualquier caso la conclusión que hago es: respetar la convención de nombres (al menos para las columnas ID, supongo también que para cualquier otra no?)… y que el constructor de una clase de persistencia de objetos sea llamado no significa mucho; hay que verificar que retorne correctamente y no con una excepción (que era lo que me pasaba a mi…)

    PD : también, el segundo error que me mostraba claramente esta “mal”… el constructor se encuentra, el tema es que su invocación tira una excepción (el código debe tener un try catch similar que pueda fallar por las dos razones, pero en el catch al mostrar la causa del error solo se contempla que lo que falle sea la reflexión y no la invocación)

Viendo 3 entradas - de la 1 a la 3 (de un total de 3)
  • Debes estar registrado para responder a este debate.