Utilisation des données d'un template XML pour un envoi sur un webservice

Bonjour,

J’ai une publication qui me donne un fichier XML (template) dont voici le code:

<employers>
[BEGIN]
	<employer>
	<id_society>[VALUE:EmplFrontBoEmployersNoSociety_ID]</id_society>
	<id_address>[VALUE:EmplFrontBoEmployersNoAddress_ID]</id_address>
	<nom1>[VALUE:EmplFrontBoEmployersName1]</nom1>
	<nom2>[VALUE:EmplFrontBoEmployersName2]</nom2>
	<pa>[VALUE:EmplFrontBoEmployersPa]</pa>	
	<rue>[VALUE:EmplFrontBoEmployersStreet]</rue>
	<norue>[VALUE:EmplFrontBoEmployersNoStreet]</norue>
	<npa>[VALUE:EmplFrontBoEmployersNpa]</npa>
	<ville>[VALUE:EmplFrontBoEmployersCity]</ville>
	<suffixe>[VALUE:EmplFrontBoEmployersSuffixe]</suffixe>		
	</employer>
[END]	
</employers>

J’aimerai envoyer les données sous forme de flux à un webservice, mais je ne sais pas comment les récupérer. J’ai essayé de trouver des infos sur la doc et dans le forum mais il n’y a rien qui éclaire vraiment ma lanterne.

Extrait du code actuel avec invokePrint :

	 //Une fonction pour envoyer le flux XML à WSPRINT
	public  byte[] envoyerBDOC(){
		AppLog.info(getClass(), " la fonction envoi à bdoc a été appelée", null ,  getGrant());
		
		try{
			String xml = (String)this.invokePrint("Pour BDOC (XML)"); // récupération des données pour le flux
			AppLog.info(getClass(), " invoke " + xml, null,   getGrant());
			EmplFrontBDOCHandler handler = new EmplFrontBDOCHandler(getGrant());
			byte[] ret = handler.printWithData2Stream(xml);

			return ret ;
		}catch(Exception e ){
			AppLog.error(getClass(),"Envoi à bdoc" ,"Exception lors génération de fichier xml", e, getGrant());
		}
		return null;

	}

Merci pour toutes les infos et votre aide.

L’appel à invokePrint permet effectivement d’appliquer un template de publication dans le contexte courant de l’objet mais il faut passer le nom du print template en question en argument. Cf. https://docs.simplicite.io/4.0/javadoc/com/simplicite/util/ObjectDB.html#invokePrint(java.lang.String)

A mon avis ce que vous passez à l’ invokePrint n’est pas le nom de votre template de publication…

effectivement, ce n’était pas le nom du template. J’ai corrigé, mais le résultat n’est toujours pas celui que j’espère. La variable xml est nulle

log :

INFO|designer|com.simplicite.objects.EmplFront.EmplFrontBoEmployers| la fonction envoi à bdoc a été appelée|Evénement: [1]
ui-bundle.js:438:297
ECORED0001|system|com.simplicite.util.ObjectDirect|invokePrint|Erreur Error invoking print template null on object EmplFrontBoEmployers
ui-bundle.js:438:241
ERROR|designer|com.simplicite.objects.EmplFront.EmplFrontBoEmployers|Envoi à bdoc|Evénement: Exception lors génération de fichier xml
ui-bundle.js:438:241
code here

Pour tester la création du XML j’ai mis la publication du XML dans le bouton (et ça créé bien un XML)
image

Pour BDOC (XML) :

Error invoking print template null on object EmplFrontBoEmployers

Il y a toujours visiblement un pb dans votre invocation…

Le nom que vous passez ne correspond sans doute pas exactement au nom du template configuré sur l’objet considéré.

en réalité pour une publication XML je n’ai que 2 possibilités :

  1. le nom publication : emplfrontBdocXML fait appel à
  2. le nom template : EmplFrontTpExport_xml

dans mon invocation j’utilise : EmplFrontTpExport_xml

	 //Une fonction pour envoyer le contenu xml à WSPRINT
	public  byte[] envoyerBDOC(){
		AppLog.info(getClass(), " la fonction envoi à bdoc a été appelée", null ,  getGrant());
		
		try{
			AppLog.info(getClass(), " fonction envoi à bdoc juste avant l'invoke", null ,  getGrant());
			String xml = (String)this.invokePrint("EmplFrontTpExport_xml"); // nom du template xml
			//emplfrontBdocXML = nom publication
			// EmplFrontTpExport_xml = nom template
			EmplFrontBDOCHandler handler = new EmplFrontBDOCHandler(getGrant());
			InputStream in = handler.printWithData2Stream(xml);
		  
			return in!=null ?  handler.getBytes(in) : null;
		}catch(Exception e ){
			AppLog.error(getClass(),"Envoi à bdoc" ,"Exception lors de la génération de fichier xml SF_EMPLFRONT", e, getGrant());
		}
		return null;

	}

Quand vous invoquez une publication vous devez passer le nom de la publication.

Il y a des publications qui n’ont pas de template associé mais qui utilisent une méthode ou un fichier modèle et qui peuvent être invoquées de la même manière. Passer le nom du template associé n’a donc pas de sens car comment alors invoquer ces publications sans template associé ?

Merci pour les éclaircissements, je vois mieux comment fonctionne la publication.

J’ai ajouté un appLog.info après l’invokePrint pour voir le contenu de ma variable xml…vide.
J’ai un peu tout essayé et je suis à court d’idée.

Rappel de ma config :
le template xml :

<employers>
[BEGIN]
	<employer>
	<id_society>[VALUE:EmplFrontBoEmployersNoSociety_ID]</id_society>
	<id_address>[VALUE:EmplFrontBoEmployersNoAddress_ID]</id_address>
	<nom1>[VALUE:EmplFrontBoEmployersName1]</nom1>
	<nom2>[VALUE:EmplFrontBoEmployersName2]</nom2>
	<pa>[VALUE:EmplFrontBoEmployersPa]</pa>	
	<rue>[VALUE:EmplFrontBoEmployersStreet]</rue>
	<norue>[VALUE:EmplFrontBoEmployersNoStreet]</norue>
	<npa>[VALUE:EmplFrontBoEmployersNpa]</npa>
	<ville>[VALUE:EmplFrontBoEmployersCity]</ville>
	<suffixe>[VALUE:EmplFrontBoEmployersSuffixe]</suffixe>		
	<daterappel1>[VALUE:EmplFrontBoEmployersRecallDate1]</daterappel1>
	</employer>
[END]	
</employers>

la publication :

la méthode contenant invokePrint:

 //Une fonction pour envoyer le contenu xml à WSPRINT
public  byte[] envoyerBDOC(){
	AppLog.info(getClass(), " la fonction envoi à bdoc a été appelée", null ,  getGrant());
	
	try{
		AppLog.info(getClass(), " fonction envoi à bdoc juste avant l'invoke", null ,  getGrant());
		String xml = (String)this.invokePrint("emplfrontBdocXML"); // nom de la publication
		AppLog.info(getClass(), "step 1 xml : " + xml, null ,  getGrant());
		//emplfrontBdocXML = nom publication
		// EmplFrontTpExport_xml = nom template
		EmplFrontBDOCHandler handler = new EmplFrontBDOCHandler(getGrant());
		AppLog.info(getClass(), "step 2", null ,  getGrant());
		InputStream in = handler.printWithData2Stream(xml);
		AppLog.info(getClass(), "step 3", null ,  getGrant());
	  
	  
		return in!=null ?  handler.getBytes(in) : null;
	}catch(Exception e ){
		AppLog.error(getClass(),"Envoi à bdoc" ,"Exception lors de la génération de fichier xml SF_EMPLFRONT", e, getGrant());
	}
	return null;

}

et les logs obtenus :

je suis preneur de toutes suggestions.

Merci

Dans quel contexte est appelée votre méthode envoyerBDOC ?

la méthode est appelée depuis une action:

image

Ok dans ce contexte voici la manière de remplir ce template de publication:

	public String xmlExport() {
		try {
			String xml = Tool.toString(getPrintTemplate("DemoOrder-XML").fillWithCurrentObject(this));
			AppLog.info(getClass(), "xmlExport", "XML = " + xml, getGrant());
			return Message.formatSimpleInfo("Exported!");
		} catch (Exception e) {
			return Message.formatSimpleError(e.getMessage());
		}
	}

PS: La methode ìnkokePrint ne concerne en effet que les publications de type “méthode”, (elle serait mieux nommée invokePublicationMethod), on va regarder si on peut lever cette limitation/ambiguïté, à minima dans la Javadoc.

Bonjour,

De retour de vacances, je me remets dans le bain…

J’ai corrigé avec la méthode

Tool.toString

et ça marche, j’ai bien un XML, mais il ne contient que le dernier élément d’une liste et pas toute la liste.

Qu’est-ce que je dois encore changer?

Merci.

Fabrice

Une action de globale (de liste) doit se servir de getSelectedIds() pour parcourir la liste des items explicitement sélectionnés et gérer le null comme, au choix, soit comme aucun items sélectionné, soit comme tous les items implicitement sélectionnés.

Ex:

// Build rows from selected IDs or from the current filters
List<String[]> rows = new ArrayList<>();
List<String> ids = getSelectedIds();
if (!Tool.isEmpty(ids)) {
	// Iterate on selected IDs
	for (int k = 0; k < ids.size(); k++)
		if (select(ids.get(k)))
			rows.add(getValues());
} else {
	// Get the full list that matches the current filters
	rows = search(false);
}

// Do something with rows

Dans cet exemple aucun item explicitement sélectionné signifie tous les items implicitement sélectionnés, pour considérer cela comme aucun item sélectionné il suffit de retirer le else

PS: il y a de nombreux exemples de code (y compris un cas comme cela, sur une publication mais c’est le même principe) dans la démo (https://github.com/simplicitesoftware/module-demo) n’hésitez pas à vous en inspirer, c’est fait pour ça.

PS2: cette question a déjà été posée dans le post suivant : Action en liste - traitement multiple, n’hésitez pas non plus à faire des recherches sur le forum

Merci pour les exemples.

la publication prenant automatiquement la liste s’il y en a une, je pensais que la méthode qui faisait appel à cette publication reprenait automatiquement la liste s’il y en avait une.

Je comprends bien le getSelectedIds() pour créer la liste, mais je ne vois pas comment je l’intègre dans mon script.

Si je comprends bien ce que vous voulez faire: vous avez une action globale (de liste) qui invoque une publication de liste ? Dans cette action vous voulez ensuite utiliser le XML produit par cette publication pour appeler un webservice ? C’est bien ça ?

Si ce que je décrit correspond bien à votre cas alors ma réponse précédente n’est pas adaptée à votre cas.

Ici vous devez juste choisir entre fillWithCurrentObject et fillWithCurrentList en fonction de ce que vous voulez populer dans votre publication.

  • fillWithCurrentObject popule le record courant
  • fillWithCurrentList popule avec la liste courante de records

Oubliez ma réponse précédente avec le getSelectIds qui ne sert à rien ici mais qui aurait été pertinente si vous aviez écrit la génération du XML directement dans votre action (je veux dire sans utiliser une publication qui est une approche un peu “luxeuse” sauf si la publication sert par ailleurs), genre:

StringBuilder x = new StringBuilder();
x.append("<employers>");
for (String[] row : rows) {
	setValues(row, false);
	x.append("<employer>");
	x.append("<id_society>" + Tool.toXML(getFieldValue("EmplFrontBoEmployersNoSociety_ID")) + "</id_society>");
	(...)
	x.append("</employer>");
}
x.append("</employers>")
String xml = x.toString();

C’est parfait maintenant avec le fillWithCurrentList

Effectivement, le but de la publication est, pour moi, d’éviter de construire un XML par script.

Merci beaucoup pour votre temps et vos explications. J’apprécie toujours.