Creating a J2ME Web Service Client

This last week I was concentrated in developing a J2ME application that communicates with a Web Service to gather some information about route planning. Basically, the mobile app ask for a route, given an origin and a destination waypoints. Although this kind of work looks very easy, I got some problems to accomplish it. Due to that, I will share here my experiences to save you some time and if you have a different solution for creating J2ME web service clients, please let me know.

First of all, you will need the following softwares:

  • NetBeans IDE: instead of my fanatism for Eclipse IDE, I used NetBeans due to its facilities in creating web services.
  • Sun Java Wireless Toolkit: java toolkit for creating mobile applications.
  • Apache Tomcat: my target Web Server. Remember to download the .zip version.

The first step is creating the Web Service. So, inside NetBeans IDE, I will configure my tomcat installation under Tools->Servers menu option. (I’m using the pt_BR version of netbeans, so the menus may be a little different). Next, I choose Add Server and type the tomcat’s path location in my local machine. (Neatbeans comes with a native Web Server called GlassFish. If you are not aware with web server now, use this configuration as default).

Later, I have to create my web application project. So, under File->New Project menu, I choose Java Web category and Web Application project type. Click on “next” until your configuration has finished. Now, it’s time to create you source. I will show here a similar implementation of my route server.

Here I show the Waypoint class.


package entities;

public class Waypoint {

    private double lat;

    private double lng;

    public Waypoint(double lat, double lng) {
        this.lat = lat;
        this.lng = lng;
    }

    public Waypoint() {
    }

    public double getLat() {
        return lat;
    }

    public void setLat(double lat) {
        this.lat = lat;
    }

    public double getLng() {
        return lng;
    }

    public void setLng(double lng) {
        this.lng = lng;
    }

}

Here I show the Route class.


package entities;

public class Route {

    private Waypoint[]  waypoints;

    public Route(Waypoint[] waypoints) {
        this.waypoints = waypoints;
    }

    public Route() {
    }

    public Waypoint[] getWaypoints() {
        return waypoints;
    }

    public void setWaypoints(Waypoint[] waypoints) {
        this.waypoints = waypoints;
    }

}

Notice that I’m using complex object and arrays, which are in the most cases the reason of a lot of problems in deploying Web Services.

Next, I create my Web Service. To do that, right-click on the package folder and choose New->WebService. Here I show the implementation of my Web Service, which just return a route created by the given latitudes and longitudes.


package webservice;

import entities.Route;
import entities.Waypoint;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 *
 * @author Fernando Kakimoto
 */
@WebService()
public class RouteService {

    /**
     * Operação de serviço web
     */
    @WebMethod(operationName = "getRoute")
    public Route getRoute(@WebParam(name = "oLat", partName="oLatPart") double oLat,
            @WebParam(name = "oLng", partName="oLngPart") double oLng,
            @WebParam(name = "dLat", partName="dLatPart") double dLat,
            @WebParam(name = "dLng", partName="dLngPart") double dLng) {

        Waypoint w1 = new Waypoint(oLat, oLng);
        Waypoint w2 = new Waypoint(dLat, dLng);
        Waypoint[] waypoints = new Waypoint[]{w1, w2};

        return new Route(waypoints);
    }
}

After project compilation, the project tree will be similar than the picture below:

project

The Web Service is done. It’s time to create our J2ME client. For that, there are some options. One option is using the netbeans native support for that. After created a J2ME project, inside the New->J2ME Client for Web Applications menu, you are able to select a WSDL file as source and the IDE creates the J2ME client code for you. However, I tried this approach and the generated code came with errors. So, I used the second option: Sun Java Wireless Toolkit.

The WTK offers some utilites under File->Utilities menu. One of them is the Stub Generator, which generates J2ME client code for your WSDL service. So, run your service inside NetBeans or create its respective WSDL file. Next, in the stub generator, type the file path or URL, the code destination and the CLDC version. Here is how my Stub Generator looks like.

stubgenerator

After the code generation, here is the result of my WebClient J2ME project.

projectj2me

To finish, all you have to do is instantiate RouteService_Stub class and invoke getRoute() method. To make things simple, I used just one class which corresponds to the midlet. Here is the midlet code.


package main;

import client.Route;
import client.RouteService;
import client.RouteService_Stub;
import client.Waypoint;
import java.rmi.RemoteException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.*;

/**
 * @author Fernando Kakimoto
 */
public class MainMidlet extends MIDlet implements CommandListener {
    private Command exitCommand = new Command("Exit", Command.EXIT, 1);
    private Form form = new Form("J2ME Web Client");

    public void startApp() {
        try {
            RouteService service = new RouteService_Stub();
            Route r = service.getRoute(1.5, 2.5, 1.8, 2.8);

            Waypoint origin = r.getWaypoints()[0];
            Waypoint detination = r.getWaypoints()[1];

            form.append("origin:" + origin.getLat() + "," + origin.getLng());
            form.append("\n");
            form.append("destination:" + detination.getLat() + "," + detination.getLng());

            form.addCommand(exitCommand);
            form.setCommandListener(this);
            Display.getDisplay(this).setCurrent(form);

        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable d) {
        if(c == exitCommand){
            destroyApp(false);
        }
    }
}

That’s it. Simple and working.
The result you can see running the midlet sample.

phone

See you,


Fernando

19 thoughts on “Creating a J2ME Web Service Client

  1. hi, i tried to add the tomcat server, i was told that i need some kind of catalina home or installation directory and i dont know which one it is , could you tell me which directory is the right one ?

    1. Hi jack,

      catalina home is your tomcat home directory, for example C:\apache-tomcat-6.0.18\
      Sometimes, you need to declare a CATALINA_HOME environment variable in order to start tomcat correctly.

      []’s
      Fernando

  2. hi,
    In my Web Service(public String getBooks(@WebParam(name = “searchText”)
    String searchText))
    i have made a db connection and put the result in a Map. Now how can I get the result(Map) in my midlet(public void callWebService()) class. Please advice me.

    1. Hi Manoj,

      in your nokia SDK there is a utility tool called Stub Generator. This tool generate j2me client classes, based on a wsdl file.

      []’s
      Fernando

      1. Hi,
        Thanks for the reply.
        The Stub generated these files in the application:
        (1)NewWebService.wsclient
        (2)NewWebService.wsdl
        (3)NewWebService.java
        (4)NewWebServiceService_Stub.java

        I had gone through these files but haven’t yet got my resultant Map/Hashtable. I want to print in the Midlet file the result which is being retrieved from the Web Service. The result/output is in the form of a Hashtable in the Web Service method. Can you please help me out?. I am really having a tough time out here. I have to submit my project in the University by tomorrow morning. Pliz help me.

        Thanks again for the reply.

      2. Hi Manoj,

        I’m not sure, but it looks like you have to instantiate NewWebServiceService_Stub class.
        Take a look at its methods and, if your web service method was found, that is the correct class.
        So you will need:

        NewWebServiceService_Stub stub = new NewWebServiceService_Stub();
        stub.methodName(); // I don’t know the return type of your method, but assign it in a local variable.

        Hope it works.

        []’s
        Fernando

      3. This is my method in the Midlet file:

        public void callWebService(){

        clearForm();
        System.out.println(“Search Text: –> “+textField.getString());
        try{
        //Hashtable hashTable=stub.getBooksBySearchKey(textField.getString());
        }
        catch(Exception e)
        {
        System.out.println(“Exception: –> “+e);
        }
        }

        This is the method in the Web Service:

        @WebMethod(operationName = “getBooksBySearchKey”)
        public Hashtable getBooksBySearchKey(@WebParam(name = “serachKey”)
        String serachKey) {
        //TODO write your implementation code here:
        System.out.println(“Search Text in WS: –> “+serachKey);
        Hashtable hashTable = new Hashtable();
        Book book = null;

        Connection conn = null;
        CallableStatement cs;
        ResultSet rs = null;

        try
        {
        Class.forName(“com.mysql.jdbc.Driver”);
        conn = DriverManager.getConnection(“jdbc:mysql://292.258.0.50:3306/assignment”,”webs”,”webs”);
        cs = conn.prepareCall(“{call stp_GetBooks(?)}”);
        cs.setString(“searchKeyword”,serachKey);
        rs = cs.executeQuery();

        while(rs.next())
        {
        book = new Book();
        book.setBookID(rs.getInt(“id”));
        book.setBook_name(rs.getString(“book_name”));
        book.setAuthor_name(rs.getString(“author_name”));
        book.setPublisher_name(rs.getString(“publisher_name”));
        hashTable.put(book.getBookID(), book);
        System.out.println(“Book Name::”+rs.getString(“book_name”));
        }
        }
        catch(Exception e)
        {
        e.printStackTrace();
        }
        System.out.println(“Book Length::”+hashTable.size());
        return hashTable;
        }

        I don’t know why but that’s probably what I have been asking.

        This is what the stub generated:

        public void getBooksBySearchKey(String serachKey) throws java.rmi.RemoteException {
        Object inputObject[] = new Object[] {
        serachKey
        };

        Operation op = Operation.newInstance( _qname_operation_getBooksBySearchKey, _type_getBooksBySearchKey, _type_getBooksBySearchKeyResponse );
        _prepOperation( op );
        op.setProperty( Operation.SOAPACTION_URI_PROPERTY, “” );
        Object resultObj;
        try {
        resultObj = op.invoke( inputObject );
        } catch( JAXRPCException e ) {
        Throwable cause = e.getLinkedCause();
        if( cause instanceof java.rmi.RemoteException ) {
        throw (java.rmi.RemoteException) cause;
        }
        throw e;
        }

        }

        I hope you could see the stub generated method return type is a void which i can not change. Now here lies the problem which I have been seeking help. I don’t know why the stub generated method return type is void. If i put the return type as int in the web service method, the stub generated method could also generate the return type as int and not void, but if i put the return type as Hashtable the return type in the stub generated method turns into void. What should I do now?
        Regards and thanks…

      4. Manoj,

        actually those client code generators, such as Stub Generator, do not support some complex types.
        Maybe, Stub Generator is not able to create a correct client for your method with a Hashtable return type.
        I recommend you try modifying your code to use primitive types or arrays. In my post sample, I used a Route type and it works well.
        Just try different approaches to your method until you find a solution. Putting these stuff to work correctly is a very exhaustive task.

        Good luck.

        []’s
        Fernando

      5. Hi,
        Thank you so much nandokakimoto. Your suggestion helped. I return the xml as String and then parse it in my midlet. It works. Thanks again for being so helpful.

        Regards,
        Manoj

  3. hi, could you show me an example of this working on a simple web service like helloworld or a simple web service that does addition or subtraction. i have done the something similar to the example you put up, the netbeans is building it and it is sayin that it’s successful but i cant see the phone output screen? any help would be really appreciated.

    thanks
    Bobby

  4. hi ,
    please could you show me an example of how to create the j2me web service client on a simple web service like helloworld or a simple addiction or subtraction . my project is due next week monday. I have tried doin something like the example you put up , the thing is building successfully but i am not seeing the result on the mobile screen output .

  5. Hi, I follow the steps and generate all the same stubs,but when i run the project, there is nothing on the emulator screen. Does anyone know how to fix it out?Thx.

  6. Hi, I follow the steps and generate all the same stubs,but when i run the project, there is nothing on the emulator screen. Does anyone know how to fix it out?

    Thanks,
    david

  7. I use Netbean 5.5 and Mobility Pack 5 and follow your steps, but I have an error ‘Communication failed’ .Do you have any idea about this? I have turned off firewall and protection on my computer.
    Thanks,

    David

  8. Thank you so much for the article! I’ve been trailing the internet about consuming web services using J2ME, I usually using .NET so was completely baffled by the wireless tools and the use of the word stub; this article has helped me understanding it all, can’t thank you enough!

    regards

    Kamal

    London

  9. Hello Fernando,

    Thanks for posting the article, which is very helpful for me.

    I am able to run the web service successfully.

    Please provide me the navigation for web service client, which is quite difficulty for me to understand.Please reply me asap.

    Thanks & Regards
    Mahender

  10. hi every body,

    please help me how to work with wtk and please provide me the navigation after generating the WSDL file

    Regards
    Mahender
    London

  11. hi All,
    I am new to j2me. I have created a secure webservice deployed on Glassfish. How can I access it via J2ME webservice client? The authentication is with username and symmetric key.
    What should be changed in generated stub classes?
    could someone direct me with correct steps?
    Thanks in advance.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s