8 liens virtuels/symboliques vers un même objet : problème de rafraichissement des listes filles

Tags: #<Tag:0x00007f4918771330>

Bonjour,

Je créé ce ticket afin de garder une trace des échanges que j’ai eu avec Alistair sur la problématique que nous avons sur des liens symboliques.

Le besoin est de créer plusieurs liens symboliques vers un même objet. Ils fonctionnent bien sur le premier objet père, mais pas sur le second ou les listes dans les onglets sont vides, alors que le nombre d’entrées indiqué est correct.
Tout n’est peut être pas parfaitement retranscrit, auquel cas je m’excuse.
La solution serait donc de créer des liens physiques, mais de modifier les searchSpecs dans les initList ou les postSearch.

Merci et bonne journée,

Vincent

Bonjour,

Votre besoin est assez atypique et ne doit pas être un cas prévu par la plateforme. Je ne comprends pas du tout comment vous avez configuré votre objet et les liens virtuels pour pointer vers un même objet.

Je passe votre besoin en feature request.

  • Vous pouvez essayer de créer des foreign keys facultatives/vides/masquées, et agir avant la recherche au preSearch mais vous aurez un soucis avec l’outer join de cette FK que Simplicité va ajouter à la requête (et ne ramènera rien sur l’id du parent), le code spécifique pour s’en sortir ne sera pas simple.

  • Vous pouvez aussi créer 2 objets hérités A1 et A2 d’un objet A sans lien virtuel, avec chacun un seul lien virtuel vers votre objet B + getTargetObject pour revenir à l’objet A

  • Sinon vous devez créer une Vue habilitée à votre objet A qui contient une liste (item de type recherche de B sans filtre) que vous pouvez filtrer spécifiquement au preSearch.

Je viens de faire un essai et cela fonctionne très bien, j’ai pu créer 2 liens vers un même objet en passant par 2 chemins différents dans les search-spec des liens virtuels.
.
Je repasse le ticket en support.
Votre second lien virtuel doit être mal paramétré quelque part.

Exemple fait sur la démo : afficher les produits depuis un client :

  • une VK1 qui ramène tous les produits commandés par un client (en passant par ses commandes)
  • une VK2 qui ramène tous les produits commandés ayant eu au moins 1 contact par un client (en passant par ses commandes et ses contacts).

J’ai essayé de faire suivre les VK pour marquer par où ça passe sur le modèle :

VK1

VK2

Résultat :

VK 1 : on a bien 3 commandes donc 3 produits commandés listés

VK 2 : on a bien 1 commande avec au moins 1 contact = un produit listé

Voici le paramétrage des 2 VK installables sur la démo.
J’ai refais un test sur une 4.0 à jour sans problème.

Field.xml (8.1 KB)

Si comme vous le dites, le second onglet affiche bien le “count” mais rien dans la liste c’est que vous avez un problème dans votre “select” ou que vous agissez dans un hook inadapté (le postSearch n’est pas appelé par le count par exemple).

  • Activez les sondes sql pour tracer toutes les requêtes SQL dans les logs : LOG_SQL_USER=yes + clear-cache (attention c’est très verbeux donc à limiter au temps d’un test unitaire)

  • Normalement le “select count(*)” et le “select de toutes les colonnes” de votre panel fils se suivent dans les logs quand vous accédez à l’onglet, et le where est strictement identique si vous ne faites rien de particulier entre temps.

  • Mettez en commentaire les hooks iniList / getCount / preSearch / postSearch, ou vos filtre/search-spec par code pour voir s’il y a une différence.

@vincent.achard
@AWheeler
@Anthony.Courtois

Francois,

Le soucis au niveau de ce ticket est que les filtres sql sont corrects, mais [row_id] n’est substitué par rien lors de l’exécution de celui ci.

Je pensais que l’erreur venait du fait que les liens ne pouvaient pas être comme on le voulait, mais si ce n’est pas la cause, alors je ne sais pas vers quoi me tourner.

En commentant le code que tu as indiqué, je n’ai pas de changement de comportement.

Quelles informations il te faudrait pour mieux t’aiguiller sur le problème?

Merci

Bonjour,

Il convient d’utiliser [ROWID] comme shorthand ou [VALUE:row_id] comme token, mais [row_id] est une vieille syntaxe deprecated V2 qui doit encore être supportée. Essayez avec une syntaxe V4 dans un premier temps.

Sinon il faut voir si le contexte du parent est présent ou perdu sur votre 2eme onglet.
Dans le hook preSearch (après votre code spécifique), il faut debugger ce que contient le contexte de votre objet lié (liste fille) :

ObjectDB parent = getParentObject();
String fk = getParentObjectRefField();
String v[] = getParentValues();
String parentId = v[0]; // => substitué dans [ROWID]

A mon avis vous avez du code incompatible avec vos différents contextes/besoins dans votre objet.
Il sera toujours possible de forcer ce contexte par code si on sait identifier le contexte de navigation (positionner un paramètre avec le row_id quand on ouvre l’objet père, pour le détecter quand on affiche la liste fille initList = forcer un search spec ou le contexte parent via storeParentContext)

Si un de ces objets est vide/null; rien ne peut se substituer. Sans accès à votre instance / votre paramétrage (héritage, nommage… ?) + code des hooks, impossible de savoir pourquoi l’id du parent n’est pas substitué. Pouvez vous nous déployer une instance pour qu’on regarde (en MP) ?

Autres questions :

  • Avez vous installé l’exemple pour voir la différence de paramétrage avec le votre ?
  • Votre lien n°2 fonctionne-t-il seul (si vous supprimez celui qui fonctionne) ?

Vous pouvez cloner votre instance pour faire le test temporairement sans casser votre paramétrage.
Je ne vois aucune raison que les onglets se mélangent les pinceaux car ce sont des instances séparées / identifiées par leur foreign-key respectives. Que le lien soit virtuel ou non, chaque onglet connait toujours son parent, vous ne passez par l’algo de substitution, reste à savoir pourquoi.

Voici un extrait de code simplifié à mettre dans le preSearch de votre liste fille vide pour regarder ce que fait le “if” qui permet d’ajouter la search-spec du lien dans le “where”. Si le [row_id] n’est pas substitué il faut regarder là-dedans ce qui ne va pas :

ObjectDB obj = this;
StringBuilder where = new StringBuilder();
ObjectDB parent = obj.getParentObject();
String fk = obj.getParentObjectRefField();
for (ObjectField f : obj.getFields()) {
	// Specific filter in foreign key ?
	if (parent!=null && fk!=null && !Tool.isEmpty(f.getRefSearchSpec()) && fk.equals(f.getName())
	&& (parent.getName().equals(f.getRefObjectName()) || parent.getName().equals(f.getRefObjectContext()))) {
		// The link search spec
		String search = new String(f.getRefSearchSpec());
		// The parent values
		String[] v = obj.getParentValues();
		for (int j=0; v!=null && j<parent.getFields().size(); j++) {
			String name = parent.getField(j).getName();
			String value = v[j];
			search = search
				.replace("["+name+"]", value) // V2
				.replace("[VALUE:"+name+"]", value); // V3
			// Other shorthand syntaxes
			if (Tool.isInternalRowIdField(name))
				search = search
					.replace("[rowid]", value)
					.replace("[ROWID]", value);
		}
		if (search.indexOf("[row_id]")<0 && search.indexOf("[VALUE:row_id]")<0) {
			if (where.length()>0) where.append(" and ");
			where.append("(").append(search).append(")");
		}
	}
}
// The compiled (virtual) link
AppLog.info(getClass(), "makeWhere", where.toString(), null);

@vincent.achard
@AWheeler

Je viens de tester ce remplacement, mais rien n’a changé, la substitution n’est toujours pas faite.

J’ai débuggé la portion de code que tu as partagé.

ObjectDB parent = getParentObject(); // => Null
String fk = getParentObjectRefField(); // => Null
String v[] = getParentValues(); // => Null
String parentId = v[0]; // => Null

Cela explique pourquoi la substitution n’est pas faite.

Je compte regarder asap la portion de code de ton deuxième message afin de pouvoir continuer à te répondre.

Merci beaucoup pour ton aide,

ps:
J’ai poussé le code actuel sur l’instance que vous avez partagé.

Merci pour ton retour, l’objet a donc perdu son contexte parent, il y a un verbe qui doit être appelé dans les hooks et qui “reset” ce context.
La portion de code n’apportera rien de plus si le parent est null.

Essaye de faire le test sans l’onglet qui fonctionne.

Je n’ai pas les accès, envoie moi les infos en MP :

  • pwd designer
  • login/pwd de test
  • le nom de l’objet à regarder et des 2 liens

Bonjour François,

Je viens de créer un dossier administratif (de row_id 2, Toto Biscotte), ainsi qu’un insee complémentaire associé.

Dans ce cas la, l’onglet insee complémentaire du dossier indique bien qu’il y a une entrée, mais quand on clique dessus, la liste est vide.

Merci beaucoup pour ton aide

Il y a des erreurs SQL quand on accède au dossier :

Il y a une UNION qui s’insère dans les requêtes. Ca doit venir de vos search-spec :
on ne peut pas faire un count avec une union de colonne, impossible de retrouver la source qui positionne cette union quand on affiche le dossier “toto”

select count(t.row_id) from sng_contrat_avenant_modif t left outer join sng_soutien_scolaire

where (t.row_id in(select sng_contrat_avenant_modif.row_id
from sng_contrat_avenant_modif
left join sng_dossier_detenu on sng_contrat_avenant_modif.sng_coam_insee = sng_dossier_detenu.sng_dode_insee
where sng_dossier_detenu.sng_dode_insee =‘1234567890’ and sng_contrat_avenant_modif.sng_coam_cmg_fk is not null
union select sng_contrat_avenant_modif.row_id
from sng_contrat_avenant_modif
left join sng_insee_complementaire on sng_contrat_avenant_modif.sng_coam_insee = sng_insee_complementaire.sng_inco_insee_drfip
left join sng_dossier_detenu on sng_insee_complementaire.sng_inco_insee_alliance = sng_dossier_detenu.sng_dode_insee
where sng_dossier_detenu.sng_dode_insee=‘1234567890’ and sng_contrat_avenant_modif.sng_coam_cmg_fk is not null))

Je ne pense pas que ce soit lié au problème de liste fille vide.

L’onglet affiche bien la ligne INSEE si on fait un “Recharger” du dossier, ou qu’on revient ensuite depuis la liste sur le formulaire sans cliquer sur l’onglet. Par contre la liste se vide dès qu’on clique sur l’onglet => ça sent un problème de synchronisation entre les appels back et front.

image

L’objet Dossier a beaucoup de code/liens… + script front pour calculer un graphique donc il va falloir brider les hooks pour voir, mais en première lecture je ne vois rien d’étrange.

On va devoir passer l’instance au debugger en back, car côté front il n’y a rien d’anormal.

Je requalifie le POST, il y a au moins 8 liens virtuel sur votre objet :

sngBulleDodeId
sngHiscoDodeId
sngDemobDodeNonArchId
sngDemobDodeArchId
sngDepsDodeVirtual
sngFdlDodeId
sngIncoDodeId qui ne marche pas
sngHistoRifsDodeVirtual

Ce qui ne simplifie rien à l’analyse.
Il faudrait les renommer plus clairement avec un suffix gente “Virtual” ou “VK” au lieu de “Id”.

De plus il faut voir pourquoi certains ont été paramétrés en “delete restrict” ? car normalement la règle restrict/null/cascad se positionne sur un vrai lien physique. Ca doit foncitonner mais c’est bizarre, les liens virtuels sont en delete cascade = “ignore” car ce sont des vues logiques sans règle métier.

Suite au passage du code au debugger, on voit que dans certains cas les valeurs en mémoire de l’objet Parent (le Dossier) côté serveur sont perdues, à mon avis un resetValues doit être appelé quelque part. Je ne vois pas où dans Simplicité car nous n’avons jamais rencontré ce problème, jamais un panel/onglet force un vidage de l’objet parent en mémoire côté serveur.

Comme le remplacement dans la search-spec du Link a besoin des valeurs du parent (row_id…), tout était substitué par vide (votre erreur SQL).

Pour retrouver le criminel, il faudrait fouiller dans les 25 liens / requêtes de “count” des nbre de lignes des onglets affichés (cad initList, preSearch… de tous les objets liés qui sont appelés de façon asynchrone mais bien de façon chainée en back).

Comme ça semble impossible vue la taille de vos objets, on a pu rendre Simplicité plus robuste en forçant un select avant la substitution si jamais le parent a été vidé (ou a changé de record). Du coup la substitution ne sera plus vide, même si du code mal positionné quelque part ou appelé de façon asynchrone fait un resetValues (ou équivalent) avant.

Il faudra attendre le prochain build V4 pour vous mettre à jour et tester que ça fait bien le job dans votre cas. En remote debug pour moi ça a fonctionné, l’onglet n’est plus jamais vide / plus d’erreur SQL.