jueves, 20 de agosto de 2009

Integrando PHP5 y J2ME por medio de Web Services

Es algo difícil encontrar buena documentación sobre como crear una aplicación para móviles usando J2ME.
Por lo general todas asumen que ya tienes tu web service funcionando y listo para usarse, pero hay un problema, el soporte en dispositivos móviles que implementan la JSR-172 es limitado por lo que aunque tengas un archivo WSDL bien definido puedes toparte con que no es posible crear el cliente por que el WSDL tiene elementos no soportados.

Después de un rato de buscar encontré este sitio que tiene una documentación algo obsoleta pero me mostró dos herramientas claves NuSOAP para PHP y kSOAP para J2ME, además este otro sitio del que solo entiendo el código de ejemplo :-D

Manos a la obra:

Primero creamos nuestro web service en PHP para tal fin usaré la librería NuSOAP la versión 0.7.3.

La forma más simple de instalar NuSOAP es descargando el archivo comprimido desde el sitio del proyecto y extraerlo en la carpeta publica de nuestro sitio de pruebas, en mi caso quedó de la siguiente forma:

/var/www/ws/
|_nusoap-0.7.3
|_lib
| |_ nusoap.php y otros archivos
|_samples
| |_ varios ejemplos de como usar NuSOAP

creamos el archivo server.php con el siguiente contenido:


<?php
// include NuSOAP library
require_once('nusoap-0.7.3/lib/nusoap.php');

// Create Web Service Server
$server = new soap_server;

$server->configureWSDL('hello', 'urn:hello');
// Register Services
// (Add) $server->register('add');
$server->register('add', // method name
array('num1' => 'xsd:string', 'num2' => 'xsd:string'),// input parameters
array('result' => 'xsd:string'), // output parameters
'urn:hello', // namespace
'urn:hello#add', // soapaction
'document', // style
'literal', // use
'Add num1 and num2' // documentation
);

// (Substract)
$server->register('substract', // method name
array('num1' => 'xsd:string', 'num2' => 'xsd:string'),// input parameters
array('result' => 'xsd:string'), // output parameters
'urn:aritmatikawsdl', // namespace
'urn:aritmatikawsdl#substract', // soapaction
'rpc', // style
'encoded', // use
'Substract num1 and num2' // documentation
);

// (Hello) $server->register('hello');
$server->register('hello', //method name
array('name' => 'xsd:string'), // input parameters
array('return' => 'xsd:string'), // output parameters
'urn:hello', // namespace
'urn:hello#hello', // soapaction
'rpc', // style
'encoded', // use
'Says hello to the caller' // documentation
);

// Define functions
function hello ($name){
return "Hello $name";
}

function add ($num1, $num2){
return $num1 + $num2;
}

function substract ($num1, $num2) {
return $num1 - $num2;
}

$server->service($HTTP_RAW_POST_DATA);
?>

Para el cliente J2ME necesitamos la librería kSOAP2 2.1.2 (http://sourceforge.net/projects/ksoap2/), que pesa aproximadamente unos 41 KiB, la descargamos y la incluimos en el proyecto.

Creamos un MIDLet llamado NuSOAPClient con el siguiente contenido:

package midlet;


import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.TextBox;
import javax.microedition.midlet.MIDlet;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransport;
import org.xmlpull.v1.XmlPullParserException;
/**
* @author eivar
*/
public class NuSOAPClient extends MIDlet {
private Display display;
//private String url = "http://0.0.0.1/ws/service.php";
private String url = "http://localhost:80/ws/service.php";
private TextBox textbox = null;

public NuSOAPClient() {
display = Display.getDisplay(this);
}

public void startApp() {
try {
testWebService();
} catch (Exception ex) {
System.out.println(ex);
}
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}

public void testWebService() throws Exception {
StringBuffer stringBuffer = new StringBuffer();
TextBox textBox = null;

// add service call
String method = "add";
SoapObject client = new SoapObject(url, method);
client.addProperty("num1", "5");
client.addProperty("num2", "5");
HttpTransport transport = new HttpTransport(url);

// creating the Soap Envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = client;

// call the WebService
try {
transport.call(method, envelope);
} catch(XmlPullParserException io) {
System.err.println(io);
}

// format the Result
String result = envelope.getResponse().toString();
stringBuffer.append(result);

// display results in textbox
textBox = new TextBox("call to add(5, 5) returns ", stringBuffer.toString(), 1024, 0);
display.setCurrent(textBox);
}
}

Ahora solo nos queda ejecutar la aplicación y ver los resultados.
Para desarrollar este proyecto se usó NetBeans 6.5 y Java Wireless Toolkit 2.5.2.

Les dejo algunas capturas de pantalla: