Errore “element IDOC has no non-whitespace child elements”

Scenario

Qualcosa-IDoc

Contesto

In un mapping già configurato in repository e directory, si cambia la cardinalità del messaggio da 1:1 a 1:n.

Effetto

L’esecuzione del messaggio fallisce nel channel monitor con l’errore

Adding control record to payload failed due to IDoc structure of incoming message is not correct – element IDOC has no non-whitespace child elements

Soluzione

Oltre a cambiare la cardinalità del message mapping e nell’operation mapping occorre reimportare l’operation mapping nella Interface Determination dello scenario.


Gestione contatori multi documento

Dato un payload in ingresso riferito a più documenti occorre creare altrettanti documenti in output ciascuno dei quali deve avvalersi di uno o più numeratori, per le posizioni o altro, ed il/i numeratore/i deve resettarsi ad ogni nuovo documento.

UDF

In Attributes and Methods definire la variabile globale

 int po_item = 0;
 
 public String clearCounters(String dummy, Container container) throws StreamTransformationException{ 
	po_item = 0;
	pckg_no = 0;
	return "";
 }
 
 public String incrPOItem(String dummy, Container container) throws StreamTransformationException{ 
	 po_item += 10;
	 return new Integer(po_item).toString();
 } 
 
 public String incrPckgNo(String dummy, Container container) throws StreamTransformationException{ 
	 pckg_no += 1;
	 return new Integer(pckg_no).toString();
 }

Mapping

Reset dei contatori all’origine del nuovo documento

Incremento del contatore

Qualora l’output dell’udf debba essere utilizzato in più calcoli ma con il medesimo valore, occorre salvarlo in una variabile ed utilizzarlo nel modo seguente:

Incrementare un’unica volta il contatore

Utilizzare il contatore nei calcoli


Determinare Receiver tramite mapping

Determinare la Receiver Determination via mapping e referenziarlo tramite la Receiver Determination con il Type of Receiver Determination:  Extended

In ESR

Sender: arbitrario

Receiver: importare Receivers

Mapping

Qualora si debba determinare dinamicamente il Party, implementare l’opportuna logica (arbitraria) su questo nodo

Valorizzare se è valorizzato Party

Valorizzare se è valorizzato Party

Per determinare dinamicamente il service implementare  l’opportuna logica (arbitraria) su questo nodo

getSystemName()  ritorna il contenuto della variabile d’ambiente SAPSYSTEMNAME presente sul server e ritorna il nome del sistema SAP

public String getSystemName(Container container){
   String locale = System.getProperty("SAPSYSTEMNAME");
   return locale;
}

SplitAndMerge

In uno scenario file to Idoc in cui nel mapping dell’idoc occorre modificare il signing in 1:unbounded, qualora fosse necessario implementare diversi mapping in cascata, per tutti i mapping dev’essere modificato il signing in 1:unbounded.

A livello di Operation Mapping il signing dev’essere 1:unbounded.

Operation Mapping

1° mapping

2° mapping

3° mapping (IDoc receiver)


Considera record in base a valore campo

Muovere il valore del campo solo se il campo qualificatore del record a cui il campo source appartiene assume un determinato valore.

Questo esempio funziona se l’output ha lo stesso numero di occorrenze dell’input.

Se l’output ha occorrenza 1 e l’input occorrenza n, questo codice tenderà a mettere in output un solo elemento, quello con PARVW=RE. In realtà, dal momento che vengono generati tanti contesti, CONTEXT, quanti sono gli elementi in input, altrettanti contesti vengono passati in output – anche se quelli scartati perché non soddisfano la regola sono passati a SUPPRESS.

Per fare in modo che solo l’elemento valorizzato venga passato, occorre rimuovere i contesti tramite removeContexts.


Concatenare un array in una stringa

Utile nel caso di testi in cui ogni riga è un context e occorre ridurli tutti al valore di un unico campo

Il risultato della JoinInContainer() è salvato in un container il cui contenuto viene mosso nel campo target.

Includere le seguenti librerie:

N4NGeneralLibrary.jar

N4NPILibrary.jar

Includere i seguenti namespace:

com.n4n.std.*

com.n4n.std.xi.tools.*

Creare un UDF di tipo All Values of a Context.

public void JoinInContainer(String[] name, String[] arr, ResultList result, Container container) throws StreamTransformationException{
/*
name: Nome container di output
arr: Array contenente le stringhe da concatenare.

Concatena le stringhe corrispondenti agli elementi di arr separandole con spazio.
La stringa ottenuta è storicizzata nel container name.
*/
      if (StringManager.isArrayNull(arr)) {
				String[] tx = {""};
				Utils.loadArrayInContainer(name[0], tx, container);
      }

      String t = "";
      for (int i = 0; i < arr.length; i++) {
         if (!StringManager.isStringNull(arr[i])) {
            t += arr[i] + " ";
         }
      }

String[] txt = { t };
Utils.loadArrayInContainer(name[0], txt, container);
}
public String RestoreFromContainer(String name, String dummy1, Container container) throws StreamTransformationException{
/*
name:  Nome container
dummy1: 

Ritorna il valore storicizzato nel container name. Il parametro dummy serve esclusivamente nel mapping grafico 
per legare all’oggetto RestoreFromContainer il blocchetto che lo precede.
*/

GlobalContainer gc = container.getGlobalContainer(); 
String[] g = (String[]) gc.getParameter( name );  // il cast è in funzione di cosa ritorna la getParameter(), per es., potrebbe essere String
String ret = "";
if (!StringManager.isStringNull(g[0])) {
	ret = g[0];
}

return ret;

}