-
1. Re: PHP Client
jmorgan Jan 5, 2008 1:50 PM (in response to timonvdm)
I was thinking about this recently and found that I had a few options depending on how intricate I wanted my architecture. Here's what I was thinking though this most likely isn't all of the options nor the best.
Option 1:
Deploy a web service on the ESB (using JBossWS and AS) -- see webservice_producer quickstart.
Deploy a web service using PHP.
Communicate between the 2 web services.
Option 2:
Implement a SQL/File listener that the PHP communicates to the ESB through -- hello_world_file_action / hello_world_sql_action quickstarts
Deploy a web service using PHP that the ESB can communicate through
Option 3:
Consider using PHPMQ + MantaRay for JMS communication. Not sure how this would work -- I only know it exists.
Option 4 (dirty nasty one):
Implement a scheduled service that polls the PHP application for updates using a PHP web service or other means.
Hope this helps! -
2. Re: PHP Client
jmorgan Jan 6, 2008 11:33 PM (in response to timonvdm)I just whipped up a modified webservice_producer quickstart and some php services that does this. I can share the code if you are interested.
-
3. Re: PHP Client
timonvdm Jan 7, 2008 3:35 AM (in response to timonvdm)Thanx for your reply!
The first three options sound like the best options, although the webservices sound like the best of those three. If you could send me your code i would be very gratefull! You can send it to my mailaddress or just post it in this topic... -
4. Re: PHP Client
jmorgan Jan 7, 2008 12:00 PM (in response to timonvdm)Here's the first PHP application. This is the entry point of the example:
<?php if (isset($_GET['submit_order'])) { $order_number = intval($_GET['order_number']); $total = doubleval($_GET['total']); $ch = curl_init(); //Calling the web service non-directly, through ESB //Just sending the SOAP request manually because I'm lazy curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_URL, "localhost"); curl_setopt($ch, CURLOPT_PORT, 8765); $content = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:good="http://phpwebservice_producer/orderplaced"> <soapenv:Header/> <soapenv:Body> <good:orderPlaced> <order_number>'.$order_number.'</order_number> <total>'.$total.'</total> </good:orderPlaced> </soapenv:Body> </soapenv:Envelope> '; curl_setopt($ch, CURLOPT_POSTFIELDS, $content); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_FAILONERROR, 0); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_HTTP_VERSION, 1); $response = curl_exec($ch); curl_close($ch); } ?> <html> <head> <title>Send Order</title> </head> <body> <form method="GET"> <table> <tr> <td><label for="order_number">Order Number:</label></td> <td><input type="text" value="<?=$order_number?>" name="order_number" /></td> </tr> <tr> <td><label for="order_number">Total</label></td> <td><input type="text" value="<?=$total?>" name="total" /></td> </tr> <tr> <td colspan="2" align="right"><input type="submit" name="submit_order"></td> </tr> </table> </form> <?if(isset($_GET['submit_order'])) { ?> Response: <pre><?=htmlspecialchars($response)?></pre> <? } ?> </body> </html>
Here's the jboss-esb.xml which defines 2 services, one exposing the WS Endpoint and the other used to call the PHP WS<?xml version = "1.0" encoding = "UTF-8"?> <jbossesb xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd" parameterReloadSecs="5"> <providers> <jms-provider name="JBossMQ" connection-factory="ConnectionFactory" jndi-context-factory="org.jnp.interfaces.NamingContextFactory" jndi-URL="localhost"> <jms-bus busid="shippingChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/needs_shipping_channel_esb" /> </jms-bus> <jms-bus busid="quickstartGwChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_webservice_producer_gw"/> </jms-bus> <jms-bus busid="quickstartEsbChannel"> <jms-message-filter dest-type="QUEUE" dest-name="queue/quickstart_webservice_producer_esb"/> </jms-bus> </jms-provider> <jbr-provider name="JBR-Http" protocol="http" host="localhost"> <jbr-bus busid="Http-1" port="8765" /> </jbr-provider> <jbr-provider name="JBR-Socket" protocol="socket" host="localhost"> <jbr-bus busid="Socket-1" port="8888" /> </jbr-provider> </providers> <services> <service category="MyShippingCategory" name="NeedsShippingService" description="ESB to Shiping WS"> <listeners> <jms-listener name="JMS-ESBListener" busidref="shippingChannel" maxThreads="1" /> </listeners> <actions> <action name="request-mapper" class="org.jboss.soa.esb.samples.quickstart.webserviceproducer.MyRequestAction"> </action> <action name="soapui-client-action" class="org.jboss.soa.esb.actions.soap.SOAPClient"> <property name="wsdl" value="http://127.0.0.1/~jmorgan/ws/shippingWS.php?wsdl" /> <property name="operation" value="needsShipping" /> <property name="responseAsOgnlMap" value="true" /> <property name="SOAPAction" value="needsShipping" /> </action> <action name="response-mapper" class="org.jboss.soa.esb.samples.quickstart.webserviceproducer.MyResponseAction"> </action> </actions> </service> <service category="MyServiceCategory" name="MyWSProducerService" description="WS Frontend speaks natively to the ESB"> <listeners> <jms-listener name="JMS-Gateway" busidref="quickstartGwChannel" is-gateway="true" maxThreads="1"/> <jbr-listener name="Http-Gateway" busidref="Http-1" is-gateway="true" maxThreads="1"/> <jbr-listener name="Socket-Gateway" busidref="Socket-1" is-gateway="true" maxThreads="1"/> <jms-listener name="JMS-ESBListener" busidref="quickstartEsbChannel" maxThreads="1"/> </listeners> <actions> <action name="print-before" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="message" value="[Quickstart_webservice_producer] BEFORE invoking jbossws endpoint"/> </action> <action name="JBossWSAdapter" class="org.jboss.soa.esb.actions.soap.SOAPProcessor"> <property name="jbossws-endpoint" value="OrderPlacedWS"/> </action> <action name="print-after" class="org.jboss.soa.esb.actions.SystemPrintln"> <property name="message" value="[Quickstart_webservice_producer] AFTER invoking jbossws endpoint"/> </action> </actions> </service> </services> </jbossesb>
The WS that is being exposed through the ESB:package org.jboss.soa.esb.samples.quickstart.webserviceproducer.webservice; import java.util.HashMap; import java.util.UUID; import java.net.URI; import javax.jws.WebService; import javax.jws.WebMethod; import javax.jws.Oneway; import javax.jws.WebParam; import javax.jws.soap.SOAPBinding; import org.jboss.soa.esb.message.format.MessageFactory; import org.jboss.soa.esb.message.Message; import org.jboss.soa.esb.message.Body; import org.jboss.soa.esb.actions.ActionUtils; import org.jboss.soa.esb.actions.soap.SOAPProcessor; import org.jboss.soa.esb.addressing.Call; import org.jboss.soa.esb.client.ServiceInvoker; /** * @author */ @WebService(name = "OrderPlacedWS", targetNamespace="http://phpwebservice_producer/orderplaced") // @SOAPBinding(style = SOAPBinding.Style.RPC) public class OrderPlacedWS { @WebMethod public String orderPlaced(@WebParam(name="order_number") int order_number, @WebParam(name="total") double total) { Message esbMessage = SOAPProcessor.getMessage(); if(esbMessage != null) { System.out.println("**** SOAPRequest perhaps mediated by ESB:\n" + esbMessage.getBody().get()); } HashMap requestMap = new HashMap(); requestMap.put("order_number", new Integer(order_number)); requestMap.put("total", new Double(total)); try { System.out.println(requestMap); ServiceInvoker si = new ServiceInvoker("MyShippingCategory","NeedsShippingService"); Message message = MessageFactory.getInstance().getMessage(); Call call = new Call(); call.setMessageID(new URI(UUID.randomUUID().toString())); message.getHeader().setCall(call); message.getBody().add(requestMap); esbMessage = si.deliverSync(message, 6000); } catch (Exception e) { //Ignoring exceptions, bad me System.out.println(e); } HashMap response = (HashMap)esbMessage.getBody().get(); return response.toString(); } }
The RequestMapper methodpublic Message process(Message message) throws Exception { logHeader(); HashMap requestMap = (HashMap) message.getBody().get(); // The "paramsLocation" property was set in jboss-esb.xml to // "helloworld-request-parameters" message.getBody().add(requestMap); System.out.println("Request map is: " + requestMap.toString()); logFooter(); return message; }
ResponseMapper methodpublic Message process(Message message) throws Exception { logHeader(); // The "responseLocation" property was set in jboss-esb.xml to // "helloworld-response" Map responseMsg = (Map) message.getBody().get(Body.DEFAULT_LOCATION); System.out.println("Response Map is: " + responseMsg); logFooter(); return message; }
We of course need the queues for the 2nd service as well as the reply queue, so in jbm-queue-service.xml et al. :<mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.esb.quickstart.destination:service=Queue,name=needs_shipping_channel_esb" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean> <mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.esb.quickstart.destination:service=Queue,name=needs_shipping_channel_esb_reply" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean>
And finally the PHP WS that the 2nd service calls:<?php // Pull in the NuSOAP code require_once('lib/nusoap.php'); // Create the server instance $server = new soap_server; $server->configureWSDL('shippingwsdl', 'urn:shippingwsdl'); // Register the method to expose $server->register( 'needsShipping', array('order_number' => 'xsd:string'), array('received'=>'xsd:boolean'), 'uri:needsShipping', 'uri:needsShipping', 'rpc', 'encoded' ); // Define the method as a PHP function function needsShipping($orderNumber) { return array(new soapval('received', 'xsd:boolean', true)); } // Use the request to (try to) invoke the service $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ''; $server->service($HTTP_RAW_POST_DATA); ?>
If anyone sees a better way of doing what I've done here please provide feedback. I kind of whipped it up as a proof of concept so some of the items could probably be done better.
Also, I chose to invoke the 2nd service using deliverSync so I could return the PHP WS return values to the original PHP, but could just have easily done it asyc.
Here's the versions of the various libs I used:
JBossAS: 4.2.1GA
JBossESB: jbossesb-server-4.2.1.GA (binary)
JBossWS: jbossws-native-2.0.0.GA
JBoss Messaging: 1.4.0 SP3
JBoss Remoting: 2.2.2.SP4 (Bluto)
I also tried using the CP branch because of some additional fixes there I wanted and found that I had to update JBossWS to jbossws-native-2.0.1.GA. -
5. Re: PHP Client
jmorgan Jan 7, 2008 2:51 PM (in response to timonvdm)Oops, forgot to set the proper request parameters on the 2nd service.
RequetsMapper method should be:public Message process(Message message) throws Exception { logHeader(); HashMap requestMap = (HashMap) message.getBody().get(); requestMap.put("needsShipping.order_number", requestMap.get("order_number")); requestMap.remove("order_number"); requestMap.remove("total"); // The "paramsLocation" property was set in jboss-esb.xml to // "helloworld-request-parameters" message.getBody().add(requestMap); System.out.println("Request map is: " + requestMap.toString()); logFooter(); return message; }