28 septembre 2022

Reinitialiser les mots de passe de eDSN en mode commande

L'utilisateur de eDSN peut modifier son mot de passe via l'interface ... s'il a réussi à se connecter !

S'il faut le réinitialiser, l'usage est de se connecter au serveur et de mettre à jour le fichier XML de configuration des comptes.

.../conf/ grep Digix users.xml

    <user id="Digix" firstName="Di" lastName="Gix" password="dummy">


Une commande a été mise à disposition depuis eDSN 8 pour le modifier depuis la console SSH. Comme pour l'IHM, il est nécessaire de connaitre l'ancien :

edsn>usermanager:change-password Digix

Ancien mot de passe :****

Nouveau mot de passe :*****

Confirmation du nouveau mot de passe :*****

Le mot de passe a été changé

edsn>

Le fichier a été mis à jour et le mot de passe est chiffré :

    <user id="Digix" firstName="Di" lastName="Gix" password="{CRYPT}PCNY5VyVhXY+FnUph1L7nGQ/Wc1pmofjFe4MCROoMS+BoTshxymSX9TkTXOc3ewH{CRYPT}">


NB : Si un addon d'authentification spécifique a été mis en place, la commande appellera la méthode de changement de mot de passe - pour peut qu'elle ait été développée ...

27 septembre 2022

Requêtes SQL sur les processus de workflow ACTIVITI de eDSN

eDSN fonctionne avec des processus de workflow. Ces derniers sont gérés par l'open source ACTIVITI.
Pour lister les processus en cours, il est donc possible de le faire par SQL dans les tables ACT_*

Quelques éléments donnés par la doc ACTIVITI :

The database names of Activiti all start with ACT_. The second part is a two-character identification of the use case of the table. This use case will also roughly match the service API.

  • ACT_RE_*: RE stands for repository. Tables with this prefix contain static information such as process definitions and process resources (images, rules, etc.). 
  • ACT_RU_*: RU stands for runtime. These are the runtime tables that contain the runtime data of process instances, user tasks, variables, jobs, etc. Activiti only stores the runtime data during process instance execution, and removes the records when a process instance ends. This keeps the runtime tables small and fast. 
  • ACT_ID_*: ID stands for identity. These tables contain identity information, such as users, groups, etc. (absentes sur eDSN) 
  • ACT_HI_*: HI stands for history. These are the tables that contain historic data, such as past process instances, variables, tasks, etc. (absentes sur eDSN) 
  • ACT_GE_*: general data, which is used in various use cases.

Par exemple, pour comptabiliser les processus et tâches en cours :

set markup csv on quote off
select regexp_substr(PROC_DEF_ID_,'^[^:]+:'),TASK_DEF_KEY_,count(*) from act_ru_task group by regexp_substr(PROC_DEF_ID_,'^[^:]+:'), TASK_DEF_KEY_ order by 1,2;
controlReport:,consultControlReport,47
flowFile:,consultFlowFile,4
manageSignalementEnvoi:,downloadSignalementEnvoi,9
monthlyDeclaration:,manageDeclarationCancel,1
monthlyDeclaration:,manageDeclarationError,2
monthlyDeclaration:,validateDeclaration,1477
signalementDeclaration:,manageSignalement,10
signalementDeclaration:,manageSignalementError,96
synchronizeSignalement:,consultSynchronizeSignalement,63
temporaryDeclaration2:,consultErroneousTemporaryDeclaration,22
temporaryDeclaration2:,consultTemporaryDeclaration,10378
uncertifiedCancelAndReplaceDeclaration:,manageUncertifiedCancelAndReplaceDeclarationError,2
uncertifiedDeclaration:,manageUncertifiedDeclarationError,3
uncertifiedSignalementDeclaration:,manageUncertifiedSignalementError,63
uncertifiedSignalementDeclaration:,validateUncertifiedSignalement,2

Noter qu'un nombre important de processus en cours va impacter négativement les performances batch et transactionnelles de eDSN. Pour purger les processus orphelins (faisant référence à une déclaration qui n'existe plus), l'application fournit une commande qu'il est intéressant d'automatiser :

admin:purge-orphans [-p SSAAMM]

Pour visualiser les messages d'erreur des processus :

select substr(J.PROCESS_INSTANCE_ID_,1,10) , regexp_substr(J.PROC_DEF_ID_,'^[^:]+:'), '-' , substr(J.EXCEPTION_MSG_,1,200)||'...'  from ACT_RU_JOB J where J.EXCEPTION_MSG_ is not NULL;
135011326  signalementDeclaration:                                          - Unknown property used in expression: ${setSignalementToBeSentStatusDelegate}...
136827668  controlReport:                                                   - Unknown property used in expression: ${deleteControlReportDelegate}...

 

Afficher en ligne toutes les propriétés (text_) du processus d'un workflow (ici 138338880) :

select proc_inst_id_, listagg(name_||'='||text_,' ') within group (order by name_) from act_ru_variable
 where proc_inst_id_ =
138338880 group by proc_inst_id_;

138338880
adminContentPath=synchronizeSignalementReports/admin/ARRET_TRAVAIL/138338880.csv beginDateRefresh= consideredEventCount=1355 done= format=csv generationDate= groups=nogroup koEventCount=17 lastInvolvedUser=admin maxDate=2022-10-24T03:03:09Z month=9 okEventCount=18 periodeDsn= processCreationDate=2022-09-24-05:02:19 processCreator=admin requestDate= signalementType=ARRET_TRAVAIL totalEventCount=1390 userContentPath=synchronizeSignalementReports/admin/ARRET_TRAVAIL/138338880.csv userId=admin year=2022

Ainsi, pour repérer un processus orphelin :

select proc_inst_id_ from act_ru_variable where name_ = 'declarationTechnicalId' and text_ not in (select id from dsndeclaration);

Ou avec ses propriétés :
select v.proc_inst_id_, listagg(v.name_||'='||v.text_,' ') within group (order by v.name_) from edsn.act_ru_variable v
join edsn.act_ru_variable w on v.proc_inst_id_ = w.proc_inst_id_ and w.name_ = 'declarationTechnicalId'
where w.text_ not in (select id from dsndeclaration) group by v.proc_inst_id_;

(pour les processus d'envoi, la liste des Id est stockée en hexadecimal dans une table ACT_GE_BYTEARRAY ... pas très lisible !)

Pour repérer les actions automatiques (réglées sur un timer ACTIVITI) et leur échéance :

select J.DUEDATE_ echeance, J.PROCESS_INSTANCE_ID_ pid, REGEXP_SUBSTR(J.PROC_DEF_ID_,'^[^:]+:') process_type, V.NAME_, V.TEXT_
from ACT_RU_JOB J
left outer join ACT_RU_VARIABLE V
on J.PROCESS_INSTANCE_ID_ = V.PROC_INST_ID_ and V.NAME_ in ('declarationTechnicalId','fluxId','contentPath','userContentPath')
where J.TYPE_='timer' and TEXT_ is not null
order by 1,3

ECHEANCE,PID,PROCESS_TYPE,NAME_,TEXT_
2027-09-26-00.00.00,61537997,signalementDeclaration:,declarationTechnicalId,de5e85b8-7b10-40cf-8316-a1f82d1f7651
2022-09-27-15.40.22,62638457,controlReport:,contentPath,controlReports/202209/john.doe@acme.com/messages-62638457.csv
2022-09-28-17.51.33,62593312,flowFile:,contentPath,flows/202208/flux_62593312_42206902100034-NET-1.dsn
2022-10-23-03.51.27,62640501,monthlyDeclaration:,declarationTechnicalId,05744771-8d5f-46bb-8f89-871418b8b794

8 juillet 2022

eDSN - Fermer l'accès à interface Web

eDSN permet de réserver l'interface à une liste d'utilisateurs privilégiés.
Pour cela passez par edsn-admin, onglet "Utilisateurs" et alimentez la liste blanche.

La liste est gérable aussi par fichier de configuration :

com.soprahr.edsn.admin.cfg

usersWhiteList = admin


Si ce mode de fonctionnement ne suffit pas, vous pouvez aussi fermer les webapps en mode commande (ceci vaut aussi pour evMedia. Attention, cette fois le navigateur de l'utilisateur affichera une erreur d'accès) :

evmedia>web:list
ID | State       | Web-State   | Level | Web-ContextPath | Name
---+-------------+-------------+-------+-----------------+-------------------------------------
47 | Active      | Deployed    | 80    | /evm-admin      | com.soprahr.evm.admin.webapp (3.1.0)
69 | Active      | Deployed    | 80    | /evm-ij         | com.soprahr.evm.sat.webapp (3.1.0) 

evmedia>web:stop 47
evmedia>web:list
ID | State       | Web-State   | Level | Web-ContextPath | Name
---+-------------+-------------+-------+-----------------+-------------------------------------
47 | Active      | Undeployed  | 80    | /evm-admin      | com.soprahr.evm.admin.webapp (3.1.0)
69 | Active      | Deployed    | 80    | /evm-ij         | com.soprahr.evm.sat.webapp (3.1.0)
evmedia>web:start 47





4 juillet 2022

HRaSpace - Téléchargement des états construits - Proposer un "Enregistrer sous ..."

J’ai discuté avec Lionel d'un problème que j'avais rencontré chez un client : lors du téléchargement de fichiers ZIPs que nous archivions via un script spécifique, pour que HRaSpace propose un "Enregistrer sous", il avait fallu suffixer le zip en « .csv » ...

Cela a été reproduit, compris et solutionné. Explication :

Dans l'écran AA P83Q01, Script onClick on trouve la Fonction hrDownloadResultQuery

  

Extrait du script :

var site = hrGetValue( _O("RU","ZO3QIDDIAG","1"), hrEvent.occRank);

if (hrTrimLeftRight(site)=="") site = hrGetValue( _O("RU","ZO00IDDIAG","1"), hrEvent.occRank);

hrDownloadResultQuery( site, hrGetValue(_O("RU","ZO3QURLSTO","1"),hrEvent.occRank) );


Syntaxe :

hrDownloadResultQuery(siteCode, filePath, forceAttachmentOpt)

 Cette fonction possède une option forceAttachmentOpt 

 

Pour utiliser un téléchargement il faut passer l’option à « true » :

hrDownloadResultQuery(site, hrGetValue(_0("RU","ZO3QURLSTO","1"),hrEvent.occRank), true) ;


A tester sur une copie de l'écran standard.

Objet "ressource Web" - Répertoire webapps/hr-rich-client/rich-client-plugins

Un objet de type "ressource Web" est livré avec le kit ATIJ

Lors de la publication un fichier jar est alors déposé dans webapps/hr-rich-client
Et un répertoire créé dans webapps/hr-rich-client/rich-client-plugins

Lors de la livraison de l’arbre en Production, pensez à récupérer ce fichier et le contenu de ce sous répertoire.

 

En cas d'absence, l'affichage des pages ATIJ provoque une erreur générique : "undefined : named item not found"

Si je regarde un autre projet j’y vois en base :

select TYOBJE,CDOBJE,trim(NMLONG) from go10 where tyobje='E3';

...
E3,JSGRAPH ,hr-graph-rcplugin-1.1.7.jar
E3,JSPLANN ,hr-planning-rcplugin-1.3.10.jar
E3,PAYANALY,hr-payroll-analyzer-plugins-1.0.2.jar
E3,DIGIFILE,hr-digital-files-plugins-1.0.3.jar
E3,ATSCRIPT,hr-arret-travail-plugin-2.0.3.jar

Des fichiers :

webapps/hr-rich-client/hr-arret-travail-plugin-2.0.1.jar
webapps/hr-rich-client/hr-arret-travail-plugin-2.0.3.jar
webapps/hr-rich-client/hr-digital-files-plugins-1.0.3.jar
webapps/hr-rich-client/hr-graph-rcplugin-1.1.7.jar
webapps/hr-rich-client/hr-payroll-analyzer-plugins-1.0.2.jar
webapps/hr-rich-client/hr-planning-rcplugin-1.3.10.jar

Et des sous répertoires hr-rich-client/rich-client-plugins :

hr-arret-travail-plugin-2.0.1
hr-arret-travail-plugin-2.0.3
hr-digital-files-plugins-1.0.3
hr-graph-rcplugin-1.1.7
hr-payroll-analyzer-plugins-1.0.2
hr-planning-rcplugin-1.3.10

On note la présence de deux versions de hr-arret-travail-plugin … Cela signifie que la publication d’une nouvelle version du ".jar" ne purge pas l’ancienne.

Je n’ai pas de bons souvenirs de telles cohabitations … Toutefois dans les pages publiées les références pointent explicitement vers la dernière version :

grep 'hr-arret-travail-plugin' ./F/FRP/TA0FR0E1/body_auw1000f.html

<link xmlns="" rel="stylesheet" href="../rich-client-plugins/hr-arret-travail-plugin-2.0.3/main.8ba9a9413a4a80e27793.css?1cccf13b81963383f7ca"/>

<script xmlns="" SRC="../rich-client-plugins/hr-arret-travail-plugin-2.0.3/main.ea9103a421a010c5f1ff.js?1cccf13b81963383f7ca"></script>

... <DIV xmlns="urn:schemas-microsoft-com:xml-data" Name="salairesReferenceComponent" CODEBASE="../hr-arret-travail-plugin-2.0.3.jar" ID="salairesReferenceComponent" STYLE="width:972px;height:54px;"></DIV>

22 juin 2022

Programmes Visual Cobol persistant en mémoire

A compter d'une "certaine version" de MicroFocus Cobol, la libération des processus chargés par les BHR ne se fait plus par défaut. Les processus peuvent alors devenir très consommateurs de mémoire.

Pour obtenir une libération mémoire effective lors du déchargement des processus
Créer un fichier de configuration, par exemple $SIGACS/adm/cfg/visualCobol.cfg contenant la ligne :

set default_cancel_mode=0

Positionnez la variable COBCONFIG dans le .profile :

COBCONFIG=$SIGACS/adm/cfg/visualCobol.cfg 

export COBCONFIG

26 avril 2022

Modèle d'entête de script sous Linux avec Vim

Voici un moyen simple de proposer un en-tête personnalisé pour les scripts shell nouvellement créés dans l'éditeur Vi (Vim sous Linux). 

1) Rédiger le modèle, le déposer dans le $HOME : par exemple

vi $HOME/.vim/sh_header.temp
#!/usr/bin/env ksh
#-------------------------------------------------------------------------------
#@(#) Write a title for this script shell here
#-------------------------------------------------------------------------------
#@(#) Syntax  :  ... {SIMUL*|EXEC} PARAM2 [PARAM3]
#@(#) {A*|B} choice, * defaut, X mandatory, [Y] optional
#@(#)    - PARAM1       : Execution mode (SIMUL defaut)
#@(#)    - PARAM2       : Parametre 2 (mandatory)
#@(#) - PARAM3 : Parametre 3 (optional)
#@(#) #@(#) Example : ksh ... #------------------------------------------------------------------------------- # Updates : # Date Author Feature details, issue fixed # 01/01/20.. John DOE Initialization #------------------------------------------------------------------------------- # Trace mode : export Trace=${Trace:-false} # export "Trace=true" to activate Unix traces # -------------------- CONSTANTS --------------------
#  --------------------       FUNCTIONS        --------------------

function check_parameters {
   ${Trace:-false} && set -x

   echo "<I> Checking parameters"

   case "${PARAM1}" in
   (SIMUL)  : ;;
   (EXEC)   : ;;
   (*)      echo "<W> Parameter 1 invalid (SIMUL, EXEC)"; return 1 ;;
   esac

   # ...

   return 0
}

function just_do_it {
   ${Trace:-false} && set -x

   echo "<I> just do it"

   # ...

   return 0
}

#  --------------------          MAIN          --------------------

function main {
   ${Trace:-false} && set -x
   echo "<I> PARAM1=${PARAM1}"
   echo "<I> PARAM2=${PARAM2}"
echo "<I> PARAM3=${PARAM3}"
check_parameters || return 1 just_do_it || return 1 return 0 } # -------------------- PARAMETRES -------------------- PARAM1=${1:-SIMUL} PARAM2=${2:?Parameter 2 not set !} PARAM3=${3:-DEFAULT} # -------------------- EXECUTION -------------------- LOGFILE="${LOG}/$(basename $0 .sh).$(date +'%Y-%m-%d-%H.%M.%S').log" echo "<I> Logfile is : ${LOGFILE}" RETFILE=${TMP}/returnCode.$$ { rm -f "${RETFILE}"; main; echo $? > "${RETFILE}"; } | tee "${LOGFILE}" RETCODE=$(cat "${RETFILE}") echo "<I> Return code : ${RETCODE:-255}" rm -f ${TMP}/*.$$ ${TMP}/$$.* ${TMP}/*.$$.* exit ${RETCODE:-255}

2) Ajouter dans le fichier de configuration de Vim une ligne pour votre "autocommande" :

vi $HOME/.vimrc
autocmd bufnewfile *.sh,*.ksh 0r $HOME/.vim/sh_header.temp

C'est à dire :

  • En cas de nouveau fichier
  • Dont le nom est *.sh ou *.ksh
  • Lire et ajouter en ligne 0 le contenu de sh_header.temp

3) L'opération est à répéter sur chacun des environnements de développement


Dès lors, si vous ouvrez sous Linux avec Vi / Vim un nouveau fichier suffixé par ".sh" ou ".ksh" ce fichier sera initialisé avec votre l'entête.


Merci à www.tecmint.com

Plus d'informations sur vimdoc.sourceforge.net

25 avril 2022

Conditionner les ordres DDL Oracle créés par la RBF

Dans HR Access la chaine batch RBF produit des ordres DDL de création / mise à jour des tables du SGBD (fichier PSBBGJ00 PSBBGJ01 PSBBGJ02). Ceux-ci procèdent souvent d'un DROP suivi d'un CREATE.

Dans le cas ou l'objet n'existe pas encore, l'ordre de DROP va provoquer un erreur. Si on retire le DROP mais que l'objet existe, c'est le CREATE qui sera a l'origine d'une erreur. Quand on souhaite contrôler le bon déroulement des livraisons cela peut être gênant.

Oracle ne fournit pas de syntaxe spécifique, mais il est possible de coder en PL/SQL un conditionnement de l'ordre ou d'inhiber l'erreur. Un autre intérêt est de pouvoir relancer le script autant de fois que nécessaire quand on a rencontré un incident sur un des objets.

17 janvier 2022

Produire une sortie CSV avec SQLPlus Oracle

Ci dessous une opération très simple pour obtenir une sortie SQL de type CSV ... Il suffit de demander à Oracle de le faire pour vous :

set head on
set echo off
set markup csv on delimiter , quote on
select NORME1,NORME2,DATDSN,DATGIP from ZDFS join ZD00 on ZDFS.NUDOSS=ZD00.NUDOSS where CDSTCO='U3N' and CDCODE='000'

"NORME1","NORME2","DATDSN","DATGIP"
"DP21V01 ","DP22V01 ","2022-01-01-00.00.00","2022-01-25-00.00.00"

A noter : 

  • SET MARKUP CSV est disponible a compter de Oracle 12
  • Pour les champs de type CHAR les espaces de fin restent significatifs (par exemple en fin de "DP21V01 "). Pour ne pas les récupérer dans votre extraction, utilisez la fonction rtrim.

plus d'informations avec :
https://docs.oracle.com/.../generating-reports

et
https://docs.oracle.com/.../SET-system-variable

 

24 novembre 2021

eDSN, evMedia - "Bad history file syntax!" ou "MalformedInputException: Input length = 1"

Un upgrade eDSN ou evMedia peut entrainer une mise à jour de la version du Karaf embarqué. A cette occasion le fichier contenant l'historique des commandes peut avoir changé de format et l'ancien fichier être considéré comme illisible. Dans le pire des cas cela provoque un blocage de l'accès aux sessions SSH ...


En cas de présence de ce message le edsn.log, la console SSH est accessible

2021-11-24T09:56:28,514 | INFO  | 4)-nio2-thread-1 | ServerSessionImpl                | Session edsn@/127.0.0.1:46726 authenticated
2021-11-24T09:56:28,750 | WARN  | onsole user edsn | jline                            | Failed to load history
java.lang.IllegalArgumentException: Bad history file syntax! The history file `/home/adm/hr9re1/.karaf/karaf.history` may be an older history: please remove it or use a different history file.
        at org.jline.reader.impl.history.DefaultHistory.addHistoryLine(DefaultHistory.java:185) ~[!/:?]
        at org.jline.reader.impl.history.DefaultHistory.addHistoryLine(DefaultHistory.java:169) ~[!/:?]
        at org.jline.reader.impl.history.DefaultHistory.lambda$load$0(DefaultHistory.java:86) ~[!/:?]


Il suffit de se connecter à la console et de réinitialiser l'historique par la commande ssh suivante :

edsn> shell:history --clear


Le cas d'erreur suivant est plus gênant puisque le client SSH est alors inaccessible :

Au lancement du client eDSN par exemple :

edsn>

Error executing command: java.nio.charset.MalformedInputException: Input length = 1

 

Dans edsn.log

2021-11-15T11:21:26,946 | ERROR | onsole user edsn | ShellUtil                        | Exception caught while executing command

java.io.UncheckedIOException: java.nio.charset.MalformedInputException: Input length = 1

        at java.io.BufferedReader$1.hasNext(BufferedReader.java:577) ~[?:?]

        at java.util.Iterator.forEachRemaining(Iterator.java:132) ~[?:?]

La solution est alors de réinitialiser l'historique des commandes Karaf en détruisant le fichier. 

Dans notre cas : 

rm -f ~/.karaf/karaf.history

25 août 2021

Oracle - date de dernière mise à jour des données d'une table

Pour connaître la date de dernière mise à jour des données d'une table (insert ,delete etc ) il est possible de se baser sur la pseudo-colonne ora_rowscn (system change number niveau ligne) :


SQL> SELECT SCN_TO_TIMESTAMP(MAX(ora_rowscn)) as TIMAJ from ZYTD12 ;

TIMAJ
---------------------------
25/08/21 09:42:45,000000000

7 juin 2021

Design Center : profil de catalogage

 Design Center met à disposition un objet "Paramètre" de type "Profil de catalogage"

 

Dans cet exemple un profil "CATAALLO" est créé pour cataloguer systématiquement les objets 

 

Le profil utilisé par l'environnement est à préciser dans l'onglet "Paramètres" de l'objet "Plateforme Physique" :


Dès lors, toute édition d'un objet provoque son catalogage (exécution par Design Center via le programme BTS de la chaîne NRG) :

30 avril 2021

Exemple d'ordre SQL MERGE permettant de gérer soit un INSERT soit un UPDATE

Dans l'exemple suivant on a inséré une occurrence dans ZD05 d'un code de DRE. On corrige ensuite la ZDTD12 par un MERGE pour que l'occurrence soit créée (si nouvelle) ou modifiée (si existante).

Il s'agit d'une syntaxe SQL ou l'on va :

  • Présenter la table ciblée (MERGE INTO ... A)
  • Produire un SELECT indiquant les valeurs par défaut (USING ... B)
  • Indiquer le critère de mise en correspondance des listes A et B (ON A...=B...)
  • Indiquer quoi faire en cas de correspondance (WHEN MATCHED THEN UPDATE ...) 
  • Ou en cas de non correspondance (WHEN NOT MATCHED THEN INSERT...)


MERGE INTO ZDTD12 A
USING (SELECT NUDOSS, .... AS PGPDOS,'05' AS CDINFO,'0' AS TEVERO,1 AS NOMBRE,0 AS NULMAX,0 AS NUCMAX,
       '        ' AS TECPRT,SYSDATE AS TIMJIF FROM ZD00 WHERE CDSTCO = 'DRE') B
ON (A.NUDOSS=B.NUDOSS AND A.CDINFO=B.CDINFO)
WHEN MATCHED THEN UPDATE SET A.NOMBRE=B.NOMBRE, A.NULMAX=B.NULMAX
WHEN NOT MATCHED THEN INSERT (NUDOSS, PGPDOS, CDINFO, NOMBRE, TEVERO, NULMAX, NUCMAX, TECPRT, TIMJIF)
       VALUES (B.NUDOSS, B.PGPDOS, B.CDINFO, B.NOMBRE, B.TEVERO, B.NULMAX, B.NUCMAX, B.TECPRT, B.TIMJIF);
COMMIT;