Utilisation des resolver de valeurs dans les ViewLink

Généralités

Introduction

Ce document décrit l’utilisation des resolver de valeurs dans les ViewLink du fichier de configuration. Cette fonctionnalité vous permet de rendre le fichier de configuration complètement dynamique.

Principes

Auparavant, il existait trois types de paramètres dans les ViewLink du fichier de configuration :

  • business : paramètre provenant du niveau de vue immédiatement supérieur (ou d’une vue de niveau supérieure si l’attribut viewName est utilisé)
  • public : les paramètres provenant de l’URL
  • value : directement la valeur du paramètre, on utilise ce type habituellement en projet une fois que le paramétrage est figé.

Il arrivait donc parfois que l’on se retrouve dans l’obligation d’écrire des valeurs « en dur » alors que ces valeurs peuvent provenir du paramétrage. C’est souvent le cas dans certaines requêtes qui contiennent des sous-requêtes permettant de récupérer la valeur d’un type de tiers par exemple. Cela a comme effet principal d’alourdir considérablement les requêtes et le nom de paramètre public que l’on passe sur les URL.

Depuis la version ACE 1.3, il vous est possible de rendre le fichier de configuration complètement dynamique avec comme avantages principaux :

  • Plus de valeur « en dur » alors qu’elles sont issues du paramétrage,
  • Allègement de la configuration,
  • Dynamisme lors de la mise en place pour les projets « in-run »,
  • Simplification des requêtes avec un gain de performances,
  • Nouvelles possibilités d’extensions vers la couche métier avec les « fournisseurs de valeurs ».

Fonctionnement

Implémentation technique

Le socle technique d’ACE (technicalframework) propose cette nouveauté fonctionnelle aux couches supérieures (métier et application). Le pilotage est réalisé dans les ViewLink, XDME est lui aussi impacté par cette nouveauté.

Afin de répondre à une utilisation la plus large et la plus souple possible, il a été décidé d’appliquer un principe équivalent aux resolver de requêtes, à savoir :

  • Le socle propose l’implémentation technique et la modification du schéma (configuration.xsd)
  • Le socle définit les règles sur les couches abstraites et sur les interfaces
  • Le métier gère la spécialisation de ces resolver et fournit les références vers la couche application (dans le fichier de configuration)

Dans le cas présent, nous parlerons de « resolver de valeurs » ou de « fournisseurs de valeurs ».

L’implémentation réalisée ce jour permet de résoudre principalement 3 types de valeurs :

  • Des valeurs de paramètres (PPE) de la table PARAV,
  • Des valeurs liées au paramétrage général (table PEV)
  • La valeur du CODSOC physique des tables (couple entité, segment optionnel : table MEV).

Extrait du schéma : ViewLink

Le nouvel attribut est nommé « solverName » car il s’agit d’un nom logique (non directement la référence à la classe Java).

Extrait du schéma : Param_def

Une sous-section de la section « application » permet de définir de manière globale les solver de tout type que l’on va exploiter dans la configuration. C’est une manière de généraliser leur exploitation avec un seul écran dans XDME.

Description des différents attributs :

  • name : le nom « logique » du solver
  • type : value ou active pour le cas qui nous préoccupe dans ce document
  • solverClass : la référence à la classe Java
  • value : la valeur par défaut (aucune utilisation ou exploitation pour le moment, cet attribut est réservé à un usage ultérieur).

Dans XDME, cette section est définie sous la forme d’un onglet général :

Packages

L’implémentation au niveau de socle se fait principalement dans les classes gérant les ViewLink, ainsi que dans le package :

  • fr.ACE.technicalframework.application.solver
  • on trouve ici un ensemble de classes abstraites et d’interfaces qui permettent d’étendre le développement vers la couche métier.

Dans la couche métier, les différents solver livrés en standard se trouvent dans le package suivant :

  • fr.generix.metier.solver

Exemple d’utilisation opérationnelle

Une liste de clients comporte deux paramètres obligatoires sur la table principale (table TIE) :

  • Le code société : champ CODSOC
  • Le type de tiers : champ TYPTIE

On a donc une requête définie dans la configuration qui, en plus de prendre ces champs là en compte, va comporter des paramètres optionnels (entourés de crochets : []).

La requête ressemble à ceci :

MevTie.CODSOC = ? AND TYPTIE = ? [ AND SIGTIE LIKE ?] [ AND NOMTIE LIKE ?] …

Dans XDME, le passage de paramètres ressemble à ceci :

Vue XML de cette partie de la configuration :

Syntaxe complète

Toutes les valeurs à exprimer doivent être saisies en majuscule, il s’agit d’un choix de développement.

Définition des espaces de nommage

Les espaces de nommage d’ores et déjà disponibles sont les suivants :

  • PEV : Le paramétrage de la fonction - typé "événement" ou "tiers" - correspondant à la table PEV
  • PPE : les paramètres associés à la cible de paramétrage, usuellement nommés PPE (Paramètres Pour Evénements)
  • MEV : résolution des valeurs de CODSOC_PHY

Exemples de valeurs opérationnelles :

  • PPE :TYPCLI.A1
  • PPE :TYPMAG.A2
  • PPE :PACPRO.N1
  • PPE :RECCTS.L1
  • PEV :TYPTIE
  • MEV :PRO
  • MEV :TIE.CLI

Liste des valeurs publiées pour les PPE (le nom est séparé par un « . ») :

  • A1 à A3
  • N1 à N5
  • M1 et M2
  • D1 à D3
  • L1 (correspond au champ LIBPAR de la table PARAV)

Liste des valeurs (équivalent aux noms de champs) publiées pour le paramétrage de la fonction (PEV) :

  • ACHVTE : Code Achat/Vente
  • TYPEVE : Type d'événement
  • CODETA : Code état géré de l'événement
  • VALETA : Code état validé de l'événement
  • SOLETA : Code état soldé de l'événement
  • TYPTIE : Type de tiers géré
  • ACHVTO : Code Achat/Vente origine
  • TYPEVO : Type d'événement origine
  • ETAEVO : Code état de l'événement d'origine
  • ACHVTS : Code Achat/Vente source
  • TYPEVS : Type d'événement source
  • CODETT : Nature de l'événement

Attention

Les valeurs spécifiées sont sensibles à la casse, « PPE:TYPMAG.A1 » n'est pas équivalent à « ppe:typmag.A1 » par exemple. La casse doit donc être respectée.

Fonctions utilisables

Il peut être intéressant dans certains cas de fournir la possibilité de réaliser directement des calculs sur les valeurs. A titre d’exemple, on peut noter que la clé d’un texte libre (table TXT) est une concaténation de plusieurs champs avec remplissage par des « 0 ».

Certaines fonctions sont donc implémentées pour répondre à ce besoin. Par la suite, de nouvelles fonctions pourront être développées au besoin par ACE Editeur.

Extensions des espaces de nommage :

  • Les fonctions : DECODE, CONCAT, INSTR, SUBSTR, RPAD, LPAD, LOWER et UPPER dont le fonctionnement est relativement similaire à la définition Java ou SQL.
  • La possibilité d'exploiter 2 espaces de nommage supplémentaires : VLB et VLP afin de récupérer des valeurs provenant des espaces de nommage "public" et "business". Dans le cas des paramètres "business", on ne peut prendre en compte à ce jour que le niveau immédiatement supérieur à la vue courante. Exemple : VLB:Codsoc
  • L'espace de nommage MEV permet de récupérer le code société physique (champ CODSOC_PHY) pour un couple entité/segment donné. Par exemple : MEV:PRO ou MEV:TIE.FOU

Note sur l’espace de nommage des PPE

Lorsque qu’aucune valeur de champ n’est demandée pour un PPE donné, le fournisseur de valeur renvoie TRUE ou FALSE. Par exemple, si le PPE TYPFOU est positionné, la syntaxe suivante renverra TRUE :

  • PPE:TYPFOU

La valeur renvoyée est en majuscule, la casse ici aussi est fondamentale.

Extensions

UML : Diagramme de classe

Resolver classes

Introduction

Définitions

Les resolver classes permettent de résoudre les clauses Where définies dans le fichier de configuration. Il en existe plusieurs types à utiliser à bon escient. On distingue principalement :

  • Ceux qui s’appliquent aux BC4J,
  • Ceux qui s’appliquent aux ViewObjects dynamiques,
  • Ceux permettant de réaliser des actions bien spécifiques (ramener l’utilisateur connecté …).

Les resolver sont invoqués dynamique par le socle technique (technicalframework), mais sont implémentés sur la couche métier. Il est donc possible de créer ses propres resolver classes spécifiques en fonction des besoins.

Le but des resolver étant de passer dynamiquement des paramètres aux requêtes, ils n’existent que pour les ViewObject (à fortiori pas pour les APIs).

Résolution de paramètres

Il existe 2 moyens de remplacer une inconnue par un paramètre avec les resolver :

  • En remplaçant littéralement le paramètre,
  • En bindant le paramètre.

Le plus simple est de prendre un exemple avec une requête simple qui attend 2 paramètres obligatoires :

Select Codpro,Nompro,Typpro,Design1 from Pro where codsoc= ? and codpro= ?

Les paramètres (1 type numérique et 1 type caractère) prendront les valeurs suivantes :

  • Codsoc è 1113
  • Codpro è TX106

En utilisant un resolver qui remplace les paramètres littéralement, on obtient la requête suivante :

Select Codpro,Nompro,Typpro,Design1 from Pro where codsoc=1113 and codpro=’TX106’

En utilisant un resolver qui bind les paramètres, la requête reste la même et on va passer les paramètres à Oracle pour qu’il réalise le travail lui-même.

select Codpro,Nompro,Typpro,Design1 from Pro where codsoc= ? and codpro= ?

Bind #1 è 1113

Bind #2 è TX106

Alors pourquoi ne pas utiliser un resolver qui bind les paramètres systématiquement ? Simplement parce qu’on ne peut pas dans ce cas passer un opérateur en paramètre (LIKE, >= …). Par exemple, on ne pourrait pas résoudre les requêtes auxquelles on passe des bornes de dates avec des opérateurs. La requête suivante serait insoluble :

select Codpro,Nompro,Typpro,Design1 from Pro where codsoc= ? and codpro= ‘?’ and Datcre ? ‘ ?’ and Datcre ? ‘ ?’

Attention

Dans ce cas, les paramètres de type “VARCHAR2” doivent être entourés de quotes sinon la requête sera syntaxiquement erronée.

Optimisation et performance

Dans tous les cas, il est préférable d’exploiter les resolver bindant les paramètres, ceci pour 2 raisons :

  • Au niveau de la base de données, une requête bindée est toujours considérée comme identique par Oracle, quels que soient les paramètres qu’on lui passe. Une fois une requête parsée par Oracle, le plan d’exécution reste en SGA ce qui permet l’économie d’un nouveau parsing.
  • Au niveau des pools d’instances sur le serveur d’application, le même principe est appliqué. Pour une requête donnée, on aura toujours une instance et éventuellement plusieurs rowsets si on a appliqué des paramètres différents à la requête è gain en mémoire et gain en CPU puisqu’on instancie moins d’objets

Par contre dans le cadre de recherches multicritères, il est préférables d’utiliser les classes qui remplacent les paramètres littéralement afin d’obliger Oracle à parser la requête et trouver le chemin d’exécution optimum (explain plan).

Il arrive parfois qu’Oracle ne parvienne pas à trouver le meilleur plan d’exécution en particulier lorsque la requête met en jeu des tables partitionnées. Dans ce cas, le moteur de parsing travaille différemment (dans un cas, il dispose des valeurs dans les prédicats, dans l’autre le binding n’est effectué que lors de l’exécution de la requête).

Pour rappel, le cheminement est le suivant lors de l’exécution d’une requête :

Définition des resolvers

Pour les objets métiers

n fr.ACE.technicalframework.application.DefaultWhereClauseResolver

BC4J, pas de paramètres optionnels, pas de quotes entre ? èBIND

n fr.generix.metier.clauseWhere.BusinessWhereClauseResolver

BC4J, paramètres optionnels autorisés, quotes entre ? è LITTERAL

n fr.generix.metier.clauseWhere.BindWhereClauseResolver

BC4J, paramètres optionnels autorisés, pas de quotes entre ? è BIND

Requêtes dynamiques

n fr.ACE.technicalframework.application.DefaultSQLQueryResolver

Dynamique, pas de paramètres optionnels, pas de quotes entre ? è BIND

n fr.generix.metier.clauseWhere.BusinessSQLQueryResolver

Dynamique, paramètres optionnels autorisés, quotes entre ? è LITTERAL

n fr.generix.metier.clauseWhere.BindSQLQueryResolver

Dynamique, paramètres optionnels autorisés, pas de quotes entre ? è BIND

Resolvers étendus

Depuis la version ACE 1.3, deux nouveaux resolvers sont disponibles. Ils autorisent le remplacement littéral de paramètres ainsi que le binding. Deux caractères différents sont utilisés suivant que l’on souhaite remplacer littéralement (@) ou binder ( ?).

Ce sont des resolver métiers, les règles habituelles sont utilisées lors des remplacements littéraux (mettre des quotes si la variable est du type VARCHAR et ne pas en mettre si c’est une expression numérique).

n fr.generix.metier.clauseWhere.BindLitteralSQLQueryResolver

Dynamique, paramètres optionnels autorisés, @ pour le remplacement littéral et ? pour les bind

n fr.generix.metier.clauseWhere.BindLitteralWhereClauseResolver

BC4J, paramètres optionnels autorisés, @ pour le remplacement littéral et ? pour les bind

Ces resolvers sont à privilégier dans le cadre des requêtes avec paramètres optionnels, ceci pour plusieurs raisons :

  • Ils sont plus souples d’utilisation
  • Ils résolvent les requêtes plus rapidement (optimisation au niveau Java)

Clause null

Il existe une clause particulière qui permet de demander au socle de ne pas passer de requête : NullClause

Dans certains cas d’utilisation, on peut vouloir ne passer la requête que si tous les paramètres sont disponibles (cas de certaines recherches par exemple). Il suffit alors de définir une requête sans paramètres optionnels (entourés de crochets) et d’utiliser le ResolverClass suivant :

n fr.generix.metier.clauseWhere.BindLitteralNullClauseResolver

Ce resolver prend en compte les jockers @ et ? suivant que l’on souhaite remplacer littéralement ou binder les paramètres.