# SOAP Messaging Fehler



## meister-g (9. Mai 2008)

Hallo Java-Gemeinde,

nachdem ich mit einer Quick&Dirty Version gescheitert bin das alte JAXM-Paket mit Java 1.6 kompatibel zu machen (Namespace-Problem-etc), habe ich mich von diesem Komplettpaket gelöst und verwende nur noch SOAP.

D.h ich habe mich von der Implementierung mit Hilfe von JAXM (veraltet und eigentlich nicht benötigt) getrennt und verwende kein externes Paket mehr (SOAP seit Java 1.6 enthalten).
Ziel ist es im Prinzip lediglich XML (->SOAP) über HTTP zu übertragen.

Meine Implementierung steht, allerdings erhalte ich folgenden internen Fehler beim Verbindungsaufbau:

09.05.2008 14:10:31 com.sun.xml.internal.messaging.saaj.soap.MessageImpl identifyContentType
SCHWERWIEGEND: SAAJ0537: Invalid Content-Type. Could be an error message instead of a SOAP message
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?
	at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.identifyContentType(MessageImpl.java:605)
	at com.sun.xml.internal.messaging.saaj.soap.MessageImpl.<init>(MessageImpl.java:278)
	at com.sun.xml.internal.messaging.saaj.soap.ver1_1.Message1_1Impl.<init>(Message1_1Impl.java:68)
	at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl.createMessage(SOAPMessageFactory1_1Impl.java:62) 
at de.mynamespace.MyHttpSOAPConnection.call(ColHttpSOAPConnection.java:116)


Implementierung:
Client: Gültige und existierende SOAPMessage wird über eine SOAPConnection verschickt. Dabei habe ich sowohl

```
SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
  
    SOAPConnection con = factory.createConnection();
      
      SOAPMessage reply = con.call(message, sUriEndPoint);
```

als auch statt der Factory eine eigene Connection-Klasse (Implementierung wie JAXM-Klasse HttpSOAPConnection) versucht. (Beides liefert den gleichen Fehler).


Als Servlet habe ich von HttpServlet abgeleitet. Und folgenden Code aus der JAXM-Implementierung (JAXMServlet) in dieser Klasse übernommen:




```
private static MessageFactory msgFactory = null; 
  private String fname = null; 



  /**
   * Initialisiert das Servlet
   * @param servletConfig Konfigurationsdaten des Servlets
   * @exception ServletException wird geworfen, wenn kein InitialContext gefunden wurde
   */
  public void init(ServletConfig servletConfig) throws ServletException {
    if (log.isDebugEnabled()) log.debug("Initialisierung eines neuen Listeners.");
    super.init(servletConfig);
    try {
      this.ctx = new InitialContext();
    } catch (NamingException ex) {
      log.error("Der InitialContext konnte nicht erstellt werden.");
      throw new ServletException("Der InitialContext konnte nicht erstellt werden.");
    }
    
    try { 
        msgFactory = MessageFactory.newInstance(); 
    } catch (SOAPException ex) { 
        throw new ServletException("Unable to create message factory"+ ex.getMessage()); 
    } 

  }
  
  
  /**
   * Internalizes the given <code>HttpServletRequest</code> object
   * and writes the reply to the given <code>HttpServletResponse</code>
   * object.
   * 


   * Note that the value for the <code>msgFactory</code> field will be used to
   * internalize the message. This ensures that the message
   * factory for the correct profile is used.
   *
   * @param req the <code>HttpServletRequest</code> object containing the
   *        message that was sent to the servlet
   * @param resp the <code>HttpServletResponse</code> object to which the
   *        response to the message will be written
   * @throws ServletException if there is a servlet error
   * @throws IOException if there is an input or output error
   */
  public void doPost(HttpServletRequest req, 
                     HttpServletResponse resp)
      throws ServletException, IOException 
  {
	try {
          // Get all the headers from the HTTP request.
	    MimeHeaders headers = getHeaders(req);

          // Get the body of the HTTP request.
          InputStream is = req.getInputStream();

          // Now internalize the contents of a HTTP request and
          // create a SOAPMessage
	    SOAPMessage msg = msgFactory.createMessage(headers, is);
	    
	    SOAPMessage reply = null;

	    reply = onMessage(msg); 

          if (reply != null) {
              
              // Need to saveChanges 'cos we're going to use the
              // MimeHeaders to set HTTP response information. These
              // MimeHeaders are generated as part of the save.

              if (reply.saveRequired()) {
                  reply.saveChanges(); 
              }

              resp.setStatus(HttpServletResponse.SC_OK);

              putHeaders(reply.getMimeHeaders(), resp);
                  
                  // Write out the message on the response stream.
                  OutputStream os = resp.getOutputStream();
                  reply.writeTo(os);

                  os.flush();
                  
          } else 
              resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
      }
      catch(Exception ex) {
          throw new ServletException("JAXM POST failed "+ex.getMessage());
	}
  }
  
  
  /**
   * Returns a <code>MimeHeaders</code> object that contains the headers
   * in the given <code>HttpServletRequest</code> object.
   *
   * @param req the <code>HttpServletRequest</code> object that a
   *        messaging provider sent to the servlet
   * @return a new <code>MimeHeaders</code> object containing the headers
   *         in the message sent to the servlet
   */
  protected static
      MimeHeaders getHeaders(HttpServletRequest req) 
  {
      Enumeration enumeration = req.getHeaderNames();
      MimeHeaders headers = new MimeHeaders();

      while (enumeration.hasMoreElements()) {
          String headerName = (String)enumeration.nextElement();
          String headerValue = req.getHeader(headerName);

          StringTokenizer values = new StringTokenizer(headerValue, ",");
          while (values.hasMoreTokens())
              headers.addHeader(headerName, values.nextToken().trim());
      }
      
      return headers;
  }

  /**
   * Sets the given <code>HttpServletResponse</code> object with the
   * headers in the given <code>MimeHeaders</code> object.
   * 
   * @param headers the <code>MimeHeaders</code> object containing the
   *        the headers in the message sent to the servlet
   * @param res the <code>HttpServletResponse</code> object to which the
   *        headers are to be written
   * @see #getHeaders
   */
  protected static
      void putHeaders(MimeHeaders headers, HttpServletResponse res) 
  {
      Iterator it = headers.getAllHeaders();
      while (it.hasNext()) {
          MimeHeader header = (MimeHeader)it.next();
          
          String[] values = headers.getHeader(header.getName());
          if (values.length == 1)
              res.setHeader(header.getName(), header.getValue());
          else 
              {
                  StringBuffer concat = new StringBuffer();
                  int i = 0;
                  while (i < values.length) {
                      if (i != 0)
                          concat.append(',');
                      concat.append(values[i++]);
                  }
                  
                  res.setHeader(header.getName(),
                                concat.toString());
              }
      }
  }
```


Zusätzlich natürlich onMessage() nach meinen Wünchen implementiert.



Kann mir hier bitte jemand weiterhelfen? Woran liegt das Problem bzw. wie kann ich es Lösen? Gibt es alternativen (ohne komplexe Web-Services pakete) XML über HTTP zu verschicken?[/code]


----------



## Murray (10. Mai 2008)

meister-g hat gesagt.:
			
		

> 09.05.2008 14:10:31 com.sun.xml.internal.messaging.saaj.soap.MessageImpl identifyContentType
> SCHWERWIEGEND: SAAJ0537: Invalid Content-Type. Could be an error message instead of a SOAP message
> com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?



Der Server liefert also in seinem Response_Header den Content-Type "text/html" - das sollte bei einem gültigen SOAP-Request eigentlich nicht passieren; der Server liefert also eine HTML-Seite (vermutlich mit einer lesbaren Fehlermeldung) anstelle eines SOAP-Response.


Was ist denn das für ein Server? Hast Du den unter Kontrolle? Dann solltest Du beim Debugging dort ansetzen. Ansonsten könntest Du versuchen, irgendwie den HTTP-Traffic mitzuschneiden und so die Fehlermeldung zu sehen.


----------



## meister.g (10. Mai 2008)

ja, den server habe ich unter kontrolle.

wie beschrieben ist es ein servlet welches auf einem tomcat läuft.

ich habe schon versucht dort zu loggen aber bis zu der doGet() methode serverseitig kommt es offensichtlich gar nicht.


den http traffic anzusehen ist dann mein nächster plan, danke für die info. unter der fehlernummer liefert google auch einige ergebnisse, werde die mal durcharbeiten.


wer sonst noch ideen und antworten auf meine fragen hat bitte nicht zögern... das problem wurmt mich langsam gewaltig


----------



## meister-g (15. Mai 2008)

Ich habe jetzt mal den http Transfer untersucht, das liefert der Server:


```
HTTP/1.1 500 Internal Server Error
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 3139
Date: Thu, 15 May 2008 09:50:22 GMT
Connection: close

<html><head><title>Apache Tomcat/5.5.23 - Error report</title><style></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade">

[b]type[/b] Exception report</p>

[b]message[/b] <u></u></p>

[b]description[/b] <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p>

[b]exception[/b] <pre>javax.servlet.ServletException: Error allocating a servlet instance
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
	org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
	org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
	org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
	org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
	org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
	java.lang.Thread.run(Unknown Source)
</pre></p>

[b]root cause[/b] <pre>java.lang.UnsupportedClassVersionError: Bad version number in .class file
	java.lang.ClassLoader.defineClass1(Native Method)
	java.lang.ClassLoader.defineClass(Unknown Source)
	java.security.SecureClassLoader.defineClass(Unknown Source)
	org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1847)
	org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:873)
	org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1326)
	org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1205)
	org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
	org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
	org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870)
	org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
	org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
	org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
	org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
	java.lang.Thread.run(Unknown Source)
</pre></p>

[b]note[/b] <u>The full stack trace of the root cause is available in the Apache Tomcat/5.5.23 logs.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/5.5.23</h3></body></html>
```

Edit...
Die Fehlermeldung war natürlich weil ich den 1.6er colpilierten Code mit dem alten JRE habe laufen lassen. Nun die fehlerhafte Antworts des Servers zitiert.

Kann mir nun jemand evtl. weiterhelfen?


----------



## Murray (15. Mai 2008)

Da steht es ja:


			
				tomcat hat gesagt.:
			
		

> java.lang.UnsupportedClassVersionError: de/mycode/Listener (Unsupported major.minor version 50.0)


Dort wird eine Klasse de.mycode.Listener geladen, die mit dem JDK 1.6 übersetzt wurde. Der Server läuft aber offenbar mit einer JRE < 1.6


----------



## meister-g (15. Mai 2008)

danke murray, selbst bemerkt und posting editiert


----------



## Murray (15. Mai 2008)

Sieht so aus, als passten JDK und JRE immer noch nicht zusammen.


----------



## meister-g (15. Mai 2008)

argl... ich doof, danke

client + server compiliert unter 1.6

client jre < 1.6 -> 
java.lang.UnsupportedClassVersionError: de/mycode/Listener (Unsupported major.minor version 50.0)

server jre < 1.6 ->
java.lang.UnsupportedClassVersionError: Bad version number in .class file 


jetzt lass ich apache mal unter der 1.6 laufen und schaue ob es funktioniert


----------



## meister-g (15. Mai 2008)

```
HTTP/1.1 500 Internal Server Error
Content-Type: text/html;charset=ISO-8859-1
Content-Language: de-DE
Content-Length: 1590
Date: Thu, 15 May 2008 10:45:31 GMT
Server: Apache-Coyote/1.1
Connection: close

<html><head><title>Apache Tomcat/5.0.25 - Error report</title><style></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade">

[b]type[/b] Exception report</p>

[b]message[/b] <u></u></p>

[b]description[/b] <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p>

[b]exception[/b] <pre>javax.servlet.ServletException: JAXM POST failed Invalid Content-Type:application/x-www-form-urlencoded. Is this an error message instead of a SOAP response?
	de.mycode.Listener.doPost(Listener.java:188)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	de.mycode.Listener.service(Listener.java:334)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
</pre></p>

[b]note[/b] <u>The full stack trace of the root cause is available in the Apache Tomcat/5.0.25 logs.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/5.0.25</h3></body></html>
```


jetzt scheinen die versionsprobleme behoben zu sein, aber anscheined gibt es nun fehler im servlet-code (siehe ganz oben) - codezeile 89 wir wird die exception gefangen und wird in zeile 59 (SOAPMessage msg = msgFactory.createMessage(headers, is); ) geworfen.


hier der request stream:


```
POST /myServlet HTTP/1.1
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_03
Host: collpc104:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-type: application/x-www-form-urlencoded
Content-Length: 253

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body><m:ConnectRequest client-version="2.3.4" xmlns:m="http://myurl:8080/ConnectRequest.dtd"/></SOAP-ENV:Body></SOAP-ENV:Envelope>
```

und der response stream:

```
HTTP/1.1 500 Internal Server Error
Content-Type: text/html;charset=ISO-8859-1
Content-Language: de-DE
Content-Length: 1590
Date: Thu, 15 May 2008 10:58:02 GMT
Server: Apache-Coyote/1.1
Connection: close

<html><head><title>Apache Tomcat/5.0.25 - Error report</title><style></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade">

[b]type[/b] Exception report</p>

[b]message[/b] <u></u></p>

[b]description[/b] <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p>

[b]exception[/b] <pre>javax.servlet.ServletException: JAXM POST failed Invalid Content-Type:application/x-www-form-urlencoded. Is this an error message instead of a SOAP response?
	de.mycode.Listener.doPost(Listener.java:190)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	de.mycode.Listener.service(Listener.java:336)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
</pre></p>

[b]note[/b] <u>The full stack trace of the root cause is available in the Apache Tomcat/5.0.25 logs.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/5.0.25</h3></body></html>
```



kann mir jemand weiterhelfen?

aus der exception lese ich, dass dem servlet
"Content-type: application/x-www-form-urlencoded"
aus dem request wohl nicht gefällt. aber wie ändere ich das?


edit:
implementiert unter 1.4 und jaxm enthielten die requests
"Content-Type: text/xml; charset="utf-8"

die messages werden ja von der jeweilig implementierten factory implementiert. ist der "falsche" content-type ein fehler oder eine "einstellung". wie behebe ich das bzw wie setze ich den content-type?


----------



## meister-g (15. Mai 2008)

ich nochmal 

mit der hoffnung dass mir jemand weiterhelfen kann


wie gesagt wird ja eine von java implementierte factory verwendet:


```
MessageFactory factory = MessageFactory.newInstance();
    	SOAPMessage message = factory.createMessage();
```

ich vermute mal, dass in dieser methode der content-type in der implementierung vom neuen soap-paket in java 1.6 eben default-mäßig auf "application/x-www-form-urlencoded" gesetzt wird (in der alten jaxm implementierung text/html, was vom servlet akzeptiert wird)

Also probierte ich mal folgendes


```
message.getMimeHeaders().setHeader("Content-type", "text/xml");
```


das scheint aber nicht richtig zu sein, der content-type bleibt unverändert

aufgefallen ist mir aber, dass wenn ich nicht "text/xml" sondern z.B. "test" verwende eine exception in der aufgerufenen methode saveChanges() geworden wird. irgendwas passiert also doch...


hat jemand einen rat oder eine lösung parat?


----------



## meister-g (16. Mai 2008)

Nach zermürbenden Debuggen quer durch Exceptions und durch die verschiedensten Implementierungen und Factorymethoden die noch verschiedenere Implementierungen verwenden habe ich des Rätsels Lösung gefunden:
Im Tomcat Verzeichnis common/endorsed alle Dateien Löschen (in meinem Fall zwei Jars, welche wohl XML Parser sind).

Das lustige: Nun funktionieren ALLE Implementierungen. (Java Standard SOAP, SAAJ, ...)


----------

