Stockage d'un fichier sur une GED externe

Bonjour,

Un objet métier possède un attribut fichier.
Ce fichier ne doit pas être stocké sur la base de simplicité mais sur une GED, la seule chose qui doit être stocké c’est l’ID fourni par la GED (caché à l’utilisateur final)
Il existe un web service pour s’interfacer avec la GED permettant de téléverser un document et de le télécharger.
Le formulaire (création/update) de l’objet métier doit permettre de téléverser un nouveau fichier ou télécharger un existant de la même manière qu’un fichier stockée par Simplicité.
Pouvez-vous me conseiller sur l’implémentation de cette fonctionnalité ?

Merci d’avance

Quelques idées :

  • Il faut stocker ce qui identifie votre document dans un champ en lecture ou caché.

  • Créer un champ File ou URL en lecture seule et calculé pour ouvrir le document : créer un param système qui donne l’URL générale d’accès + calcul pour substituer l’ID du doc dans cette URL (postSearch ou dans l’expression du champ calculé si la syntaxe est simple).

  • Si ce n’est pas un URL mais un appel API complexe (client java, avec credentials, certificat…) il faudra plutôt créer une action “Ouvrir doc” qui appelle une méthode back qui fera l’appel complexe pour récupérer le document et le servir au front.

  • Pour l’upload : il faut nécessairement créer un champ de type Document “mydocUpload” et lors du preSave, appeler votre GED avec le DocumentDB reçu, et si ok valoriser l’ID caché, et remettre le champ “mydocUpload” à vide pour ne pas stocker le doc en base locale.

J’ai une autre contrainte technique c’est que le web service n’est pas accessible en direct (depuis le navigateur client), il n’est accessible que par le serveur simplicité donc la 2ème solution n’est pas possible.
Il me reste la troisième solution, créer une action avec une méthode Back, mais je suis perdue car je ne sais pas quel type d’objet doit retourner cette méthode pour permettre le téléchargement du fichier. J’ai essayé plusieurs choses rien ne fonctionne.

J’ai trouvé une autre solution en passant par une publication pour le téléchargement d’undocument.
Je ne sais pas si c’est un détournement de la fonctionnalité de publication.
Dans ce cadre-là, j’aurai besoin de personnaliser l’icône associée à la publication ainsi que rendre son affichage conditionnelle par rapport à la présence ou non d’un id, je n’arrive pas trouver cette possibilité via le paramétrage, pouvez-vous m’aider ?

Suite à notre discussion:

  1. Affichage conditionnel d’une publication = hooks isPrintTemplateEnable (cf. https://docs.simplicite.io/4.0/javadoc/com/simplicite/util/ObjectDB.html#isPrintTemplateEnable(java.lang.String[],java.lang.String))

  2. Ajouter un bouton custom sur un input:

(function() {
	Simplicite.UI.hooks.MyObject = function(o, cbk) {
		try {
			if (o.isMainInstance()) {
				o.locals.ui.form.onload = function(ctn, obj) {
					$ui.getUIField(ctn, obj, "myField").ui.input.closest(".input-group")
						.append($('<span class="input-group-addon" data-action="AFakeActionName"/>').append($ui.view.icon("fas/upload"))
						.click(function() {
						// Do something on click...
					}));
				};
			}
		} catch(e) {
			app.error("Error in Simplicite.UI.hooks.MyObject: "+e.message);
		} finally {
			cbk && cbk();
		}
	};
})();

J’ai un comportement inattendu depuis que j’ai surchargé la méthode isPrintTemplateEnable
Les boutons sont bien affichés conditionnellement mais par contre quand je clique dessus j’ai l’erreur suivante

ERROR : No grant for print template NamDocAdminPubli for object NamDocAdministrative

(j’ai fait les tests en mettant grantable à YES ou NO)
Si la méthode isPrintTemplateEnable n’est pas surchargée, la publication se fait correctement sans erreur
J’ai suivi strictement l’exemple dans le module démo et qui fonctionne correctement sur mon environnement, je ne sais pas ce qui cloche.
Simplicité version4.0 patch level P24Built on2020-09-14 14:52 (revision 68a40be6819d7cb5c77b1618230f1eac2745021c)

La trace complète dans les logs

2020-09-16 12:59:09,178 ERROR [com.simplicite.webapp.ObjectPrint] SIMPLICITE|http://ip-172-22-19-177.eu-west-3.compute.internal:8080||ERROR|system|com.simplicite.webapp.ObjectPrint|print||Evénement: [1]
    com.simplicite.util.exceptions.GrantException: No grant for print template NamDocAdminPubli for object NamDocAdministrative
     at com.simplicite.webapp.ObjectPrint.getTemplates(ObjectPrint.java:157)
     at com.simplicite.webapp.ObjectPrint.printone(ObjectPrint.java:334)
     at com.simplicite.webapp.ObjectPrint.print(ObjectPrint.java:305)
     at com.simplicite.webapp.servlets.ui.BusinessObjectServlet.service(BusinessObjectServlet.java:506)
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
     at com.simplicite.webapp.filters.AuthMethodFilter.doFilter(AuthMethodFilter.java:137)
     at com.simplicite.webapp.filters.AbstractFilter.doFilter(AbstractFilter.java:37)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
     at com.simplicite.webapp.filters.RewriteFilter.doFilter(RewriteFilter.java:77)
     at com.simplicite.webapp.filters.AbstractFilter.doFilter(AbstractFilter.java:37)
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:188)
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
     at com.simplicite.tomcat.valves.APISessionValve.invoke(APISessionValve.java:191)
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
     at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
     at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
     at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
     at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
     at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
     at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
     at java.base/java.lang.Thread.run(Thread.java:832)

Quel est votre code dans le isTemplateEnable ?

// row[3] contient la valeur de l'attribut conditionnant l'afficahge
return (row!=null) && !Tool.isEmpty(row[3]) && super.isPrintTemplateEnable(row, printTemplate);

Pouvez vous mettre les balises markdown typeés autour de vos blocs de code copier/coller plus plus de lisibilité ? Merci

Ensuite votre code ne va pas car:

  1. il ne faut JAMAIS mettre un index en dur mais toujours écrire row[getFieldIndex("myField")] en effet, l’index d’un attribut dépend de la définition courante de l’objet (qui peut être différente d’un user à l’autre et/ou qui peut être dynamiquement modifiée, etc.).

  2. Quand row est null c’est qu’on est sur un formulaire (quand il est non nul c’est qu’on est sur un item de liste), il faut alors regarder le valeurs dans le record courant getField("myField") / getFieldValue("myField") etc., cf. l’exemple de la démo:

@Override
	public boolean isPrintTemplateEnable(String[] row, String ptName) {
		if ("DemoOrder-PDF".equals(ptName)) {
			String s = row!=null ? row[getStatusIndex()] : getStatus();
			return "V".equals(s) || "D".equals(s);
		}
		return super.isPrintTemplateEnable(row, ptName);
	}

NB : Le getStatus() est un shorthand pour getFieldValue("myStatusField")

D’accord merci beaucoup, je ne connaissais pas la méthode getFieldIndex et le comportement différent sur une liste.

Je précise que row peut aussi être nul quand on parle d’une publication globale (“de liste”) mais vous n’êtes pas dans ce cas là.

Cette logique est commune à tous les hooks isSomethingEnable qui prennent un argument row.

PS: votre code doit aussi tenir compte du fait que vous pouvez avoir d’autres publications sur votre objet donc l’exemple de la démo (qui teste explicitement le nom de la publication) est le bon pattern:

if ("MyPublicationName".equals(ptName)) {
   return <condition for this publication>;
 } //else
 return super.isPrintTemplateEnable(row, ptName);

Oui j’ai ajouté cela, merci beaucoup pour vos conseils