# XML Nachricht  mit Java Servlet weiterleiten



## Robson0815 (6. Sep 2004)

Hallo,
Ich hab da folgende Frage.
Ich will ein Java Servlet haben was XML Nachrichten weiterleitet.

Mal ein Beispiel:

Es wird eine XML Nachricht auf die Adresse http://host:5000/myServlet geschickt.
die XML wird da von einem Servlet eingelesen und das Servlet soll die Nachricht dan weiter auf die Adresse http://host:8000/Adapter/bla/... schicken.

Jemand ne Idee wie man sowas Realiesieren könnte?


----------



## foobar (6. Sep 2004)

```
request.getRequestDispatcher(response.encodeURL("myurl")).forward(request, response);
```


----------



## Robson0815 (6. Sep 2004)

Danke, das ging ja Schnell  :lol: 

Wenn ich jetzt noch was an die XML nachricht anhängen will geht das dann auch so?

Bsp: Nachricht kommt an. 
        XML wird ausgelesen. 
        Es wird was an die Nachricht angehängt. 
        und dann weitergeleitet.


----------



## foobar (6. Sep 2004)

> Wenn ich jetzt noch was an die XML nachricht anhängen will geht das dann auch so?


Ich denke schon, aber mit der Forwardmethode kannst du glaube ich nur Seiten erreichen die den selben Kontext haben. 

Hiermit kannst überall hin weiterleiten:

```
res.sendRedirect("myurl");
```


----------



## Robson0815 (6. Sep 2004)

Gut  .. also weiterleiten kann ich so .

Die Ankommenden Nachrichten, kann ich die dan mittel JDOM einlesen.
Also wen man eine XML nachricht auf mein Servelt schickt(mit WFetch o.ä.).

Ich hab mit JDOM noch nicht gearbeitet ist das dazu da? oder kann man damit nur XML Files einlesen die auf meiner Festplatte liegen ?


----------



## foobar (6. Sep 2004)

Mit JDOM kannst du beliebige Xmldatenströme einlesen, egal ob von der Festplatte oder aus einem Servlet.


----------



## Robson0815 (6. Sep 2004)

Ok .. ich beschreibe nochmal das Ganze Szenario nur damit ich mir sicher sein kann das ich nicht an der falschen stellte suche.

Szenario:

Es wird eine XML Nachricht auf das Servlet ("IPChecker") geschickt (*http://host:5000/IPChecker*). Dieses soll die XML Nachricht auslesen und sie um den Punkt IP Adresse ergänzen. (Die IP Adresse die Ergänzt werden soll, muss die IP Adresse sein, von welcher die XML Nachricht gekommen ist.

Eingangs Nachricht(Die auf das Servlet Geschickt wird):


```
<?xml version="1.0" ?> 
<MESSAGE DTD="XMLMSG" VERSIOM="1.0> 
    <COMMAND> 
    .......... 
    </COMMAND> 
</MESSAGE>
```

Ausgangs Nachricht(Die das Servlet weiterleiten soll):


```
<?xml version="1.0" ?> 
<MESSAGE [b]IP="10.10.10.10"[/b] DTD="XMLMSG" VERSIOM="1.0> 
    <COMMAND> 
    .......... 
    </COMMAND> 
</MESSAGE>
```

Diese Nachricht soll dan weiter auf die Adresse http://host:8000/Adapter/bla geschickt werden.

Kan ich das mit JDOM und in einem Servlet Realiesieren und wo finde ich die nötigen Dokumentationen um sowas zu basteln ?


----------



## foobar (6. Sep 2004)

Man kann das ganze auch ganz einfach mit DOM lösen:

```
private void init()
	{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(true);
		try
		{
			DocumentBuilder builder = factory.newDocumentBuilder();
			builder.setErrorHandler(new TestCenterDTDErrorHandler());
			this.doc = builder.parse(  "myFile.xml" );
		}
		catch (SAXException e)
		{
			throw new XmlException(getClass() + " SAXException: " + e.getMessage()); //$NON-NLS-1$
		}
		catch (IOException e)
		{
			throw new XmlException(getClass() + " IOEXception: " + e.getMessage()); //$NON-NLS-1$
		}
		catch (ParserConfigurationException e)
		{
			throw new XmlException(getClass() + " ParserConfigurationException: " + e.getMessage()); //$NON-NLS-1$
		}
	}
	
	protected void parse() throws XmlException, ConfigException
	{
		HashMap out = new HashMap();
		NodeList lstGroup = doc.getElementsByTagName("group");
		for (int i = 0; i < lstGroup.getLength(); i++)
		{
			Element elmGroup = (Element) lstGroup.item(i);
			String currentGroupName = elmGroup.getAttributes().getNamedItem("name").getNodeValue();
			NodeList lstItem = elmGroup.getElementsByTagName("item");
			for (int j = 0; j < lstItem.getLength(); j++)
			{
				Node nodItem = lstItem.item(j);
				String key = nodItem.getAttributes().getNamedItem("name").getNodeValue();
				String value = nodItem.getAttributes().getNamedItem("value").getNodeValue();
				String type = nodItem.getAttributes().getNamedItem("type").getNodeValue();
				
				.......
					
			}
		}
```
Die Methode parse() der DocumentBuilderklasse kann auch einen InputStream entgegen nehmen, da mußt du dann einfach den InputStream aus dem Servlet übergeben. Ansonsten guck dir die Api-Dokumentation zu den einzelnen Kassen an.


----------



## Robson0815 (6. Sep 2004)

Ich komme mit dem ganzen kram irgendwie nicht besonders gut klar   
Kennt jemand brauchbare Einsteiger Tutorials für DOM/JDOM auf Deutsch ?

Ich finde zwar jede menge Kram aber irgendwie hilft mir das nicht, oder ich bin irgendwie zu doof das zu verstehen :roll:


----------



## Bleiglanz (6. Sep 2004)

>>Es wird eine XML Nachricht auf das Servlet ("IPChecker") geschickt 

ich nehme an, du meinst einen POST request? 

>>Diese Nachricht soll dan weiter auf die Adresse 
>>http://host:8000/Adapter/bla geschickt werden. 

ja aber wie? auch als POST (das ist nicht trivial, weil du dann einen HTTP request erzeugen musst) oder reicht ein request.setAttribute + forward ?

IMHO wärs am einfachsten, du machst das einfach mit String Funktionen, z.B. replaceAll und einem regex

aber auch mit DOM kein Problem:

```
//String neueIP = request.getRemoteHost();
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = builder.parse( new File("example.xml"));
        Element mess = (Element) doc.getElementsByTagName("MESSAGE").item(0);
        mess.setAttribute("ip",neueIP);
        TransformerFactory tFactory = TransformerFactory.newInstance();
        Transformer transformer = tFactory.newTransformer();
        DOMSource source = new DOMSource(doc);
        StringWriter resultStringBuffer = new StringWriter();
        transformer.transform(source, new StreamResult(resultStringBuffer));
        String result = resultStringBuffer.toString();
```


----------



## robson0815 (6. Sep 2004)

Ja die soll auch wieder als POST weitergeleitet werden. 
Aber für heute reicht es mir erstmal .. ne Nacht drüber schlafen und morgen geh ich da nochmal mit neuer Energie dran


----------



## robson0815 (7. Sep 2004)

Wie mach ich es jetzt das er ne XML NAchricht als POST Request empfangen kann ?


```
public class Doorlock extends HttpServlet{
	
	public void doGet(HttpServletRequest request,
			  HttpServletResponse response)
			  throws ServletException, IOException{
		
	
	String remoteIP = request.getRemoteHost(); 
    DocumentBuilder builder = null;
	try {
		builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (FactoryConfigurationError e) {
			e.printStackTrace();
	}
	Document doc = null;
	try {
		doc = builder.parse( new File("myxml.xml"));
		} catch (SAXException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
	}
	Element mess = (Element) doc.getElementsByTagName("MESSAGE").item(0); 
    mess.setAttribute("ip",remoteIP); 
    TransformerFactory tFactory = TransformerFactory.newInstance(); 
    Transformer transformer = null;
	try {
		transformer = tFactory.newTransformer();
		} catch (TransformerConfigurationException e2) {
			e2.printStackTrace();
		}
	DOMSource source = new DOMSource(doc); 
    StringWriter resultStringBuffer = new StringWriter(); 
    try {
		transformer.transform(source, new StreamResult(resultStringBuffer));
		} catch (TransformerException e3) {
			e3.printStackTrace();
		} 
    String result = resultStringBuffer.toString(); 

    result.sendRedirect("http://host:9000/adapter/plain_xi"); 
}
}
```


----------



## Robson (7. Sep 2004)

> Hiermit kannst überall hin weiterleiten:
> 
> ```
> res.sendRedirect("myurl");
> ```



Der kennt den Befehl bei mir gar nicht ..  muss ich ein bestimmtes Paket dafür importieren ?[/quote]


----------



## foobar (7. Sep 2004)

> Der kennt den Befehl bei mir gar nicht .. muss ich ein bestimmtes Paket dafür importieren ?


Nein, eigentlich nicht. Guckst du hier: http://java.sun.com/products/servlet/2.2/javadoc/javax/servlet/http/HttpServletResponse.html#sendRedirect(java.lang.String)


----------



## Robson (7. Sep 2004)

Dann ist in meinem Servlet irgendwo der wurm drin ..


----------



## Bleiglanz (7. Sep 2004)

mit res ist der ServletResponse gemeint, aber das hilft dir hier gar nichts

sendRedirect ist QUARK, damit wird (ein Browser?) aufgefordert einen neuen GET an die Zieladresse abzuschicken - zurückgesendet wird da nur ein HTTP Status code (glaube 303) und die Zieladresse

die POST Daten und deine Bearbeitung sind in diesem Fall verloren, du musst also einen POST request von Hand basteln (java.net.*)!

ODER http://jakarta.apache.org/commons/httpclient/

ODER verwende einen Servlet Filter (das ist viel einfacher und in deinem Fall glaube ich vorteilhafter)


----------



## Robson (7. Sep 2004)

Wenn ich ne Post Anfrage auf mein Servelt Jage sagt der auch immer

* "HTTP Post Methode is not supported by this url"*

das is doch auch irgendwie nicht richtig  :shock:


----------



## Robson (7. Sep 2004)

Also will ich mal schritt für schritt aufschreiben wie ich vorgehen muss, wenn da was falsch ist bitte schreien !

1. Ich bastel ein Servelt mit DOM welche einen Inputstream einliest (Die Post Anfrage in form von XML wo die Daten übergeben werden.)

2. Mit request.getRemoteHost(); hole ich mir die IP vom Sender und hänge sie mit DOM an das XML Dokument.

3. Bastel ich einen Post Request welcher das veränderte XML Dokument an die andere URL schickt.

oder eineen Servlet Filter ( Wo ich allerdings net weis was das ist.)


Aktueller Status:
 Punkt 2 funktioniert halbwegs. Bei 1- 2 hänge ich weil ich weder ahnung von Inputstream und DOM habe , noch weiss ich wie ich nen Post Request bastel. 
Wo finde ich Infos zu diesen themen die mir weiter helfen ?


----------



## Bleiglanz (7. Sep 2004)

zu 1)
...du musst natürlich die doPost methode überschreiben (und dann mit getParameter("namedeseingabetextes") den Input abholen 

zu 2) hamwa ja schon, danach hast du einen String

zu 3) die Idee ist nicht so besonders, du bist ja schon auf dem Server und hast das Resultat als String => jetzt willst du nochmal einen POST auf den gleichen Server losschicken??? 

- mach RequestDispatcher.forward(req,res)
- oder lern was Filter sind
- oder lies http://javaalmanac.com/egs/java.net/Post.html


----------



## Robson (7. Sep 2004)

Was genau meinst du mit "namedeseingabetextes" ?

Das XML file was auf mein Servlet geschickt wird kommt aus einem R/3 System. Diese XML Nachricht soll von meinem Servlet eingelesen werden. So das ich das file dan mit DOM bearbeiten kann.

Das ist im prinzip Schritt 1. nach Schritt 2 haben wir dan den String(Das geänderte XML File) dieses soll dan in ein anderes System(B) geschickt werden was Physikalisch zwar auf dem gleichen System liegt, aber trotzdem ne ganz andere Soße ist.

Zurzeit sendet das R/3 die XML Nachrichten direkt auf das System(B) aber zwischen die beiden System soll das Servelt. 

Deswegen deke ich muss ich schon ein POST Request erzeugen. Obwohl ich zugeben muss das ich auch kein Java Programmierer bin (noch nicht  )


----------



## Bleiglanz (7. Sep 2004)

Robson hat gesagt.:
			
		

> Was genau meinst du mit "namedeseingabetextes" ?



1) Wenns ein POST request ist, dann hast du im Servlet normalerweise einen Parameternamen für den Inhalt?

2) ja ok, wenn das zweite Servlet auf einem anderen Server läuft, dann hiflt nur der manuell erzeugte POST


----------



## Robson (7. Sep 2004)

Damit Simulier ich das R/3 System um eine XML Nachricht los zuschicken.
Das pustet die nachricht auf mein Servlet *"doorlock"*








Hat jemand mal nen code Beispiel wie ich diese Nachricht jetzt in meinem Servlet einlesen kann ? 

weil so wie ich es jetzt habe sucht er ja in der Datei *myxml.xml* oder habe ich jetzt irgendwo total den hänger?


```
....
String remoteIP = request.getRemoteHost(); 
    DocumentBuilder builder = null; 
   try { 
      builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
      } catch (ParserConfigurationException e) { 
         e.printStackTrace(); 
      } catch (FactoryConfigurationError e) { 
         e.printStackTrace(); 
   } 
   Document doc = null; 
   try { 
      doc = builder.parse( new File("myxml.xml")); 
      } catch (SAXException e1) { 
         e1.printStackTrace(); 
      } catch (IOException e1) { 
         e1.printStackTrace(); 
   }

....
```


----------



## Robson (7. Sep 2004)

Ich mal wieder  8) 

so hab ich das jetzt und es funktioniert natürlich nicht


```
String result = resultStringBuffer.toString(); 
	//System.out.println(result);
	
	try {
        
        URL url = new URL("http://10.180.191.174:8000/sap/xi/adapter_plain?bs=ServerRS&interface=ROW_OUT&namespace=RS&QOS=EO");
        URLConnection conn = url.openConnection();
        conn.setDoOutput(true);
        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(result);
        wr.flush();
        wr.close();
       
    } catch (Exception e) {
    }
```

müsste er so nicht die Daten aus der XML Datei die ich jetzt in den String geschrieben habe _String result = resultStringBuffer.toString(); _ an die URL Schicken ? aber er macht es nicht .. oder kommt das jetzt irgendwie anders beim Server an als wenn man die XML direkt schickt ?


----------



## Bleiglanz (7. Sep 2004)

versuchs mal mit 

http://javaalmanac.com/egs/java.net/PostSocket.html


----------



## Robson (7. Sep 2004)

hab das problem erkannt, er übergibt damit nur daten in der URL so wie bei manchen Formularen 

z.B http://host:8000/formular.htm&name=hans&nachname=wurst

aber ich hab meine daten ja im Body stehen wie kann ich die den übergeben ?


----------



## Bleiglanz (7. Sep 2004)

versuchs nochmal mal mit

http://javaalmanac.com/egs/java.net/PostSocket.html


----------



## Robson (7. Sep 2004)

hab ich und ich werd einfach nicht schlau daraus, warum das so nicht funktioniert. Da ist doch jetzt sogar der richtige Header bei !


```
try {
       
		// Create a socket to the host
        String hostname = "server03";
        int port = 8000;
        InetAddress addr = InetAddress.getByName(hostname);
        Socket socket = new Socket(addr, port);
    
        // Send header
        String path = "/sap/xi/adapter_plain?bs=ServerRS&interface=ROW_OUT&namespace=RS&QOS=EO";
        BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
        wr.write("POST "+path+" HTTP/1.1\r\n");
        wr.write("Host: "+hostname+"\r\n");
        wr.write("Accept: */*\r\n");
        wr.write("Content-Length:"+result.length()+"\r\n");
        wr.write("\r\n");
        wr.write(result);
        wr.flush();
        wr.close();
    } catch (Exception e) {
    }
```

kann er dan Path nicht auflösen oder wo hat der sein Problem ?


----------



## Bleiglanz (7. Sep 2004)

du musst das result url encoden und mit "result=" 
in den Stream schreiben, danach nicht

      doc = builder.parse( new File("myxml.xml"));

sondern mit 

```
doc = builder.parse(new StirngReader(request.getParameter("result"));
```
usw.

mal ganz abgesehen davon: du kennst dich mit HTTP / Servlets / XML nicht so besonders aus und musst jetzt so eine (nicht ganz triviale) Aufgabe erledigen? Seltsa

[Edit by foobar: Codetags repariert]


----------



## Robson (7. Sep 2004)

seltsam ist noch gar kein Ausdurck  8)

mich macht das alles Total Wirre !  ???:L 

kann ich an der stelle* doc = builder.parse( new File("myxml.xml")); *

den das so machen *doc = builder.parse(new StirngReader(request.getParameter("result")); *
der kennt doch *result* an der stelle noch gar nicht
result wird doch erst ganz zum schluss gefüllt


----------



## Bleiglanz (7. Sep 2004)

nein, der Servlet Container liest den POST body und extrahiert dir daraus die Variablen als Strings

wenn im POST body steht "foo=bar"

dann liefert request.getParameter("foo") den String "bar"


----------



## Robson (8. Sep 2004)

Das ist doch der body von meinem Post.


```
<?xml version="1.0" ?>
<MESSAGE DTD="XMLMSG" VERSIOM="1.0>
    <COMMAND> 
   
    </COMMAND> 
</MESSAGE>
```

und ich will den ganzen body einlesen. Weil der ganze Body soll ja auch weitergeleitet werden.


----------



## Bleiglanz (8. Sep 2004)

Dann musst du 

request.getInputStream 

verwenden. Das ist aber dann wahrscheinlich kein gülltiger HTTP Post, weil ja eigentlich immer name=wert paare im body stehen sollen


----------



## Robson (8. Sep 2004)

```
ServletInputStream data = request.getInputStream();
			doc = builder.parse(data);
```

Wieso geht das jetzt nicht ? 

sollte er zeile 1 nicht den inputstream einlesen und dan hat er die xml Daten  und in zeile 2 sie dan parsen so wie wenn man nen xml file da angeben würde ?


----------



## Bleiglanz (8. Sep 2004)

Robson hat gesagt.:
			
		

> Wieso geht das jetzt nicht ?



ich hab jetzt keine Lust mehr: kannst du nicht mal beschreiben WAS nicht geht? bye


----------



## Robson (8. Sep 2004)

naja..

Der Anfang und das Ende funktioniert noch nicht  :roll: 

Also einmal die XML Daten aufzunehmen aus dem POST Request auf mein Servlet.
und einmal das senden einens XML POST Request auf eine andere URL.

Tortzdem Danke für deine mühe. Sorry das ich dich so generft habe.

 :###


----------



## Bleiglanz (8. Sep 2004)

wie wärs mit fehlermeldungen o.ä? soll ich vielleicht raten was nicht funktioniert?


----------



## Robson (8. Sep 2004)

hab nen neuen thread aufgemacht zum Problem Nr.1 ... wenn du die schnauze noch nicht voll hast kannst ja mal reingucken


----------

