5 Replies Latest reply on Jan 7, 2008 2:51 PM by jmorgan

    PHP Client

    timonvdm

      Hi,

      Is there a simple way to connect to JBoss with a PHP client? I want to connect
      a php web-application to other (php web-)applications by sending requests
      and receiving information. I have not found any example/question/client that
      matches my criteria.

      Thanx in forward

      Timon

        • 1. Re: PHP Client
          jmorgan


          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

            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

              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

                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 method

                 public 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 method
                 public 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

                  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;
                   }