Affichage TreeView KO / Unable to get row ID 112 for object BCSIWKFSpecBusnDomain

Bonsoir,
je rencontre une problème très curieux d’accès à un TreeView d’un objet héritier.

Le treeView défini sur l’hérité se comporte bien (a priori).
J’ai redéfini sur l’héritier le même TreeView (par duplication) que sur l’hérité.
Au premier affichage (quel que soit le record/rowId), le TreeView s’affiche bien.
Lorsque je ferme leTreeView puis que je ré-ouvre le même record héritier ou un autre (quel que soit le rowId), j’ai une zone vide à la place du TreeView, aucune erreur dans les logs système (back) et une erreur lisible en réponse au POST d’action du get front du TreeView:

{
	"type": "error",
	"response": {
		"message": "Unable to get row ID 112 for object BCSIWKFSpecBusnDomain",
		"level": 2
	}
}

Le problème peut être reproduit sur l’instance bcsi.renault.simplicite.io (Datamaps métier / Contributeur / Domaines de données métier / Domaine test 2).

  • Le fait de réinitialiser la session de l’utilisateur de test (par clear cache ou par simple déconnexion) suffit à débloquer la situation pour afficher à nouveau le TreeView mais dès le premier ré-affichage, le bug revient.
  • J’ai essayé de voir si des searchSpecs ou des filtres résiduels trainaient dans le contexte mais ce n’est pas le cas.
  • Sur cet objet, il n’y a aucun jeu de contrainte manipulant le caractère obligatoire des fk (donc pas d’effet de bord “douteux” sur la logique de join SQL).
  • Les données sous-jacentes sont les mêmes (hérité/héritier) à ceci près que l’arbre de l’hérité est construit sur des données fk dites “de référence” et que l’arbre de l’héritier est construit sur un duplicata “éditable” de ces données de référence (qui sont par ailleurs soumises à un workflow de validation).
  • Ce problèlme fait écho à celui énoncé dans le post suivant: Unable to get row ID –> cache ajax persistent?

Effectivement, il doit y avoir un filtre rémanent positionné sur l’instance TreeView de l’objet hérité.
Ca doit venir des jointures avec les objets enfants qui passent par des setAdditionalSearchSpec sur les FK dans le cas de réflexive ou autre fabrication dynamique compliquée.

Il faudrait debuguer les filtres au moment du select de l’objet racine pour voir pourquoi la requête remonte rien au 2eme passage :

public void preSelect(String rowId, boolean copy) {
    if (isTreeviewInstance()) {
       AppLog.info(getClass(), "preSelect", "object = "+this, null);
       AppLog.info(getClass(), "preSelect", "id filter= "+getField("row_id").getFilter(), null);
       AppLog.info(getClass(), "preSelect", "search-spec = "+getSearchSpec(), null);
       AppLog.info(getClass(), "preSelect", "FK search-spec = "+getField("myParentFk").getAdditionalSearchSpec(), null);
       // ...
    }
}

(Simplicité a été obligé de passer par des additional-search-spec au nveau des champs pour ne pas écraser les search-spec de l’objet lui-même, c’est possible qu’il manque des cas de reset suivant la nature de l’arbre).

Autre méthode bourrine est d’activer toutes les traces SQL et de regarder pourquoi ce “select” ramène rien : param LOG_SQL_USER = yes (ensuite faut fouiller les traces à la date t du test).

Ensuite on verra si le reset du filtre est oublié par Simplicité…
ou s’il est positionné par vos hooks quelque part.

Merci François pour ton retour.
Il y a deux fk dans l’objet: pour chacune, l’additionalSearchSpec=null et le getFilter=’%’ au premier affichage (qui est ok) et au deuxième (qui est ko). Le filtre de l’objectField row_id est aussi ‘%’.
J’ai activé le LOG_SQL_USER à yes…

J’ai repéré dans les logs la différence entre les deux requêtes de sélection des TreeView:

select t.row_id, t.busn_spec_domain_name, t.busn_spec_domain_dataprovider, t.busn_spec_domain_desc, t.busn_spec_domain_datamap_id, t_BusnSpecDomainDatamapId.busn_datamap_name, t_BusnSpecDomainDatamapId.busn_datamap_data_manager, t.busn_spec_domain_domainleader, t.busnspecdomain_busnspecdomain_id, t_BusnSpecDomainBusnSpecDomainId.busn_spec_domain_name, t_BusnSpecDomainBusnSpecDomainId.busn_spec_domain_datamap_id, t.busn_spec_domain_status, t.busn_spec_domain_path, t.busn_spec_domain_notif, t.busn_workflow_status, t.wkf_busn_spec_domain_name, t.wkf_busn_spec_domain_dataprovider, t.wkf_busn_spec_domain_desc, t.wkf_busn_spec_domain_datamap_id, t_WKFBusnSpecDomainDatamapId.busn_datamap_name, t_WKFBusnSpecDomainDatamapId.busn_datamap_data_manager, t.wkf_busn_spec_domain_domainleader, t.wkf_busnspecdomain_busnspecdomain_id, t_WKFBusnSpecDomainBusnSpecDomainId.wkf_busn_spec_domain_name, t_WKFBusnSpecDomainBusnSpecDomainId.wkf_busn_spec_domain_datamap_id, t.wkf_busn_spec_domain_status, t.wkf_busn_spec_domain_path, t.wkf_busn_spec_domain_notif, t.created_dt, t.created_by, t.updated_dt, t.updated_by from bcsi_spec_busn_domain t inner join bcsi_data_map t_BusnSpecDomainDatamapId on (t.busn_spec_domain_datamap_id=t_BusnSpecDomainDatamapId.row_id) left outer join bcsi_spec_busn_domain t_BusnSpecDomainBusnSpecDomainId on (t.busnspecdomain_busnspecdomain_id=t_BusnSpecDomainBusnSpecDomainId.row_id) inner join bcsi_data_map t_WKFBusnSpecDomainDatamapId on (t.wkf_busn_spec_domain_datamap_id=t_WKFBusnSpecDomainDatamapId.row_id) left outer join bcsi_spec_busn_domain t_WKFBusnSpecDomainBusnSpecDomainId on (t.wkf_busnspecdomain_busnspecdomain_id=t_WKFBusnSpecDomainBusnSpecDomainId.row_id) where (t.row_id=112) order by t.row_id asc;
 -> 1 row selected
select t.row_id, t.busn_spec_domain_name, t.busn_spec_domain_dataprovider, t.busn_spec_domain_desc, t.busn_spec_domain_datamap_id, t_BusnSpecDomainDatamapId.busn_datamap_name, t_BusnSpecDomainDatamapId.busn_datamap_data_manager, t.busn_spec_domain_domainleader, t.busnspecdomain_busnspecdomain_id, t_BusnSpecDomainBusnSpecDomainId.busn_spec_domain_name, t_BusnSpecDomainBusnSpecDomainId.busn_spec_domain_datamap_id, t.busn_spec_domain_status, t.busn_spec_domain_path, t.busn_spec_domain_notif, t.busn_workflow_status, t.wkf_busn_spec_domain_name, t.wkf_busn_spec_domain_dataprovider, t.wkf_busn_spec_domain_desc, t.wkf_busn_spec_domain_datamap_id, t_WKFBusnSpecDomainDatamapId.busn_datamap_name, t_WKFBusnSpecDomainDatamapId.busn_datamap_data_manager, t.wkf_busn_spec_domain_domainleader, t.wkf_busnspecdomain_busnspecdomain_id, t_WKFBusnSpecDomainBusnSpecDomainId.wkf_busn_spec_domain_name, t_WKFBusnSpecDomainBusnSpecDomainId.wkf_busn_spec_domain_datamap_id, t.wkf_busn_spec_domain_status, t.wkf_busn_spec_domain_path, t.wkf_busn_spec_domain_notif, t.created_dt, t.created_by, t.updated_dt, t.updated_by from bcsi_spec_busn_domain t inner join bcsi_data_map t_BusnSpecDomainDatamapId on (t.busn_spec_domain_datamap_id=t_BusnSpecDomainDatamapId.row_id) left outer join bcsi_spec_busn_domain t_BusnSpecDomainBusnSpecDomainId on (t.busnspecdomain_busnspecdomain_id=t_BusnSpecDomainBusnSpecDomainId.row_id) inner join bcsi_data_map t_WKFBusnSpecDomainDatamapId on (t.wkf_busn_spec_domain_datamap_id=t_WKFBusnSpecDomainDatamapId.row_id) left outer join bcsi_spec_busn_domain t_WKFBusnSpecDomainBusnSpecDomainId on (t.wkf_busnspecdomain_busnspecdomain_id=t_WKFBusnSpecDomainBusnSpecDomainId.row_id) where (t.wkf_busnspecdomain_busnspecdomain_id=112) order by t.row_id asc limit 20;
-> 0 row selected

La différence est en effet sur l’une des fk qui correspond à une relation de composition (réflexive):

  • requête qui fonctionne (ramène 1 ligne) -> where (t.row_id=112);
  • … suivie de la requête concernant la recherche des fils (relation reflexive): where (t.wkf_busnspecdomain_busnspecdomain_id=112);
  • requête qui ne fonctionne pas (ne ramène aucune ligne) -> where (t.row_id=112) and (t.wkf_busnspecdomain_busnspecdomain_id=112);
  • … suivie de la requête concernant la recherche des fils (relation reflexive): where (t.wkf_busnspecdomain_busnspecdomain_id=112);

Il semble donc que le bout de searchspec concernant la relation réflexive ne soit pas réinitialisé lors du réaffichage du TreeView (quel que soit le rowId).

En poursuivant les tests, je suis revenu sur l’arborescence qui fonctionne (sur l’hérité) et j’ai remarqué des problèmes passés inaperçus précédemment.

  • il y a en fait deux entrées dans l’arbre concernant la relation réflexive (portant le même nom)
  • lorsque la relation réflexive est documentée (count réflexive >0), les deux entrées restituent les mêmes données et tous les counts des autres relations sont à 0, aucune donnée listée dans l’arbre mais le clic sur les branches affichent bien les données en liste dans la zone adjacente
  • lorsqu’elle n’est pas documentée (count réflexive =0), les counts des relations suivantes sont correctement affichés ainsi que les données dans l’arbre

Il semble que la relation réflexive pose un problème dans le rendu de l’arbre même sans être dans un contexte d’héritage.

Illustrations:

  • le domaine métier “Project Deliverables” n’a pas de sous-domaine métier et a 29 caractéristiques.

  • en cliquant sur la branche “Caracétristiques”, la liste des 29 caractéristiques est affichée

  • le domaine métier “Vehicle software” a 4 sous-domaines métier et a 1 data source

  • le count de data sources de l’arbre vaut 0

  • en cliquant sur la branche “Data sources”, la liste de 1 datasource est affichée

Merci Bruno pour tes analyses.
On va regarder ça, il doit y avoir un cas d’oubli de reset des filtres sur les reflexives dans un arbre auto.

Merci pour ton retour.

J’ai tenté d’inhiber cette relation avec un FIX temporaire dans le canReference ( if ( this.isTreeviewInstance() && objectName.equals(this.getName()) ) return false ) -> ça a résolu semble-t-il tous les problèmes sauf pour le doublon d’affichage des sous-domaines métier dans l’arbre de l’héritier.

  • Affichage de la vue arborescente de l’hérité : OK y compris pour la relation réflexive “sous-domaines métier” rendue une seule fois, counts OK avec ou sans sous-domaine
  • Affichage de la vue arborescente de l’héritier : OK (ne plante plus) sauf pour pour la relation réflexive “sous-domaines métier” rendue deux fois

J’ai l’impression que c’est l’héritage du lien qui pose problème (avec deux effets de bords: le doublon de la relation et le search spec additionnel qui n’est pas correctement réinitialisé)…

J’ai trouvé le pb le doublon dans les arbres “automatiques” :

  • en fait il y a un scan des réflexives en premier dans l’arbre, puis une boucle sur les Links donc y compris la réflexive, il va falloir élaguer cette double branche.
  • par contre je ne vois pas encore où certains filtres pourraient rester, car ils sont bien retirés à la fin mais comme on est dans du récursif optimisé en mémoire pour n’utiliser qu’un nombre réduit d’instances d’objet, c’est assez complexe à reproduire.
  • l’héritage n’a pas d’influence car l’objet une fois instancié a une liste de Links hérités ou pas, la notion d’héritage ne sert pas au parcours récursif
  • je pense que les pb de “count à 0” sont liés au même pb de filtre rémanent

A suivre…

Bon, je n’ai pu reproduire et corriger que le problème de branches en double (1 ramenée par la recherche réflexive puis 1 autre via les links automatiques). Ce sera livré dans la journée.

Par contre pour le “count=0” rien à faire, je ne reproduis pas le problème.

La liste filtrée sur le parent id, est bien vide ou conforme au count affiché (sauf si un autre user crée un truc entre temps). D’ailleurs sur la UI, je remarque un truc à améliorer en terme d’UX : il faudrait afficher la clé fonctionnelle du filtre sur l’objet parent dans le header de liste, là comme on filtre sur l’id du noeud parent, la liste de l’instance “tree” ne présente pas de badge de filtre et c’est ambiguë. On va regarder ça.

@bmo
Dans ta copie d’écran, on dirait plutôt que le click sur “Data source” n’ouvre pas la bonne liste ?
En tout cas je ne vois pas “Vehicule software” mais “Embedded software” dans “Objet métier FR” ?

Merci pour tes retours.
Il s’agit bien de la bonne liste (a priori)… pas de problème de ce côté (la datasource 'VESPA" référence l’objet métier “Embedded software” dans le domaine métier “Vehicle software”).

Si le patch résout le problème de double entrée, les problèmes de count et de addSearchSpec rémanant seront peut-être réglés aussi… je teste asap et je reviens vers toi.