OpenBaseMovil http://www.openbasemovil.org J2ME Framework, J2ME database and more Mon, 10 Nov 2008 10:28:36 +0000 http://wordpress.org/?v=2.6.3 en http://creativecommons.org/licenses/by-nc-nd/3.0/1567055http://www.feedburner.com Seminar on Mobile JavaME and OpenBaseMovil development http://www.openbasemovil.org/2008/11/10/seminar-on-mobile-javame-and-openbasemovil-development/ http://www.openbasemovil.org/2008/11/10/seminar-on-mobile-javame-and-openbasemovil-development/#comments Mon, 10 Nov 2008 10:28:36 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=52 We've been really busy this last months, hiring, planning, rising funds, but we are now ready again to publish our news on OpenBaseMovil development.

We're also starting with a very interesting side of Open Source development: training and "evangelization".

Tomorrow we will start a seminar on JavaME and OpenBaseMovil development at the Computer Science College, Universidad Computense de Madrid (one of the best Universities in Spain).

The seminar has raised great expectation: It will be delivered to 40 students, but over 100 will have to wait until the next session.

We plan to publish also our conclusions, part of the seminar materials, and some photos after the seminar.

]]>
http://www.openbasemovil.org/2008/11/10/seminar-on-mobile-javame-and-openbasemovil-development/feed/
Using the networking library openbasemovil-net (II) http://www.openbasemovil.org/2008/05/24/using-openbasemovil-net-ii/ http://www.openbasemovil.org/2008/05/24/using-openbasemovil-net-ii/#comments Fri, 23 May 2008 23:39:05 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=45 We will now address how to create a servlet to handle RemoteCalls from our device.

The first piece of code is a very generic servlet that takes the binary data, handles it to another class, and sends back the result. That second class is the one that will do the parsing. This way is easier to perform unit testing, for example.

Here is the code for the servlet:

/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
*/
 
public class RPCServlet
    extends HttpServlet
{
    private String infoPage;
 
    public void init( final ServletConfig config )
    {
        infoPage = config.getInitParameter( "informationPage" );
    }
 
    protected void doGet(
            final HttpServletRequest    request,
            final HttpServletResponse response
    )
            throws ServletException,
                   IOException
    {
        request.getRequestDispatcher( infoPage ).forward( request, response );
    }
 
    protected void doPost(
            final HttpServletRequest     request,
            final HttpServletResponse   response
    )
            throws ServletException,
                   IOException
    {
        processRequest( request, response );
    }
 
    private void processRequest(
            final HttpServletRequest request,
            final HttpServletResponse   response
    )
            throws ServletException
    {
        try
        {
            // Read all the data into a byte array
            final BufferedInputStream bis = new BufferedInputStream(
                    request.getInputStream()
            );
            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int c = bis.read();
            while( c != -1 )
            {
                baos.write( c );
                c = bis.read();
            }
            final byte[] data = baos.toByteArray();
 
            // Handle the data to the RPCBroker class
            final byte[] result = RPCBroker.handle( data );
 
            // Return the result to the device
            response.setContentType( "application/octet-stream" );
            response.setContentLength( result.length );
            response.getOutputStream().write( result );
        }
        catch( Exception e )
        {
            throw new ServletException( e );
        }
    }
}
 

Now the RPCBroker has to parse the data and make the actual call. We will not be doing here the call, you can do what suits you better: from a simple if-else structure to calling objects using reflection. If you use reflection, please be careful that you allow calls to the objects you want to be called and not a generic approach, since that could lead to big security problems.

 
/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
*/
public class RPCBroker
{
    private static Log log = LogFactory.getLog( RPCBroker.class );
 
    public static final int RC_SUCCESS              = 0;
    public static final int RC_INVALID_OBJECT       = 1;
    public static final int RC_INVALID_METHOD       = 2;
    public static final int RC_NOT_ALLOWED          = 3;
    public static final int RC_INVALID_ARGUMENTS    = 4;
    public static final int RC_INVOKATION_EXCEPTION = 5;
    public static final int RC_INVALID_CRC          = 6;
 
    public static byte[] handle( final byte[] data )
        throws IOException,
               SerializationException
    {
        if( data == null )
        {
            return sendError( RC_INVALID_CRC, "Null data" );
        }
        try
        {
            final ByteArrayInputStream bais = new ByteArrayInputStream( data );
            final ChecksumedInputStream cis = new ChecksumedInputStream( bais );
            final SerializerInputStream in = new SerializerInputStream( cis );
            final byte      version     = in.readByte();
            final byte      encryption  = in.readByte();
            final String    deviceGuid  = in.readString();
            final long      deviceId    = in.readLong();
            final String    objectName  = in.readString();
            final String    methodName  = in.readString();
            final Object[]  parameters;
            try
            {
                parameters = (Object[]) in.readNullableObject();
            }
            catch( SerializationException e )
            {
                throw new IOException( e.getMessage() );
            }
            final long crc = cis.getCRC();
            final String    endOfData   = in.readString();
            if( endOfData.equals( "END_OF_DATA" ) )
            {
                final long originalCRC = in.readLong();
                if( originalCRC != crc )
                {
                    return sendError( RC_INVALID_CRC, "Invalid CRC" );
                }
                else
                {
                    return invoke(
                            version,
                            deviceGuid,
                            deviceId,
                            objectName,
                            methodName,
                            parameters
                    );
                }
            }
            else
            {
                return sendError( RC_INVALID_ARGUMENTS, "Wrong signature" );
            }
        }
        catch( SerializationException e )
        {
            return sendError( RC_INVALID_CRC, e.getMessage() );
        }
    }
 
    private static byte[] invoke(
            final byte      version,
            final String    deviceGuid,
            final long      deviceId,
            final String    objectName,
            final String    methodName,
            final Object[]  parameters
    )
            throws IOException,
                   SerializationException
    {
        // Here is where you actually look up the object
        // make the call and return the value
 
        Object retval;
        /*
        1. Lookup object
 
        if object is not found: return sendError( RC_INVALID_OBJECT, "error message" );
 
        2. Check security, if applicable
 
        if not allowed to call: return sendError( RC_NOT_ALLOWED, "error message" );
 
        3. Make the call
 
        store the return value in the retval variable.
        if an error raises: return sendError( RC_INVOKATION_EXCEPTION, "error message" );
        */
 
        // You should perform the appropriate try-catch
        // The following code should be placed into a try block,
        // when the call has been successful
       final ByteArrayOutputStream baos = new ByteArrayOutputStream();
       final SerializerOutputStream out = new SerializerOutputStream( baos );
       out.writeInt( RC_SUCCESS );
       out.writeString( "OK" );
       out.writeNullableObject( retval );
       out.flush();
       return baos.toByteArray();
    }
 
    private static byte[] sendError( final int code, final String message )
            throws IOException,
                   SerializationException
    {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final SerializerOutputStream out = new SerializerOutputStream( baos );
        out.writeInt( code );
        out.writeString( message != null ? message : "" );
        out.flush();
        return baos.toByteArray();
    }
}
 

With this second article you should have almost everything you need to perform remote calls.

Please, leave your comments and suggestions.

]]>
http://www.openbasemovil.org/2008/05/24/using-openbasemovil-net-ii/feed/
Using the networking library openbasemovil-net http://www.openbasemovil.org/2008/05/22/using-openbasemovil-net/ http://www.openbasemovil.org/2008/05/22/using-openbasemovil-net/#comments Thu, 22 May 2008 20:28:48 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=44 The Networking library in OpenBaseMovil (openbasemovil-net) provides some very useful networking methods that you can use in your applications.

One of the most useful ones is the RemoteCall class. As you can guess it is a remote call procedure, and it is a binary one. If your target platform supports the remote call or webservice optional APIs, you can use them, but we wanted to provide an approach that could be used on any device (many of the current devices in the market do not support those optional APIs). We also decided to use a binary protocol since it is more compact and more efficient for binary data, instead of XML.

We also wanted to control how the network was reached and do it in a very simple way.

The library contains three main blocks: Net, Binding and RemoteCall.

Net has all the needed constants, and also some networking wide configuration settings. It also has a checkNetwork method that will allow you to check if you have signal and if your remote server is up and running.

The synchronization engine uses the deviceGuid and deviceId settings to perform simple authentication. Those settings are sent from the server to the device when the user successfully authenticates in our system using the company name, user name and password.
You can use them for your own purposes, or you can ignore them, they are not really needed. If not set, they will be sent as an empty string and 0 respectively to the server in the remote call protocol.

The checkNetwork method provides also a small example of RemoteCall usage, as it calls a remote Object called "LoginHandler" to a method called "ping". That checks if our server is up and running. If it can not make the call, it checks if it can read the home page of yahoo (you could put any other well known service). That is used to check if the previous error was due to the server being down or to the lack of network connectivity (we assume yahoo is up :) ).

final RemoteCall rc = new RemoteCall(
    "LoginHandler", // remote object name
    "ping",         // remote object method name
    0               // number of parameters
);
rc.invoke();

The RemoteCall class allows you to set a default url to call, so you can later just call the no argument version of invoke, but you can also provide an url for each call using the other version of invoke.
In the previous example, the Net class assumes that you have previously set the defaultURL property in the RemoteCall class. That should be done at application startup.

The RemoteCall class sends a binary stream to a remote url, using a the POST method through the Binding class. RemoteCall will try to invoke the remote method up to MAX_RETRIES (currently 5) times if there's a network error (not if the server returns an error), providing you with a level of network security (mobile networks can be very error prone).

The protocol is very simple, and it uses the openbasemovil-core serialization tools to send and receive the data, so complex objects can be sent and received (anything that can be serialized through the SerializerOutputStream).
It is already present as a comment in the code, but I will put it here:

Device request:
 
(data:
{byte       version}        // RPC version, currently 2
{byte       encryption}     // Encryption: 0 - none, 1 - Blowfish
{String     deviceGuid}     // Device Globally Unique Identifier
{long       deviceId}       // Device remote id
{String     object}         // Name of object to call
{String     method}         // Object method to call
{byte[]     parameters}     // Parameters serialized using
                            // SerializerOutputStream
                            // writeNullableObject method
)
{String     "END_OF_DATA"}      // Constant text to identify
                                // data boundary
{long       CRC}                // Adler32 CRC code of the data
 
Server response:
 
{int        responseCode}       // Result of the method call
{String     responseMessage}    // Result message
{byte[]     responseData}       // An object serialized using
                                // SerializerOutputStream
                                // writeNullableObject method
 
responseCode can be one of:
 
0 - RC_SUCCESS
Everything went fine
1 - RC_INVALID_OBJECT
The requested object is invalid
2 - RC_INVALID_METHOD
The object has no method with the requested name
3 - RC_NOT_ALLOWED
The caller is not allowed to execute the requested method
4 - RC_INVALID_ARGUMENTS
The arguments passed are invalid
5 - RC_INVOKATION_EXCEPTION
The method produced an exception when invoked
6 - RC_INVALID_CRC
The CRC of the data sent is invalid

So you can code a Servlet (or whatever) in your server, handle the post request, and parse the data sent using the openbasemovil-core SerializerInputStream class. Then is your turn to locate the object, the method, make sure you want the device make that call, make the call, and finally send the response back using the SerializerOutputStream class.
For the response, the responseCode and responseMessage are mandatory, and if the call is successful then the responseData is also mandatory.
responseData will be read by the device using SerializerInputStream.readNullableObject.

Your server side code should check that after the incomming data the END_OF_STREAM string si found and also the CRC code. And you should also perform the CRC checking using the openbasemovil-core Adler32 class, to make sure that everything arrived ok.

A bit more complex example of RemoteCall use, calling a remote object called "MyServer", to a method called "sendImage" which receives three paremeters, a String, a byte array, and a Vector of String objects.

// Somewhere in your code at startup you will set the default URL
RemoteCall.setDefaultURL( "http://myserver/rpc" );
 
// Now we will make the call
/**
 * Send an image to the server.
 * @param name image file name
 * @param data image raw data
 * @param attributes image attributes, a collection of Strings
 */
public Long sendImage(
                 final String name,
                 final byte[] data,
                 final Vector attributes
)
    throws RemoteCallException
{
    final RemoteCall rc = new RemoteCall(
                                   "MyServer",
                                   "sendImage",
                                   3
    );
    rc.setParameter( 0, name );
    rc.setParameter( 1, data );
    rc.setParameter( 2, attributes );
    return (Long) rc.invoke();
}

The RemoteCall method uses the Binding class to actually call the remote server with a POST method.

The Binding class provides an easy and extensible way to abstract you from the real method used to make the call. It also controls all the open bindings, allowing you to close them all at once to make sure that there're no connections open.

Binding is an abstract class that by default uses the provided sublcass HttpBinding. As you can imagine, the HttpBinding class uses the javax.microedition.connection to actually create an http or https connection.

With the Binding framework you could create other Binding subclasses and use other means for connecting to the network. For example, in future versions we will provide a BluetotthBinding and a Java SE Proxy. With them you will be able to connect your phone through bluetooth using the proxy running on a PC. And everything will work exactly the same.

To create a new Binding class and use it you simply need to subclass Binding, implement the needed methods, and then set it as the binding factory with:

// For CLDC 1.0
Binding.setFactory( new BluetoothBinding().getClass() );

or

// For CLDC 1.1
Binding.setFactory( BluetoothBinding.class );

This introduction to the networking part of OpenBaseMovil will be included in the next revisions of the documentation.
We look forward for your comments to enhance and clarify it before it is actually included.

]]>
http://www.openbasemovil.org/2008/05/22/using-openbasemovil-net/feed/
OpenBaseMovil at Open Movil Forum 2nd barcamp http://www.openbasemovil.org/2008/05/21/openbasemovil-at-open-movil-forum-2nd-barcamp/ http://www.openbasemovil.org/2008/05/21/openbasemovil-at-open-movil-forum-2nd-barcamp/#comments Wed, 21 May 2008 13:35:56 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=43 BarCampWe've just returned from the WES, and we will be at another event soon: The second Barcamp at Open Movil Forum. Open Movil Forum is an initiative of Movistar, the Spanish network operator, around open source software and mobility.

We made a quick presentation at the first Barcamp, now we will be showing a more in depth look at our flagship application bmSales, which will be soon released under an Apache or BSD license.

This is a powerful application that has been running on real customers for the last two years, with many functionalities, that illustrates how to get the best of the OpenBaseMovil framework.

If you're in Madrid next May 27th, you can sign up for free and attend the event.

]]>
http://www.openbasemovil.org/2008/05/21/openbasemovil-at-open-movil-forum-2nd-barcamp/feed/
Now at BlackBerry WES http://www.openbasemovil.org/2008/05/13/now-at-blackberry-wes/ http://www.openbasemovil.org/2008/05/13/now-at-blackberry-wes/#comments Tue, 13 May 2008 14:57:47 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=41 Hi folks,

After the initial presentation of the event, I'm currently now waiting for the first session to start, at Salon 7B.

I must say that the event is really well organized, and that I like Florida very much. It's really beautiful!

I'm hosted at the World Center Marriot Hotel, the one that holds the WES.

If you're around here and want to have a talk, just drop me an email narciso a-t elondra d-o-t com. I'll get it right in my BlackBerry :)

See you!

]]>
http://www.openbasemovil.org/2008/05/13/now-at-blackberry-wes/feed/
Elondra at BlackBerry WES Orlando http://www.openbasemovil.org/2008/05/05/elondra-at-blackberry-wes-orlando/ http://www.openbasemovil.org/2008/05/05/elondra-at-blackberry-wes-orlando/#comments Mon, 05 May 2008 21:47:08 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=40 Hi all,

I'm like crazy trying to arrange everything, but I'll be at the BlackBerry WES at Orlando, Florida next week. From May 13th to May 15th.

If you're going to be around there and want to talk with me please, send us an email through the contact form.

Elondra is now becoming a BlackBerry ISV Partner, and we want to improve our support for BlackBerry and also to find companies from all around the worl that want to sell our products, services or technology in their own regions.

The WES is a great place for this since it's the biggest meeting for BlackBerry partners worlwide.

See you at Orlando!

]]>
http://www.openbasemovil.org/2008/05/05/elondra-at-blackberry-wes-orlando/feed/
OpenBaseMovil Datacenter http://www.openbasemovil.org/2008/04/29/openbasemovil-datacenter/ http://www.openbasemovil.org/2008/04/29/openbasemovil-datacenter/#comments Tue, 29 Apr 2008 21:25:49 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=37 No, this is not the datacenter where our servers are hosted (neither our sites nor our bmServer database synchronization servers), but they could :-)

Javier, one of the partners at Elondra, instead of taking a cup of coffee was playing with a photo and came up with this:

Your own datacenter in your phone

It made me laugh a while, so I decided to post it so you could laugh a while too.

He explains that he was trying to illustrate the storage and computing power of phone with OpenBaseMovil.

Do you think he got it?

]]>
http://www.openbasemovil.org/2008/04/29/openbasemovil-datacenter/feed/
Vote for us! http://www.openbasemovil.org/2008/04/29/vote-for-us/ http://www.openbasemovil.org/2008/04/29/vote-for-us/#comments Tue, 29 Apr 2008 21:11:50 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=36 Dear readers and contributors,

We are currently taking part in the Startup 2.0 contest, and through that we have been also mentioned at KillerStartups where you can vote for the best startups.

Please, help us promote OpenBaseMovil voting for us:

KillerStartups

Startup 2.0

Thanks!

]]>
http://www.openbasemovil.org/2008/04/29/vote-for-us/feed/
Quick start for bmScript http://www.openbasemovil.org/2008/04/25/quick-start-for-bmscript/ http://www.openbasemovil.org/2008/04/25/quick-start-for-bmscript/#comments Fri, 25 Apr 2008 11:33:03 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=35 I was writing an email for Richard Hull, explaining some of the basics of bmScript and how to use it, but after writing it, I thought that it was worth posting it instead of just sending the email.

So there it goes.

Introduction

The ant build file for openbasemovil-script creates various jar files for the engine, one of them contains just the runtime to execute compiled scripts, another one contains also the script compiler, and the other two are JavaSE tools to compile and run script files in a standard JavaSE environment. These tools can also be a good example of how to perform the same from a mobile device using JavaME.
Though bmScript is a scripting language, it is really compiled to a binary form for a couple of reasons. First to be able to compile the scripts on application build or a remote server and reduce application size by using the runtime-only jar, but most important to improve execution speed by spending time on interpretation just once.

Class loading

The engine provides the ScriptingClassLoader class, which searches for .bmc (compiled scripts) resources in the classpath under the folder "vm". It also provides access to system defined classes and system or custom NativeClasses.
You can subclass the ScriptingClassLoader in order to provide other ways of finding classes. The compiler and runtime for JavaSE do it to find classes in standard folders, but you can extend it to download them from a remote server, for example.

Integration with non-scripting classes (Java classes)

The NativeClass provides an easy way to create proxy Java classes that can be injected in a ScriptingClassLoader to be able to access any other Java class from a script.
It could have been done a lot easier with reflection, but that is not available with JavaME, so we have to do it in another way.
The NativeClass provides all the "infrastructure" to define methods and properties and to find and check that they are properly invoked, so you can create proxy classes for Java classes easier by subclassing NativeClass.
A good example are the classes found in the bm.vm.sys package under the main src folder of openbasemovil-script: The Map class lets you create Hashtable objects from the script, though you call them "map" in the script.
The Map class declares the methods present in the class in a static block, and then just provides the implementation of the invoke method that is a switch to handle the different methods declared.
Let's suppose that I have a NativeClass called List that will let me access java.util.Vector, and I want my scripts to access it as "list" (check the Map class, that is performed in the constructor).
Now I obviously want to run a script that will access this class, to do that all I have to do is add it to the class loader of a virtual machine (we'll get later to the full process of creating and invoking a vm):

 
    vm.getClassLoader().addNativeClass(
        "list",
        new sample.List( vm )
    );
 

Compiling a script

The bmsc class in the tools folder of openbasemovil-script is a JavaSE command line tool to compile .bms (script files) to .bmc (compiled scripts), very much in the way you do with javac.
The source code shows how to create a custom class loader, how to create a virtual machine and how to invoke the script compiler from Java code.
It is JavaSE 1.5+, but it can be used in a very similar way from JavaME.

Running a script

The bms class in the tools folder is a command line runtime, this time like the java command line tool from the jre. It shows how to create a custom class loader, how to create a virtual machine and how to invoke a script.

Using the example of the List NativeClass above, we could do something like this:
My scripting class (foo.bms):

 
class foo
{
    method int main()
    {
        var list myList;
        set myList = new list();
        mylist.add( "hello world with list!" );
        system.println( mylist.get( 0 ) );
    }
}
 

The java code to invoke the script (once compiled into foo.bmc):

 
    final VirtualMachine vm = new VirtualMachine();
    vm.getClassLoader().addNativeClass(
        "list",
        new sample.List( vm )
    );
    vm.run( "foo" );
 

The run method is a shortcut to the one used in bms that uses no arguments, it will load the scripting class foo, search for a main method and invoke it with no arguments.

If you want to retrieve a return value from a script, the run method or the invoke method in the virtual machine will always return an Instance object.
The Instance object represents (obviously) an instance of an ScriptingClass object.
For native types (boolean, int, etc) they always have a property called "value" that you can retrieve with the get method.

For other types, the real java object might be in an attachment. The Map class does this, it uses an attachment called "map" to hold the real Hashtable object used.

In further articles we will try to get deeper in the possibilities of the language. It obviously can be used from JavaSE, it allows you to compile or just run scripts that are loaded dynamically, and through the NativeClass system it allows you to extend the runtime to access any Java class you want.

Please, feel free to comment your thoughts, and remember that bmScript is still v0.1, it works, but it has still to be thoroughly tested and performance tunned.

]]>
http://www.openbasemovil.org/2008/04/25/quick-start-for-bmscript/feed/
Spanish and German Forums http://www.openbasemovil.org/2008/04/25/spanish-and-german-forums/ http://www.openbasemovil.org/2008/04/25/spanish-and-german-forums/#comments Fri, 25 Apr 2008 10:04:34 +0000 Narciso Cerezo http://www.openbasemovil.org/?p=34 A couple of days ago we created a mirror of the current English forum categories under two new languages: Spanish and German.

Thanks to Stefan Haacker for the German translation and for his collaboration as the moderator of the German part of the forum.

We hope that you use them, don't be afraid by the fact that they have 0 topics... they are brand new!

]]>
http://www.openbasemovil.org/2008/04/25/spanish-and-german-forums/feed/