lumnik. / scénarios Tous les scénarios · English

Struts 1 sans API: l'export CSV de l'écran, lu tel qu'il sort

Objectif Lire une application Struts 1 qui n'a pour toute sortie que l'export CSV de son écran, et être prévenu d'un retour client qui attend une pièce depuis plus de 30 jours.

Un fabricant de pompes gère ses retours clients dans un intranet Struts 1 écrit en 2007: Tomcat, JSP, DisplayTag. Aucune API; l'écran a un lien d'export CSV, et une tâche planifiée le récupère chaque nuit.

rma-ouverts-2026-11-05.csv
RMA-26-0001,20/08/2026,Agri-Services Dubreuil,Vanne V-40,Surchauffe,Reçu,"89,90",77
RMA-26-0002,21/08/2026,"Léon, Fils & Cie",Surpresseur S-3,Casse au transport,Avoir à émettre,"2 310,00",76
RMA-26-0003,22/08/2026,Établissements Morvan,Pompe P-220,Erreur de référence,Ouvert,"1 234,50",75
RMA-26-0004,27/08/2026,Thermique de l'Ouest,Pompe P-220,Ne démarre pas,En attente pièce,"1 234,50",70
RMA-26-0005,28/08/2026,Agri-Services Dubreuil,Vanne V-40,"Client: \"pièce jamais reçue\", relancé",En expertise,"179,80",69
RMA-26-0006,28/08/2026,Quincaillerie Bérard,Carte électronique CE-12,Ne démarre pas,En attente pièce,"636,00",69
RMA-26-0007,29/08/2026,Côté Jardin Négoce,Carte électronique CE-12,Erreur de référence,En attente pièce,"318,00",68
RMA-26-0008,31/08/2026,Thermique de l'Ouest,Surpresseur S-3,"Bruit anormal, vibrations",En attente pièce,"4 620,00",66
RMA-26-0009,01/09/2026,Plomberie Garnier SARL,Carte électronique CE-12,Erreur de référence,Ouvert,"318,00",65
RMA-26-0010,03/09/2026,Hydro Saône,Carte électronique CE-12,Fuite au joint,En attente pièce,"636,00",63
RMA-26-0011,04/09/2026,"Léon, Fils & Cie",Pompe P-220,"Client: \"pièce jamais reçue\", relancé",Avoir à émettre,"1 234,50",62
RMA-26-0012,08/09/2026,Plomberie Garnier SARL,Carte électronique CE-12,"Client: \"pièce jamais reçue\", relancé",Avoir à émettre,"636,00",58
RMA-26-0013,11/09/2026,Thermique de l'Ouest,Surpresseur S-3,Surchauffe,En attente pièce,"2 310,00",55
RMA-26-0014,13/09/2026,"Léon, Fils & Cie","Moteur M-1,5 kW","Client: \"pièce jamais reçue\", relancé",En expertise,"612,75",53
RMA-26-0015,14/09/2026,Thermique de l'Ouest,Vanne V-40,Ne démarre pas,Ouvert,"89,90",52
RMA-26-0016,16/09/2026,Établissements Morvan,Vanne V-40,Fuite au joint,Reçu,"89,90",50
RMA-26-0017,17/09/2026,Plomberie Garnier SARL,Pressostat PR-6,"Bruit anormal, vibrations",En attente pièce,"46,20",49
RMA-26-0018,19/09/2026,Plomberie Garnier SARL,Pompe P-220,Casse au transport,Ouvert,"1 234,50",47
RMA-26-0019,19/09/2026,Agri-Services Dubreuil,Surpresseur S-3,Erreur de référence,Ouvert,"2 310,00",47
RMA-26-0020,21/09/2026,"Léon, Fils & Cie",Pompe P-220,Surchauffe,En expertise,"1 234,50",45

… 26 lignes de plus

manifests/10-rma-export.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-struts-a  connector_type: csv-file  scopes: [sav-a]spec:  transport:    kind: local    path: /tmp/lumnik-scenario/struts-displaytag-export/a/rma-ouverts.csv   # one file, rewritten every night: the table follows it  parser:    delimiter: ","    encoding: ISO-8859-1           # DisplayTag writes the response's charset: text/csv;charset=ISO-8859-1    has_header: false              # export.csv.include_header=false, DisplayTag's default    columns: [rma_no, opened, customer, item, reason, status, amount, age_days]    escape: "\\"                   # DisplayTag's CsvView escapes a quote with a backslash, never doubles it  after_process: none  mapping:    cell:      - parse-date: { column: opened, formats: ["dd/MM/yyyy"] }      - parse-number: { column: amount, decimal-separator: "," }   # "2 310,00": grouped by a no-break space      - parse-number: { column: age_days, integer: true }
manifests/20-waiting-for-a-part.yaml
apiVersion: apps.lumnik.io/v1kind: Processmetadata:  name: scenario-struts-waiting-aspec:  scope: sav-a  on: { event: data.row.changed, table: connector.t_scenario_struts_a }  when:    - status=En attente pièce    - age_days>30                    # the screen's own Ancienneté (j): the application computes it  emit:    type: decision.waiting-for-a-part-a    message: "{rma_no} ({customer}, {item}): waiting for a part for {age_days} days"    key: rma_no
rma-ouverts-2026-11-06.csv
RMA-26-0001,20/08/2026,Agri-Services Dubreuil,Vanne V-40,Surchauffe,Reçu,"89,90",78
RMA-26-0002,21/08/2026,"Léon, Fils & Cie",Surpresseur S-3,Casse au transport,Avoir à émettre,"2 310,00",77
RMA-26-0003,22/08/2026,Établissements Morvan,Pompe P-220,Erreur de référence,Ouvert,"1 234,50",76
RMA-26-0005,28/08/2026,Agri-Services Dubreuil,Vanne V-40,"Client: \"pièce jamais reçue\", relancé",En expertise,"179,80",70
RMA-26-0006,28/08/2026,Quincaillerie Bérard,Carte électronique CE-12,Ne démarre pas,En attente pièce,"636,00",70
RMA-26-0007,29/08/2026,Côté Jardin Négoce,Carte électronique CE-12,Erreur de référence,En attente pièce,"318,00",69
RMA-26-0008,31/08/2026,Thermique de l'Ouest,Surpresseur S-3,"Bruit anormal, vibrations",En attente pièce,"4 620,00",67
RMA-26-0009,01/09/2026,Plomberie Garnier SARL,Carte électronique CE-12,Erreur de référence,Ouvert,"318,00",66
RMA-26-0010,03/09/2026,Hydro Saône,Carte électronique CE-12,Fuite au joint,En attente pièce,"636,00",64
RMA-26-0011,04/09/2026,"Léon, Fils & Cie",Pompe P-220,"Client: \"pièce jamais reçue\", relancé",Avoir à émettre,"1 234,50",63
RMA-26-0012,08/09/2026,Plomberie Garnier SARL,Carte électronique CE-12,"Client: \"pièce jamais reçue\", relancé",Avoir à émettre,"636,00",59
RMA-26-0013,11/09/2026,Thermique de l'Ouest,Surpresseur S-3,Surchauffe,En attente pièce,"2 310,00",56
RMA-26-0014,13/09/2026,"Léon, Fils & Cie","Moteur M-1,5 kW","Client: \"pièce jamais reçue\", relancé",En expertise,"612,75",54
RMA-26-0015,14/09/2026,Thermique de l'Ouest,Vanne V-40,Ne démarre pas,Ouvert,"89,90",53
RMA-26-0016,16/09/2026,Établissements Morvan,Vanne V-40,Fuite au joint,Reçu,"89,90",51
RMA-26-0017,17/09/2026,Plomberie Garnier SARL,Pressostat PR-6,"Bruit anormal, vibrations",En attente pièce,"46,20",50
RMA-26-0018,19/09/2026,Plomberie Garnier SARL,Pompe P-220,Casse au transport,Ouvert,"1 234,50",48
RMA-26-0020,21/09/2026,"Léon, Fils & Cie",Pompe P-220,Surchauffe,En expertise,"1 234,50",46
RMA-26-0021,23/09/2026,Hydro Saône,Surpresseur S-3,"Bruit anormal, vibrations",Reçu,"2 310,00",44
RMA-26-0022,24/09/2026,Hydro Saône,Pressostat PR-6,Surchauffe,En attente pièce,"46,20",43

… 25 lignes de plus

Limites

  • Le run dit « 1 row(s) removed »: c'est la baisse de la table. Les lignes n'ont pas de clé; trois retours clos et deux ouverts font 1.
  • L'ancienneté change chaque nuit, donc chaque ligne est réécrite: c'est ainsi que la règle, déclarée après la première lecture, voit les sept retours. Ce que devient la décision d'un retour qui attend encore la troisième nuit n'a pas été joué.
  • Le lien d'export est appelé sans session. Une application qui exige une connexion pour son écran demande un cookie de session: non joué ici.
  • La tâche cron est jouée par le script du scénario, pas par un crontab.
  • Retours, clients et montants synthétiques; Struts 1.3.10, DisplayTag 1.2 et Tomcat 9 sont réels.

SAV · Struts 1

Les retours clients vivent dans un intranet de 2007.

Struts 1, DisplayTag, Tomcat. Aucune API, un lien « Export CSV ».

?6578706f7274=1&d-16516-e=1

Le problème

Le hub lisait 5 lignes sur 46.

  • DisplayTag écrit \" dans un guillemet, au lieu de le doubler.
  • Et 2 310,00 est groupé par une espace insécable: le montant était perdu.

Ce qui n'est pas modifié

L'application reste telle quelle.

  • Aucune ligne de Java, aucune JSP touchée.
  • L'export est celui de l'écran, appelé chaque nuit.

Ce qu'il a fallu écrire

escape: "\\"
encoding: ISO-8859-1

Deux lignes dans le connecteur.

  • Le motif garde ses guillemets.
  • Un seul fichier: la table le suit.

Ce qui a été corrigé

parser.escape existe (#1877).

  • parse-number enlève l'espace insécable (#1878).
  • 46 retours lus, 7 décisions le lendemain.

Essayer

Le scénario se rejoue en local.

Chaque étape est publiée avec sa sortie.

Ce scénario tourne sur lumnik Open, gratuit et open source.

Essayer lumnik Open →