{"id":978,"date":"2007-07-05T23:30:05","date_gmt":"2007-07-06T07:30:05","guid":{"rendered":"http:\/\/cephas.net\/blog\/2007\/07\/05\/debugging-soap-xfire-with-ethereal\/"},"modified":"2007-07-05T23:30:05","modified_gmt":"2007-07-06T07:30:05","slug":"debugging-soap-xfire-with-ethereal","status":"publish","type":"post","link":"https:\/\/cephas.net\/blog\/2007\/07\/05\/debugging-soap-xfire-with-ethereal\/","title":{"rendered":"Debugging SOAP \/ XFire with ethereal"},"content":{"rendered":"<p>I&#8217;ve spent way more time than I should have the last couple weeks working to help migrate a website built against Jive Forums to run against a Clearspace X instance. As part of the migration, one of the things I did was to move all the data syndication that had been done with RSS and custom namespaces to use the <a href=\"http:\/\/www.jivesoftware.com\/builds\/docs\/clearspace\/latest\/ClearspaceWebServicesDevGuide.html\">Clearspace SOAP API<\/a>, which is built on a technology called <a href=\"http:\/\/xfire.codehaus.org\/\">XFire<\/a>.  The first problem I ran into was that production website was configured so that requests to http:\/\/example.com were redirected to http:\/\/www.example.com\/, which resulted in errors like this in the logs:<\/p>\n<pre>\r\nJul 5, 2007 11:30:11 PM org.apache.commons.httpclient.HttpMethodDirector isRedirectNeeded\r\nINFO: Redirect requested but followRedirects is disabled\r\n<\/pre>\n<p>That error was pretty easy to fix (swap in http:\/\/www.example.com in place of http:\/\/example.com), but the next thing I ran into was way less intuitive. When I invoked a certain service, I&#8217;d get a stack trace that looked like this:<\/p>\n<pre>\r\nException in thread \"main\" org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. \r\nNested exception is org.codehaus.xfire.fault.XFireFault: Unexpected character '-' (code 45) in prolog; expected '<'\r\n at [row,col {unknown-source}]: [2,1]\r\norg.codehaus.xfire.fault.XFireFault: Unexpected character '-' (code 45) in prolog; expected '<'\r\n at [row,col {unknown-source}]: [2,1]\r\n\tat org.codehaus.xfire.fault.XFireFault.createFault(XFireFault.java:89)\r\n\tat org.codehaus.xfire.client.Client.onReceive(Client.java:386)\r\n<\/pre>\n<p>which was troubling because the exact same SOAP method invocation worked fine on both my local machine and in the test environment. What was different? Two things: the production system was running on Java 6 and the production system was configured to run behind an <a href=\"http:\/\/httpd.apache.org\/\">Apache HTTP server<\/a> proxied by <a href=\"http:\/\/www.caucho.com\/resin-3.0\/install\/plugin-dispatch.xtp\">mod_caucho<\/a> versus no Apache HTTP server \/ proxy in development or on my machine. I needed to see what was going on between the server and the client (one of the things that makes SOAP so hard is that you can't just GET a URL to see what's being returned) so I fired up <a href=\"http:\/\/www.ethereal.com\/\">ethereal<\/a> at the behest of one of my coworkers.  I kicked off a couple of SOAP requests with ethereal running, recorded the packets and then analyzed the capture. Said coworker then pointed out the key to debugging HTTP requests with ethereal: right click on the TCP packet you're interested in and then click 'Follow TCP Stream'.  The invocation response looked like this when run against the development environment:<\/p>\n<pre>\r\nHTTP\/1.1 200 OK\r\nDate: Mon, 02 Jul 2007 21:59:30 GMT\r\nServer: Resin\/3.0.14\r\nContent-Type: multipart\/related; type=\"application\/xop+xml\"; start=\"<soap.xml@xfire.codehaus.org>\"; start-info=\"text\/xml\"; .boundary=\"----=_Part_5_25686393.1183413571061\"\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n1dce\r\n\r\n------=_Part_5_25686393.1183413571061\r\nContent-Type: application\/xop+xml; charset=UTF-8; type=\"text\/xml\"\r\nContent-Transfer-Encoding: 8bit\r\nContent-ID: <soap.xml@xfire.codehaus.org>\r\n...\r\n<\/pre>\n<p>and looked like this when invoked against the production instance:<\/p>\n<pre>\r\nHTTP\/1.1 200 OK\r\nDate: Mon, 02 Jul 2007 21:41:56 GMT\r\nServer: Apache\/2.0.52 (Red Hat)\r\nVary: Accept-Encoding,User-Agent\r\nCache-Control: max-age=0\r\nExpires: Mon, 02 Jul 2007 21:41:56 GMT\r\nTransfer-Encoding: chunked\r\nContent-Type: text\/plain; charset=UTF-8\r\nX-Pad: avoid browser bug\r\n\r\n24e\r\n\r\n------=_Part_29_31959705.1183412516805\r\nContent-Type: application\/xop+xml; charset=UTF-8; type=\"text\/xml\"\r\nContent-Transfer-Encoding: 8bit\r\nContent-ID: <soap.xml@xfire.codehaus.org>\r\n...\r\n<\/pre>\n<p>Notice the different content type returned by the production server?  So then the mystery became not 'what?' but 'who?'  I googled around for a bit and found a <a href=\"http:\/\/jira.atlassian.com\/browse\/JRA-11515\">bug filed against JIRA<\/a> that had all the same symptoms as the problem I was running into: the solution posted in the comments of the bug said that the problem was with mod_caucho.  I worked with the ISP that hosts the production  instance of Clearspace, got them to remove mod_caucho and use mod_proxy to isolate that piece of the puzzle and sure enough, the problem went away.  Our ISP recommended that we not settle for mod_proxy for the entire site and instead wrote up a nifty solution using mod_rewrite and mod_proxy, which I've pasted below:<\/p>\n<pre>\r\n RewriteRule ^\/clearspace\/rpc\/soap(\/?(.*))$ to:\/\/www.example.com:8080\/clearspace\/rpc\/soap$1\r\n RewriteRule ^to:\/\/([^\/]+)\/(.*)    http:\/\/$1\/$2   [E=SERVER:$1,P,L]\r\n ProxyPassReverse \/community\/rpc\/soap\/ http:\/\/www.example.com\/clearspace\/rpc\/soap\/\r\n<\/pre>\n<p>Hope that helps someone down the road!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve spent way more time than I should have the last couple weeks working to help migrate a website built against Jive Forums to run against a Clearspace X instance. As part of the migration, one of the things I did was to move all the data syndication that had been done with RSS and &hellip; <a href=\"https:\/\/cephas.net\/blog\/2007\/07\/05\/debugging-soap-xfire-with-ethereal\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Debugging SOAP \/ XFire with ethereal<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,16,33,10],"tags":[],"_links":{"self":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/978"}],"collection":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/comments?post=978"}],"version-history":[{"count":0,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/978\/revisions"}],"wp:attachment":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/media?parent=978"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/categories?post=978"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/tags?post=978"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}