Web Services - CapitalMIDlet

This section provides the source code for the CapitalMIDlet. For the complete Eclipse project ZIP file, see Forum Nokia.

The example includes the following classes:

CapitalMIDlet

package example.capitals;

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import example.capitals.ui.*;

/**
 * Main MIDlet class. This class takes care of handling the Display
 * and listen for the result of WebServices requests
 */
public class CapitalMIDlet extends MIDlet implements PosterListener {

    // screen which is displayed at the moment
	private Screen currentScreen;
	// location of the web service
	private String endPoint;
	
	protected void startApp() throws MIDletStateChangeException {
		endPoint = getAppProperty("endPoint");
		// create a new WelcomeScreen and set it active
		changeScreen(new WelcomeScreen(this));		
	}
	
	protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
	}

	protected void pauseApp() {
	}

	/**
	 * Change the currently active screen
	 */	
	void changeScreen(Screen screen) {		
		currentScreen = screen;
		screen.makeActive();
	}
	
	/**
	 * Called to force termination of MIDlet
     */
	public void quit()
	{    	
		notifyDestroyed();
	}
    
	/**
	 * This method calls the web service
	 */
	public void requestCapital(String country) {
		changeScreen(new WaitingScreen(this));
		Poster poster = new Poster(this, endPoint);
		poster.requestCapital(country);
	}
    
	public void showMainScreen() {
		changeScreen(new MainScreen(this));
	}

	/**
	 * Called when a valid result is retrieved from the
	 * WebService
	 */
	public void onCapitalRequestComplete(String nation, String capital){
		changeScreen(new ResultScreen(this, nation, capital)); 
	}

	/**
	 * Called when an error happens during the WebService call
	 */
	public void onCapitalRequestError(String code){
		changeScreen(new ErrorScreen(this, code));
	}
	
}

CapitalBinding_stub

/* This file was created by Nokia Developer's Suite for J2ME(TM) */
/* Do not modify this file.                                      */

package example.capitals;

import java.util.Hashtable;
import java.util.Enumeration;

import javax.xml.rpc.Stub;
import javax.xml.rpc.JAXRPCException;
import javax.xml.namespace.QName;
import java.rmi.RemoteException;

import javax.microedition.xml.rpc.Operation;
import javax.microedition.xml.rpc.Type;
import javax.microedition.xml.rpc.ComplexType;
import javax.microedition.xml.rpc.Element;

public class CapitalBinding_Stub implements CapitalPortType, javax.xml.rpc.Stub
{
    public CapitalBinding_Stub()
    {
        properties = new Hashtable();
        properties.put(ENDPOINT_ADDRESS_PROPERTY,new String("http://194.137.80.38:80/CapitalService/Capitals").trim());
    }

    /**
     * Sets the name and value of a configuration property for this Stub
     * instance.
     */
    public void _setProperty(String name, Object value)
    {
	properties.put(name,value);
    }

    /**
     * Gets the value of a specific configuration property.
     */
    public Object _getProperty(String value)
    {
        if (ENDPOINT_ADDRESS_PROPERTY.equals(value) ||
            USERNAME_PROPERTY.equals(value) ||
            PASSWORD_PROPERTY.equals(value))
        {
            return null;
        }

        if (SESSION_MAINTAIN_PROPERTY.equals(value))
        {
            return new Boolean(false);
        }

        if (properties.containsKey(value))
        {
            return properties.get(value);
        }

        throw new JAXRPCException("Unknown property: "+value);
    }

    protected void prepareOperation(Operation oper)
    {
        Enumeration names = properties.keys();
        Object key, val = null;

        if (names == null) return;

        while(names.hasMoreElements())
        {
            key = names.nextElement();
            val = properties.get(key);

            if (key instanceof String && val != null)
            {
                oper.setProperty((String)key,val.toString());
            }
        }
    }

    // Implement methods from generated interface
   public String getCapital(String aNation) throws java.rmi.RemoteException
    {

  
        Object inputObject = aNation;
     
        Operation oper = Operation.newInstance(wsdl_name_getCapital,oper_Request,oper_Response);
    
	prepareOperation(oper);
	oper.setProperty(Operation.SOAPACTION_URI_PROPERTY, "");

	Object outputObject = null;

	try
        {
            outputObject = oper.invoke(inputObject);
        }
        catch(JAXRPCException ex)
        {
            // Get the linked cause
            Throwable cause = ex.getLinkedCause();
            if (cause instanceof RemoteException)
            {
                throw (RemoteException)cause;
            }

            throw ex;
        }

        
        return (String)outputObject;
      
    }


    /** Hashtable containing stubs properties */
    private Hashtable properties;

  
    protected static final QName qname_Request = new QName("urn:nokia:example:capitals:2005-01","request");
    protected static final QName qname_Response = new QName("urn:nokia:example:capitals:2005-01","response");
    protected static final QName wsdl_name_getCapital = new QName("urn:nokia:example:capitals:2005-01","getCapital");

    protected static final Element oper_Request;
    protected static final Element oper_Response;

    static
    {
        oper_Request = new Element(qname_Request,Type.STRING);
    
        oper_Response = new Element(qname_Response,Type.STRING);
    
    }

}

CapitalPortType

/* This file was created by Nokia Developer's Suite for J2ME(TM) */
/* Do not modify this file.                                      */

package example.capitals;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface CapitalPortType extends java.rmi.Remote
{
   public String getCapital(String aNation) throws java.rmi.RemoteException;
}

Poster

package example.capitals;

import javax.xml.rpc.Stub;
import java.rmi.RemoteException;

/**
 * The Poster class does the call to the remote web service
 * It creates the stub and fill the parameters
 * The call is done in a separate thread and the results
 * are delivered asynchronoulsy via PosterListener
 */
public class Poster implements Runnable {
	// true if IO thread is running, false if not
	private boolean isThreadRunning = false;
	// The listener
	private PosterListener listener;	
	private String nation;
	private String endPoint;
	
    public Poster(PosterListener _listener, String _endPoint) {
		if (_listener == null) {
			throw new IllegalArgumentException("Listener cannot be null");
		}
		endPoint = _endPoint;
		listener = _listener;
	}	

	/**
	 * Start the WebService call in a separate thread.
	 * It checks that only one call is active at the same time
	 */
	public synchronized void requestCapital(String _country) {
		if (!isThreadRunning) {
			isThreadRunning = true;
			this.nation = _country;
			new Thread(this).start();
		}		
	}

	/**
	 * This is an IO operation and thus is executed in a
	 * separate thread
	 */
	public void run() {
		CapitalBinding_Stub capitalServiceStub = new CapitalBinding_Stub();
		capitalServiceStub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, endPoint);
		
		CapitalPortType capitalService = (CapitalPortType)capitalServiceStub;
		try {			
			String capital = capitalService.getCapital(nation);
			listener.onCapitalRequestComplete(nation, capital);
		} catch (RemoteException e) {
			listener.onCapitalRequestError(e.getMessage());
		}
	}
	
}

PosterListener

package example.capitals;

/**
 * Implementors of this interface can request to be informed
 * of the results of the Web Service remote call asynchronously
 */
public interface PosterListener {

	/**
	 * Called as a result of a succesful call containing the nation
	 * and the resulting capital
	 */
	public void onCapitalRequestComplete(String nation, String capital);

	/**
	 * Called as a result of an error while calling the WebService
	 */
	public void onCapitalRequestError(String code);
}

MainScreen

package example.capitals.ui;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import example.capitals.CapitalMIDlet;

/**
 * Main Screen. From this you can select the country and request
 * the WebService to be called using the country as input
 */
public class MainScreen extends Screen {
	private Command exitCommand, callCommand;
	private TextField textField;

	public MainScreen(CapitalMIDlet _midlet) {
		super(_midlet);

		// create form
		textField = new TextField("Country", "", 20, TextField.ANY);
		Form f = new Form("Capital Service");
		f.append(textField);
		displayable = f;
	
		// create command buttons
		exitCommand = new Command("Exit", Command.EXIT, 0);
		displayable.addCommand(exitCommand);
		callCommand = new Command("Retrieve Capital", Command.OK, 0);
		displayable.addCommand(callCommand);		

		// set command listener
		displayable.setCommandListener(this);
		System.out.println("Done");
	
	}

	public void commandAction(Command c, Displayable d) {
		if (c == exitCommand) {
			midlet.quit();
		} else if (c == callCommand) {
			if (textField.getString().length() > 0) {
				// request the midlet to retrive the capital
				midlet.requestCapital(textField.getString());
			}
		}
	}

}

ResultScreen

package example.capitals.ui;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import example.capitals.CapitalMIDlet;

/**
 * This class presents the results of the remote call to the user
 */
public class ResultScreen extends Screen {
	private Command exitCommand, backCommand;

	public ResultScreen(CapitalMIDlet _midlet, String nation, String capital) {
		super(_midlet);

		// create the results form
		Form f = new Form("Result");
		f.append(new StringItem("Nation", nation));
		f.append(new StringItem("Capital", capital));
		displayable = f;

		// add commands
		exitCommand = new Command("Exit", Command.EXIT, 0);
		backCommand = new Command("Back", Command.BACK, 0);
		displayable.addCommand(exitCommand);
		displayable.addCommand(backCommand);

		displayable.setCommandListener(this);
	}

	public void commandAction(Command c, Displayable d) {
		if (c == exitCommand) {
			midlet.quit();
        } else if (c == backCommand) {
        	// Go back
        	midlet.showMainScreen();
        }
    }
}

Screen

package example.capitals.ui;

import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Display;


import example.capitals.CapitalMIDlet;

/**
 * Abstract Screen class. It provides a common interface
 * for all the classes making up the user interface
 */
public abstract class Screen implements CommandListener {

	protected CapitalMIDlet midlet;	
	protected Displayable displayable;

	public Screen(CapitalMIDlet _midlet) {
		midlet = _midlet;
	}
	
	/**
	 * Makes the current screen active
	 */
	public void makeActive() {
		try {
			Display d = Display.getDisplay(midlet);
			
			// this prevents from bringing application to foreground
			// in case is application is in background and the current 
			// displayable is the same as the one made active
			if(d.getCurrent() != displayable) {		
				d.setCurrent(displayable);
			}			
		} catch (NullPointerException e) {
			throw new RuntimeException("Screen.midlet == null");
		}
	}

}

WaitingScreen

package example.capitals.ui;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Gauge;
import java.util.Timer;
import java.util.TimerTask;

import example.capitals.CapitalMIDlet;

/**
 * Simple screen showing the progress of the connection
 * to the remote WebService
 */
public class WaitingScreen extends Screen {
	private Gauge progressGauge;
	private Command exitCommand;

	public WaitingScreen(CapitalMIDlet _midlet) {
		super(_midlet);

		// create displayable
		Form f = new Form("Calling Web Service");
		progressGauge = new Gauge("", false, 10, 0);
		f.append(progressGauge);
		displayable = f;

		// create the timer
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			public void run() {
				if (progressGauge.getValue() == progressGauge.getMaxValue()) {
					progressGauge.setValue(0);
				} else {
					progressGauge.setValue(progressGauge.getValue()+1);
				}
			}
        }, 0, 1000);

		// add commands to the text box
		exitCommand = new Command("Exit", Command.EXIT, 0);
		displayable.addCommand(exitCommand);

		// set command listener
		displayable.setCommandListener(this);
	}

	public void commandAction(Command arg0, Displayable arg1) {
		midlet.quit();
	}	

}

WelcomeScreen

package example.capitals.ui;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;

import example.capitals.CapitalMIDlet;

/**
 * Initial screen. It gives some basic information
 * about the application
 */
public class WelcomeScreen extends Screen {

	private Command okCommand;
	private Command exitCommand;
	
	public WelcomeScreen(CapitalMIDlet _midlet) {
		super(_midlet);
	
		String name = midlet.getAppProperty("MIDlet-Name");		
		String version = midlet.getAppProperty("MIDlet-Version");
        Form f = new Form("Capital Service");
		f.append(name);
		f.append(version);
        displayable = f;

		// create command buttons
		okCommand = new Command("OK", Command.OK, 0);
		exitCommand = new Command("Exit", Command.EXIT, 0);

		// add commands to the text box
		displayable.addCommand(okCommand);
		displayable.addCommand(exitCommand);

		// set command listener
		displayable.setCommandListener(this);
	}

	public void commandAction(Command c, Displayable d) {
		if (c == okCommand) {
			// change to Main Screen
			midlet.showMainScreen();
		} else if (c == exitCommand) {
			// initiate exit
			midlet.quit();
		}
	}

}

ErrorScreen

package example.capitals.ui;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import example.capitals.CapitalMIDlet;

/**
 * Simple class to display an error screen
 */
public class ErrorScreen extends Screen {
	private Command exitCommand, backCommand;

	public ErrorScreen(CapitalMIDlet _midlet, String errorString) {
		super(_midlet);

		// create displayable
		Form f = new Form("Error");
		f.append(new StringItem("Value", errorString));
		displayable = f;

		// add commands
		exitCommand = new Command("Exit", Command.EXIT, 0);
		backCommand = new Command("Back", Command.BACK, 0);
		displayable.addCommand(exitCommand);
		displayable.addCommand(backCommand);

		// set command listener		
		displayable.setCommandListener(this);
	}

	public void commandAction(Command c, Displayable d) {
		if (c == exitCommand) {
			midlet.quit();
		} else if (c == backCommand) {
			// Go back
			midlet.showMainScreen();
		}
	}

}