{"id":1000271,"date":"2006-11-12T13:18:04","date_gmt":"2006-11-12T18:18:04","guid":{"rendered":"http:\/\/www.elharo.com\/blog\/software-development\/2006\/11\/12\/porting-a-java-program-to-php\/"},"modified":"2006-11-12T15:07:34","modified_gmt":"2006-11-12T20:07:34","slug":"porting-a-java-program-to-php","status":"publish","type":"post","link":"https:\/\/www.elharo.com\/blog\/software-development\/2006\/11\/12\/porting-a-java-program-to-php\/","title":{"rendered":"Porting a Java Program to PHP"},"content":{"rendered":"<p>In <a href=\"http:\/\/www.cafeconleche.org\/books\/xmljava\/\">Processing XML with Java<\/a>, I used an example of plain text, XML-RPC, and SOAP clients that communicate with a Fibonacci number server I run here on www.elharo.com. Originally I wrote the servers in Java using the Java Servlet API. However, problems with Tomcat meant that the server went down every few months. When I moved this server from Linux to a Mac I didn&#8217;t even bother to reinstall Tomcat, and instead decided to port the servers to PHP 5. PHP has its own idiosyncrasies, but I use it for other things on this server (including this blog), and it didn&#8217;t seem worth keeping Tomcat running just for a few simple scripts.<br \/>\n<!--more--><\/p>\n<p>Porting the <a href=\"\/fibonacci\">plain text Fibonacci server<\/a> was straightforward since it&#8217;s based on GET and query strings. It&#8217;s just a few lines of code:<\/p>\n<pre><code>&lt;?php\r\n$generations = $_GET['generations'];\r\nif ( $generations == 0) {\r\n  $generations = 10;\r\n}\r\n$low = 1;\r\n$high = 1;\r\nfor ( $counter = 1; $counter &lt;= $generations; $counter++) {\r\n    echo $low;\r\n    $oldhigh = $high;\r\n    $high = $high + $low;\r\n\t$low = $oldhigh;\r\n    echo \" \";\r\n}\r\n?><\/code><\/pre>\n<p>The next two proved harder. PHP has always been aimed at hacking together web sites for browser delivery. It&#8217;s never worked well as soon as you attempt anything more complex than that. In particular, it expects to see POST requests as x-www-formurlencoded strings, just like GET requests. Start sending XML, whether XML-RPC or SOAP or XForms or something else, and it more-or-less punts. <\/p>\n<p>When I first started doing this back in the days of PHP 3 it was simply impossible to respond to XML-RPC requests in PHP. (That&#8217;s a big reason I went with servlets in the first place.) Nowadays I understood that in PHP 4 and 5 it was possible to see the raw request body, and parse it as you liked using <code>$HTTP_RAW_POST_DATA<\/code> (or <code>$_SERVER[HTTP_RAW_POST_DATA]<\/code> or <code>$GLOBALS[HTTP_RAW_POST_DATA]<\/code>; various references couldn&#8217;t seem to agree on this point) Anyway, that didn&#8217;t matter because none of those worked at all. <\/p>\n<p>I inspected the source code for various PHP, SOAP, and XForms libraries and all of them seemed to be using <code>$HTTP_RAW_POST_DATA<\/code>. One XForms library did suggest this:<\/p>\n<pre><code>if (!isset($HTTP_RAW_POST_DATA)) {\r\n   echo \"Not set\";\r\n   $HTTP_RAW_POST_DATA = file_get_contents(\"php:\/\/input\");\r\n}<\/code><\/pre>\n<p>That confirmed my suspicion that the variable wasn&#8217;t set; but still failed to give me the input data I needed. Fortunately I&#8217;m not the <a href=\"http:\/\/marc.theaimsgroup.com\/?l=php-dev&#038;m=103697306505179&#038;w=2\">only<\/a> <a href=\"http:\/\/www.phpbuilder.com\/board\/showthread.php?t=10304087\">person<\/a> having trouble with this. Seems like there&#8217;s something called <code>always_populate_raw_post_data<\/code> I may need to set in php.ini? So let&#8217;s add <\/p>\n<p><code>always_populate_raw_post_data = On <\/code><\/p>\n<p>to my php.ini file, backup the server, and then restart Apache. (I&#8217;m always paranoid before a server restart.) And still nothing happens! Bleah. Time to do a little more digging. Nothing on the web seems to help so I look at my own code. In particular I make the PHP script print out the client headers to see what it&#8217;s sending:<\/p>\n<pre><samp>$ java FibonacciXMLRPCClient 10\r\nGET\r\nNot set\r\n\r\nDebugging\r\nArray\r\n(\r\n    [UNIQUE_ID] => 3jinfcCo-igAAD1VqbUAAAAM\r\n    [HTTP_USER_AGENT] => Java\/1.5.0_06\r\n...\r\n<\/samp><\/pre>\n<p>What the hell? It&#8217;s using GET?! Why is it doing that? Time to look at the client. Hmm, that looks OK:<\/p>\n<pre><code>      URL u = new URL(server);\r\n      URLConnection uc = u.openConnection();\r\n      HttpURLConnection connection = (HttpURLConnection) uc;\r\n      connection.setDoOutput(true);\r\n      connection.setDoInput(true); \r\n      connection.setRequestMethod(\"POST\");\r\n      OutputStream out = connection.getOutputStream();\r\n      OutputStreamWriter wout = new OutputStreamWriter(out, \"UTF-8\");<\/code><\/pre>\n<p>I do note I should probably be setting the Content-type header, but it is specifying POST. Why am I seeing GET coming into the server? Maybe I&#8217;m running an older version of the code? I try recompiling but that doesn&#8217;t fix it. I try printing out the URLConnection&#8217;s own opinion of its method. <\/p>\n<pre><code>      URL u = new URL(server);\r\n      URLConnection uc = u.openConnection();\r\n      HttpURLConnection connection = (HttpURLConnection) uc;\r\n      connection.setDoOutput(true);\r\n      connection.setDoInput(true); \r\n      connection.setRequestMethod(\"POST\");\r\n      <em>System.err.println(connection.getRequestMethod());<\/em>\r\n      OutputStream out = connection.getOutputStream();\r\n      OutputStreamWriter wout = new OutputStreamWriter(out, \"UTF-8\");<\/code><\/pre>\n<p>However, the client thinks it&#8217;s sending POST and the SERVER thinks it&#8217;s hearing GET:<\/p>\n<pre><samp>$ java FibonacciXMLRPCClient 10\r\nPOST\r\nGET\r\nNot set\r\n...\r\n<\/samp><\/pre>\n<p>Someone&#8217;s lying to me and I don&#8217;t know who. Let&#8217;s try pointing the client at a different page, one that just uses <code>phpinfo()<\/code>, and see what it thinks. OK, that page also thins the client is sending POST, not GET so something must be wrong with my script. <\/p>\n<p><img decoding=\"async\" id=\"image1000272\" width='634' height='427' src=\"http:\/\/www.elharo.com\/blog\/wp-content\/uploads\/2006\/11\/headersinfo.png\" alt=\"HTTP Request POST \/test.phtml HTTP\/1.1\" \/><\/p>\n<p>What could possibly be the difference between these two cases? What could be getting in my way and changing the POST to a GET? Here&#8217;s an idea: the phpinfo() URL was referenced directly, but the XML-RPC URL was referenced by pointing to its directory. I.e. I was loading http:\/\/www.elharo.com\/fibonacci\/XML-RPC instead of http:\/\/www.elharo.com\/fibonacci\/XML-RPC\/index.php. Could that have something to do with it? Let&#8217;s try:<\/p>\n<pre><samp>$ java FibonacciXMLRPCClient 10 http:\/\/www.elharo.com\/fibonacci\/XML-RPC\/index.php\r\nPOST\r\nPOST\r\n...\r\n<\/samp><\/pre>\n<p>Bingo! That&#8217;s how the POST is changed to a GET.  Further testing reveals that http:\/\/www.elharo.com\/fibonacci\/XML-RPC\/ with a trailing slash retains the POST method but http:\/\/www.elharo.com\/fibonacci\/XML-RPC without a trailing slash switches it to GET.<\/p>\n<p>I wonder if this is documented behavior or a bug in Apache 2 or PHP 5? And is there an obvious workaround?<\/p>\n<p>If anyone has any ideas about how to fix this, please comment. In the meantime, I&#8217;m going to move on to the next step: implementing the XML-RPC response.<br \/>\n<!--nextpage--><\/p>\n<h2>XML-RPC<\/h2>\n<p>Once I actually managed to read the raw post data, parsing it and generating the appropriate response was easy. It&#8217;s just math and a little <a href=\"http:\/\/www-128.ibm.com\/developerworks\/library\/x-simplexml.html\">SimpleXML<\/a>:<\/p>\n<pre><code>&lt;?php\r\n\r\nif (!isset($HTTP_RAW_POST_DATA)) {\r\n   echo \"Please make sure the URL ends in a trailing slash\";\r\necho \"\\n\";\r\n}\r\n$request = $HTTP_RAW_POST_DATA;\r\n$methodCall =  simplexml_load_string($request);\r\n$value = $methodCall->params->param->value->int;\r\n\r\necho \"&lt;methodResponse>\\n\";\r\necho \"  &lt;params>\\n\";\r\necho \"    &lt;param>\\n\";\r\necho \"      &lt;value>&lt;double>\";\r\necho fibonacci($value);\r\necho \"&lt;\/double>&lt;\/value>\\n\";\r\necho \"    &lt;\/param>\\n\";\r\necho \"  &lt;\/params>\\n\";\r\necho \"&lt;\/methodResponse>\\n\";\r\n\r\n\r\nfunction fibonacci($generations)\r\n{\r\n\r\n  $low = 1;\r\n  $high = 1;\r\n  for ( $counter = 1; $counter &lt; $generations; $counter++) {\r\n    $oldhigh = $high;\r\n    $high = $high + $low;\r\n\t$low = $oldhigh;\r\n  }  \r\n  return $high;\r\n  \r\n}<\/code><\/pre>\n<p>I need to improve the error handling, and make sure the response MIME type is correct, but that&#8217;s basically it.<\/p>\n<p>One downside: this program is noticeably slower than the Java version for even medium sized input. I guess PHP isn&#8217;t designed to do really vast arithmetic. If any PHP gurus see opportunities for optimization please holler.<br \/>\n<!--nextpage--><\/p>\n<h2>SOAP<\/h2>\n<p>The SOAP server is similar. We just parse a SOAP request and generate a SOAP envelope instead of an XML-RPC request and envelope:<\/p>\n<pre><code>&lt;?php\r\n\r\nif (!isset($HTTP_RAW_POST_DATA)) {\r\n   fault(\"Please make sure the URL ends with a forward slash (\/).\r\n          For example, http:\/\/www.elharo.com\/fibonacci\/SOAP\/\r\n          not http:\/\/www.elharo.com\/fibonacci\/SOAP\");\r\n}\r\nelse {\r\n    $request = $HTTP_RAW_POST_DATA;\r\n    $envelope =  simplexml_load_string($request);\r\n    $envelope->registerXPathNamespace('fib', 'http:\/\/namespaces.cafeconleche.org\/xmljava\/ch3\/');\r\n    $values = $envelope->xpath('\/\/fib:calculateFibonacci');\r\n    \r\n    echo \"&lt;SOAP-ENV:Envelope\r\n xmlns:SOAP-ENV='http:\/\/schemas.xmlsoap.org\/soap\/envelope\/' \/>\r\n  &lt;SOAP-ENV:Body>\r\n    &lt;Fibonacci_Numbers \r\n      xmlns='http:\/\/namespaces.cafeconleche.org\/xmljava\/ch3\/'>\\n\";\r\n    foreach ($values as $value) {\r\n      fibonacci($value);\r\n      break;\r\n    }\r\n\r\n    echo \"&lt;\/Fibonacci_Numbers>\r\n  &lt;\/SOAP-ENV:Body>\r\n&lt;\/SOAP-ENV:Envelope>\";\r\n}\r\n\r\nfunction fibonacci($generations)\r\n{\r\n\r\n  $low = 1;\r\n  $high = 1;\r\n  for ( $index = 1; $index &lt;= $generations; $index++) {\r\n    echo \"      &lt;fibonacci index='\" . $index . \"'>\" . $low . \"&lt;\/fibonacci>\\n\";\r\n    $oldhigh = $high;\r\n    $high = $high + $low;\r\n\t$low = $oldhigh;\r\n  }\r\n  \r\n}\r\n\r\nfunction fault($message)\r\n{\r\n\r\n  echo \"&lt;SOAP-ENV:Envelope\r\n xmlns:SOAP-ENV='http:\/\/schemas.xmlsoap.org\/soap\/envelope\/'>\r\n  &lt;SOAP-ENV:Body>\r\n    &lt;SOAP-ENV:Fault>\r\n      &lt;faultcode>SOAP-ENV:Client&lt;\/faultcode>\r\n      &lt;faultstring>\" . $message .\r\n      \"&lt;\/faultstring>\r\n    &lt;\/SOAP-ENV:Fault>\r\n  &lt;\/SOAP-ENV:Body>\r\n&lt;\/SOAP-ENV:Envelope>\";\r\n  \r\n}<\/code><\/pre>\n<p>Again, modulo a little error handling and adjustment of the MIME types, this is all we need. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Processing XML with Java, I used an example of plain text, XML-RPC, and SOAP clients that communicate with a Fibonacci number server I run here on www.elharo.com. Originally I wrote the servers in Java using the Java Servlet API. However, problems with Tomcat meant that the server went down every few months. When I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[410],"class_list":["post-1000271","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-flash"],"_links":{"self":[{"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/posts\/1000271","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/comments?post=1000271"}],"version-history":[{"count":0,"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/posts\/1000271\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/media?parent=1000271"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/categories?post=1000271"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.elharo.com\/blog\/wp-json\/wp\/v2\/tags?post=1000271"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}