Docstoc

Session Management in J2ME and PHP

Document Sample
Session Management in J2ME and PHP Powered By Docstoc
					Session management with J2ME and PHP
Skill Level: Introductory John Muchow Author

13 Jan 2004 This tutorial provides an introduction to session management between a J2ME MIDlet and a Web server running PHP.The course discusses how to create and establish connections using HTTP, and also has a short overview of PHP, including how PHP and HTML work together to create dynamic content.

Section 1. Before you start
About this tutorial
This tutorial provides an introduction to session management between a J2ME MIDlet and a Web server running PHP. I begin the tutorial by discussing how to create and establish connections using HTTP. I'll also have a short overview of PHP, including how PHP and HTML work together to create dynamic content. I'll then develop a MIDlet that calculates someone's age based on their birth date. The later half of the tutorial focuses on session management. I'll have a brief discussion of the request-response nature of HTTP, which explains why you need additional tools in order to manage sessions. I wrap up the tutorial by creating a golf score calculator MIDlet that provides a user interface for entering golf scores. On the server side will be a PHP script that will calculate the running total for 18 holes of golf. The MIDlet and PHP script will use cookies to maintain session information. Upon completion of this tutorial, you will have a working knowledge of how to communicate with a server running PHP, including how to create and manage sessions using cookies.

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 1 of 48

developerWorks®

ibm.com/developerWorks

Prerequisites
To run the samples in this tutorial, you'll need the following software tools: • The Java Development Kit (JDK) • The Wireless Toolkit (WTK) • Apache Web server • PHP Scripting Language See Software prerequisites for information on downloading, installing, and configuring these software tools.

Section 2. Software prerequisites
Software installation
You'll work with four software tools throughout this tutorial. Begin by downloading and installing each of the required components. • The Java Development Kit (JDK): The JDK provides the Java source code compiler and a utility to create Java Archive (JAR) files. When working with the Wireless Toolkit 2.0 (as you will be here), you'll need to download JDK version 1.4 or greater. Download JDK version 1.4.2 (http://java.sun.com/j2se/1.4.2/download.html). • The Wireless Toolkit (WTK): The Sun Microsystems Wireless Toolkit integrated development environment (IDE) creates J2ME MIDlets. The WTK download contains an IDE, as well as the libraries required for creating MIDlets. Download J2ME Wireless Toolkit 2.0 (http://java.sun.com/products/j2mewtoolkit). • Apache Web server: Apache is an open source HTTP server. To run the examples as shown in this tutorial, you'll use Apache. Should you already have an installation of an HTTP server that supports PHP, you can skip the sections regarding the installation and configuration of Apache. Download Apache 2.0.x (http://httpd.apache.org/). • PHP Scripting Language: PHP is an open source scripting language

Session management with J2ME and PHP Page 2 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

designed for Web development. Download PHP 4.3.4 (http://www.php.net/downloads.php).

Install the JDK and Wireless Toolkits
The Java Development Kit (JDK) Use the JDK documentation to install the JDK. You can choose either the default directory or specify another directory. If you choose to specify a directory, make a note of where you install the JDK. During the installation process for the Wireless Toolkit, the software attempts to locate the Java Virtual Machine (JVM); if it cannot locate the JVM, you are prompted for the JDK installation path. The Wireless Toolkit (WTK) This tutorial builds on an earlier developerWorks tutorial "MIDlet Development with the Wireless Toolkit" (see Resources), which explains the basics of creating MIDlets with the toolkit. This tutorial is an excellent starting point if you are new to the Wireless Toolkit. The Wireless Toolkit is contained within a single executable file. Run this file to begin the installation process. It is recommended that you use the default installation directory. However, if you do not use the default directory, make sure the path you select does not include any spaces.

Install the Apache Web server
Run the Apache installer and follow the instructions given. When prompted for the Network Domain, enter localhost. For the Server Name, enter 127.0.0.1. When installing a Web server for local development and testing, this IP address always represents your system. Known as a loop-back address, any reference to this IP is "looped-back" to your computer.

Test the Apache Web server
In order to complete the installation of Apache, you must verify that Apache will load a Web page. If you open a Web browser, enter the address http://localhost; Apache will display output similar to that shown here in Figure 1. Figure 1. Apache installation

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 3 of 48

developerWorks®

ibm.com/developerWorks

If Apache was installed using the default paths, you can see the file Apache loaded by searching for a file named index.html.en in the C:\Program Files\Apache Group\Apache2\htdocs directory. This is Apache's default location when searching for HTML files, and is the same location in which you'll place the PHP files as you progress through this tutorial. Also, note the extension of the HTML file, .en. Apache provides several versions of the same test file in various languages, and .en represents the english version. Should you have trouble viewing Web pages with Apache, refer to the Apache online documentation (http://httpd.apache.org/docs/) for help.

Session management with J2ME and PHP Page 4 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Install PHP
PHP does not include an installer program. Instead, open the ZIP file you downloaded and extract all the contents into the C:\php directory. To enable PHP within your Apache Web server, you will need to copy several files into the directory in which you originally installed Apache. Assuming you are running PHP version 4.3.4, locate the following files: • C:\php\php-4.3.4-Win32\php4ts.dll • C:\php\php-4.3.4-Win32\php.ini-recommended • C:\php\php-4.3.4-Win32\sapi\php4apache2.dll Copy each of these files to the C:\Program Files\Apache Group\Apache2 directory . Note: If you have installed different versions of either Apache or PHP you must change the references to the installation paths and files for the configuration steps.

Configure PHP
With the PHP files now available within your Apache installation, there are a few final steps in order for Apache to recognize and process PHP files. 1. 2. 3. Rename the php.ini-recommended file to php.ini. Open the file in a text editor and search for the string doc_root. Update the doc_root value as shown below:

doc_root = C:\Program Files\Apache Group\Apache2\htdocs

4. 5.

Open the Apache configuration file, httpd.conf, in the C:\Program Files\Apache Group\Apache2\conf directory. Move to the bottom of the file and add the following two lines:

LoadModule php4_module php4apache2.dll AddType application/x-httpd-php .php

These two lines tell the Apache server which module to load to process any file that has an extension of .php.

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 5 of 48

developerWorks®

ibm.com/developerWorks

6.

Restart the Apache Web server so the changes to the configuration files will be recognized. To restart, select Start > All Programs > Apache HTTP Server > Control Apache Server > Restart.

You're nearly there; all that remains is to test the PHP installation.

Test PHP
There are several steps to verify that PHP has been installed and configured properly. 1. Verify that Apache can properly locate and load the PHP files by selecting Start > All Programs > Apache HTTP Server > Configure Apache Server > Test Configuration. You should see output similar to Figure 2, which indicates there were no errors locating or loading PHP. If a window quickly opens and closes before you can read the contents, you can assume the configuration process completed successfully.

Figure 2. Apache configuration

2.

Ensure that Apache can properly process and display a PHP file by opening a text editor and entering the following PHP script:

<?php echo 'Looking good....<br>'; echo phpinfo(); ?>

3. 4.

Save the file as sample.php in the C:\Program Files\Apache Group\Apache2\htdocs directory. In a Web browser, enter http://localhost/sample.php. If everything is working, you'll see output similar to what is displayed in Figure 3.

Figure 3. PHP configuration

Session management with J2ME and PHP Page 6 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Note: All PHP files that you'll create during this tutorial will be saved in the C:\Program Files\Apache Group\Apache2\htdocs directory. This location is known as the documentation root, or simply doc root, which refers to the location where Apache looks for files when a request is received from a Web browser.

Section 3. Introduction to HTTP
Overview
Within J2ME/MIDP, the Generic Connection Framework (GCF) was developed to

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 7 of 48

developerWorks®

ibm.com/developerWorks

provide a foundation for support of various types of network and file I/O. Within MIDP 2.0, the only network protocols required to be implemented are HTTP and HTTPS. However, a device manufacturer might choose to offer additional protocols such as datagrams and sockets. Although the discussion of network support can be quite involved, for this tutorial all you need is a basic understanding of how to open a connection, pass client data to a server, and receive and process a server response. In the next few sections I'll cover each of these topics. Note: For additional information regarding network support in MIDP, please see Resources for links to other developerWorks tutorials that provide more comprehensive introductions to working with HTTP.

Creating a connection
Creating an HTTP connection requires only a few lines of code:
String url = "http://www.corej2me.com"; HttpConnection http = null; http = (HttpConnection) Connector.open(url);

Once the connection request has been issued, I package together a client request, which will contain information I want to pass to the server for processing. The client request consists of the following three sections: • Request method • Header • Body In the following sections, I'll describe each of these sections.

Client -- Request method
The request method indicates to the server how data will be sent from the client. The two most common request methods are POST and GET. With GET, all data is sent from the client to the server as part of the URL. POST sends client information using a stream of data. Choosing which type of request method to use typically boils down to how much data you will have to send. When using GET, client data is stored in environment variables on the server; thus, there is a limit to the size of a request. With POST, because data is sent as a stream, there is no limit to how much data

Session management with J2ME and PHP Page 8 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

can be processed. Setting the request method is accomplished through a call to setRequestMethod() as shown here:
String url = "http://www.corej2me.com"; HttpConnection http = null; http = (HttpConnection) Connector.open(url); // Set request method to GET http.setRequestMethod(HttpConnection.GET);

Client - Header information
Header information is a way to pass parameters from a client to a server. Header fields are specified as key-value pairs, using the setRequestProperty() method. For instance, the following example requests that a server only return data that has been modified since December 21st, 2003.
String url = "http://www.corej2me.com"; HttpConnection http = null; http = (HttpConnection) Connector.open(url); http.setRequestMethod(HttpConnection.GET); // Header field http.setRequestProperty("If-Modified-Since", "Sun, 21 DEC 2003 12:00:00 GMT");

For a complete list of the available header values, see Resources, which lists a link to the HTTP specification.

Client -- Body
Any data that you choose to send to the server is sent as the Body of the client request. As mentioned previously, GET sends the body as part of the URL. POST sends the body in a separate stream. The following short code block shows how you could pass a string of data to a server using a POST request method:
String url = "http://www.corej2me.com", str = "client data"; OutputStream ostrm = null;

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 9 of 48

developerWorks®

ibm.com/developerWorks

HttpConnection http = null; http = (HttpConnection) Connector.open(url); http.setRequestMethod(HttpConnection.POST); // Send client body ostrm = http.openOutputStream(); byte bytes[] = str.getBytes(); for(int i = 0; i < bytes.length; i++) { os.write(bytes[i]); } os.flush();

Interpreting server response
After the server has processed the client request, it will, in turn, send a response. There are up to three sections that might be packaged in the server response: • Status line • Header • Body The following sections describe the contents of each of these sections.

Server -- Status line
An HTTP server returns information that indicates the success or failure of a client request. Status codes are divvied into the following categories: • 1xx - informational • 2xx - success • 3xx - redirection • 4xx - client error • 5xx - server error The complete status line returned from the server includes the HTTP version running on the server, the status code, and a text message. Following are several examples: • "HTTP/1.1 200 OK" • "HTTP/1.1 400 Bad Request"

Session management with J2ME and PHP Page 10 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

• "HTTP/1.1 500 Internal Server Error"

Server -- Header
As with a client, a server can send information (parameters) through header fields. To obtain header field information passed as part of the server response, a client calls one of the following methods:
String getHeaderField(int n) Get header field value looking up by index String getHeaderField(String name) Get header field value looking up by name String getHeaderFieldKey(int n) Get header field key using index

I'll show several examples of how to retrieve header fields when I build the session management MIDlet.

Server -- Body
Beyond the status line and header data, any additional information sent from a server is passed to the client as a Java stream. You'll see a complete example of how to read the body of a server response later in this tutorial. I'll put together all the pieces regarding client and server communication when I write the first MIDlet in an upcoming section.

Section 4. Introduction to PHP
Overview
PHP is a server-side scripting language designed to provide an open source tool for creating dynamic Web content. PHP script is embedded inside an HTML document. When a Web server parses an HTML file, all PHP script is processed by the PHP engine and the output replaces the corresponding PHP code. If you are familiar with programming languages such as C, Perl, or any number of scripting languages, then learning PHP will be fairly simple. I won't present an

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 11 of 48

developerWorks®

ibm.com/developerWorks

in-depth overview of PHP within this tutorial; however, the next three sections will discuss how to embed PHP in an HTML file, creating variables, and the difference between using single quotes ' ' and double quotes " " around text strings.

PHP inside HTML
I'll show how to write a short example of how to write PHP code inside an HTML file. Begin by reviewing the following code:

<html> <head> <title>developerWorks Tutorial</title> </head> <body> <p><em><strong><font color="#800040"> This is the main body of the HTML file</font></strong></em>....</p> <?php echo "PHP embedded in a Web-page!"; ?> </body> </html>

PHP code is placed within the HTML file by enclosing the script inside the tags <?php and ?>. In this example, I call the PHP function echo to display a string of text. Figure 4 shows how this will appear when displayed within a Web browser. Figure 4. PHP output

Session management with J2ME and PHP Page 12 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Although this example is rather trivial, the concept never changes -- the PHP code between the tags <?php and ?> is processed by the PHP engine on the Web server, and the results appear inside the final HTML output.

PHP variables
Next, I'll quickly discuss how to declare variables within PHP. Variables always begin with $, followed by a letter. Any additional characters in the variable name can be either numbers or letters, including underscores. PHP does not force you to specify the data type when creating a variable. In the examples that follow, you'll see both number and string variables created.
<?php /* Define several variables, both numbers and strings */ $house_number = 212; $street = 'Main Street'; $x = 2; $y = 7; $z = $x + $y; // Echo both the house number and street echo $house_number . $street ?>

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 13 of 48

developerWorks®

ibm.com/developerWorks

Notice the string Main Street is enclosed in single quotes. The next section describes the use of quotes in more detail. Also, you can see that PHP supports both multi-line (/* ... */) and single line (// ...) comments.

PHP quotes
Determining which style of quotes to use (' or ") depends on whether you choose to embed variables in the string. This is better understood by looking at an example:
<?php $house_number = 212; $street = 'Main Street'; // Expand variables in double quotes echo "I live at $house_number $street."; // Insert a break in the HTML output echo "<br>"; // Ignore variables in single quotes echo 'I live at $house_number $street.'; ?>

Figure 5. PHP variable expansion

When using double quotes, PHP expands variables that are inside a string. With single quotes, any reference to a variable is treated as pure text.

Session management with J2ME and PHP Page 14 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Section 5. Age Calculator MIDlet
MIDlet screen shots
The first MIDlet will pull together what I have discussed up to this point. The primary emphasis will be on demonstrating communication between a MIDlet and a PHP script. The user interface consists of a data entry field that prompts the user for their birth date. With this information in hand, I'll call a PHP script to calculate the age of the user, and will in turn, display the information on the device display. There are several screen shots of the MIDlet shown below. Figure 6 shows the MIDlet upon startup; notice the date has been programmed to default to the current date. Figure 6. AgeCalculator startup

Figure 7 shows the DateField component as it is displayed within the Wireless Toolkit. Here is where the user will enter their birth date. Figure 7. AgeCalculator datefield

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 15 of 48

developerWorks®

ibm.com/developerWorks

The final step is to calculate the age, based on the date entered. This is done by passing the date to a PHP script running on a Web server. Once the age has been determined, the value is returned to the MIDlet and displayed as shown in Figure 8. Figure 8. AgeCalculator output

Session management with J2ME and PHP Page 16 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Create MIDlet
For each MIDlet you develop in this tutorial, you'll follow the same set of steps when using the Wireless Toolkit: 1. 2. 3. 4. Create the project Write the source code Compile and preverify the code Run the MIDlet

You'll start by creating a project in the next panel.

Create the project
1. Click New Project

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 17 of 48

developerWorks®

ibm.com/developerWorks

2. 3.

Enter the project name and MIDlet class name, as shown in Figure 9 Click Create Project

Figure 9. Create AgeCalculator project

Write the Java code
There are two source code files associated with this MIDlet: • AgeCalculator.java: MIDlet • AgeCalculator.php: PHP script to determine age Begin by copying and pasting the following AgeCalculator.java code into a text editor:
/*-------------------------------------------------* AgeCalculator.java *-------------------------------------------------*/ import java.util.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.io.*; import java.io.*; public class AgeCalculator extends MIDlet implements ItemStateListener, CommandListener { private Display display; // Reference to display object private Form fmMain; // Main form

Session management with J2ME and PHP Page 18 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

private Command cmExit; private DateField dfBday; private TextField tfAge;

// Exit MIDlet // DateField component // Textfield to show age

public AgeCalculator() { display = Display.getDisplay(this); // The main form fmMain = new Form("Age Calculator"); // DateField with today's date as a default dfBday = new DateField("Enter birthday:", DateField.DATE); dfBday.setDate(new Date()); // Create textfield to show age tfAge = new TextField("Your age is: ", "", 3, TextField.NUMERIC | TextField.UNEDITABLE); // All the commands/buttons cmExit = new Command("Exit", Command.EXIT, 1); // Add to form and listen for events fmMain.append(dfBday); fmMain.append(tfAge); fmMain.addCommand(cmExit); fmMain.setCommandListener(this); fmMain.setItemStateListener(this); } public void startApp () { display.setCurrent(fmMain); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } public void itemStateChanged(Item item) { try { // Get an instance of calendar java.util.Calendar cal = java.util.Calendar.getInstance(); // Set calendar to the date user entered cal.setTime(dfBday.getDate()); System.out.println("month: " + cal.get(java.util.Calendar.MONTH)); System.out.println("day: " + cal.get(java.util.Calendar.DAY_OF_MONTH)); System.out.println("year: " + cal.get(java.util.Calendar.YEAR)); // Connect to server running PHP. Pass in the date entered connect(cal.get(java.util.Calendar.MONTH), cal.get(java.util.Calendar.DAY_OF_MONTH), cal.get(java.util.Calendar.YEAR)); } catch (Exception e) { db("connect " + e.toString()); } } public void commandAction(Command c, Displayable s) {

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 19 of 48

developerWorks®

ibm.com/developerWorks

if (c == cmExit) { destroyApp(false); notifyDestroyed(); } } /*-------------------------------------------------* Send request to PHP to determine age * based on the date entered *-------------------------------------------------*/ private void connect(int month, int day, int year) throws IOException { InputStream iStrm = null; ByteArrayOutputStream bStrm = null; HttpConnection http = null; String url = "http://localhost/AgeCalculator.php"; try { // Append all the parameters onto the url // Resulting string will look something like: // http://localhost/AgeCalculator.php?month=7&day=5&year=1902" url = url + "?month=" + Integer.toString(month+1) + "&day=" + Integer.toString(day) + "&year=" + Integer.toString(year); System.out.println("url: " + url); // Create the connection http = (HttpConnection) Connector.open(url); //---------------// Client Request //---------------// 1) Send request method http.setRequestMethod(HttpConnection.GET); // If you experience connection/IO problems, try // removing the comment from the following line //http.setRequestProperty("Connection", "close"); // 2) Send header information - No header // 3) Send body/data - No data for this request //---------------// Server Response //---------------// 1) Get status Line if (http.getResponseCode() == HttpConnection.HTTP_OK) { // 2) Get header information - No header // 3) Get data from server int ch; iStrm = http.openInputStream(); bStrm = new ByteArrayOutputStream(); while ((ch = iStrm.read()) != -1) { // Ignore any carriage returns/linefeeds if (ch != 10 && ch != 13) bStrm.write(ch); } // Update the textfield with the age tfAge.setString(new String(bStrm.toByteArray())); } }

Session management with J2ME and PHP Page 20 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

finally { // Clean up if (iStrm != null) iStrm.close(); if (bStrm != null) bStrm.close(); if (http != null) http.close(); } } /*-------------------------------------------------* Simple message to console for debug/errors *-------------------------------------------------*/ private void db(String str) { System.err.println("Msg: " + str); } }

When you create a new project, the WTK builds the proper directory structure for you. In this example, the WTK has created the C:\WTK21\apps\AgeCalculator directory and the necessary subdirectories. Save your Java source file as AgeCalculator.java in the src directory as shown in Figure 10. (Note that the drive and WTK directory will vary depending on where you have installed the toolkit.) Figure 10. Save AgeCalculator code

Note: I'll cover the specifics of what is happening in the Java code a little later in the tutorial.

Write the PHP script
Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 21 of 48

developerWorks®

ibm.com/developerWorks

The second source code file is the PHP script, which calculates the age based on a specified date. Copy and paste the following into a text editor:
<?php function getAge($month, $day, $year) { // Get the current month, day and year $currentMonth = date("m"); $currentDay = date("d"); $currentYear = date("Y"); // Get starting point for age... $age = $currentYear - $year - 1; // If birth-month has been passed, // or birthday is/was this month // increase the age If ($month < $currentMonth OR ($month == $currentMonth AND $day <= $currentDay)) $age++; return $age; } // Get the parameters from the URL $month = $_GET["month"]; $day = $_GET["day"]; $year = $_GET["year"]; if ($month != "" AND $day != "" AND $year != "") echo getAge($month, $day, $year); else echo "invalid date information"; ?>

You will need to save this source file as AgeCalculator.php in the doc root on the Web server. Figure 11 shows the default location when installing Apache using the default configuration options. Figure 11. Save AgeCalculator PHP code

Session management with J2ME and PHP Page 22 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Note: As with the Java source, I'll revisit the PHP code in an upcoming section to explain just what is taking place.

Save, compile, and preverify
1. Select Build to compile, preverify, and package the MIDlet, as shown in Figure 12. Figure 12. Build AgeCalculator project

2.

Select Run to start the Application Manager.

Start the AgeCalculator MIDlet
To start the AgeCalculator MIDlet, select Launch, as shown in Figure 13. Figure 13. Launch AgeCalculator MIDlet

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 23 of 48

developerWorks®

ibm.com/developerWorks

Figure 14 shows a series of screen shots that demonstrate the MIDlet in action. Figure 14. AgeCalculator output

Session management with J2ME and PHP Page 24 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Code review: itemStateChanged()
There are two primary sections of the MIDlet code to review. First is the event handling code inside the itemStateChanged() method. The code is shown below.
public void itemStateChanged(Item item) { try { // Get an instance of calendar java.util.Calendar cal = java.util.Calendar.getInstance(); // Set calendar to the date user entered cal.setTime(dfBday.getDate()); System.out.println("month: " + cal.get(java.util.Calendar.MONTH)); System.out.println("day: " + cal.get(java.util.Calendar.DAY_OF_MONTH)); System.out.println("year: " + cal.get(java.util.Calendar.YEAR)); // Connect to server running PHP. Pass in the date entered connect(cal.get(java.util.Calendar.MONTH), cal.get(java.util.Calendar.DAY_OF_MONTH), cal.get(java.util.Calendar.YEAR)); } catch (Exception e) { db("connect " + e.toString()); } }

When the user changes the value of the DateField component, the above method is called. I create a Calendar object and set the date to the value entered by the user. I have also included several println() statements for debugging purposes. With the date information in hand, I now call the connect() method, passing in the values for the selected month, day, and year. As you'll see in the next section, the connect() method passes this information to the Web server for processing by the PHP script.

Code review: connect()
The first few lines allocate several variables I'll need to communicate with the Web server. Included is the URL where the PHP script can be found. The next step is to build the entire URL, appending the values for the month, day, and year parameters passed from the itemStateChanged() method. Notice how each parameter is a key-value pair, where the key and value are separated by = and key-value pairs are separated by &.

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 25 of 48

developerWorks®

ibm.com/developerWorks

private void connect(int month, int day, int year) throws IOException { InputStream iStrm = null; ByteArrayOutputStream bStrm = null; HttpConnection http = null; String url = "http://localhost/AgeCalculator.php"; try { // Append all the parameters onto the url // Resulting string will look something like: // http://localhost/AgeCalculator.php?month=7&day=5&year=1902" url = url + "?month=" + Integer.toString(month+1) + "&day=" + Integer.toString(day) + "&year=" + Integer.toString(year); ...

The bulk of the remaining code establishes the HTTP connection, checks the server return code, reads the data from the server (as a stream), and updates the TextField, which will display the calculated age on the device.
http = (HttpConnection) Connector.open(url); //---------------// Client Request //---------------// 1) Send request method http.setRequestMethod(HttpConnection.GET); // 2) Send header information - No header // 3) Send body/data - No data for this request //---------------// Server Response //---------------// 1) Get status Line if (http.getResponseCode() == HttpConnection.HTTP_OK) { // 2) Get header information - No header // 3) Get data from server int ch; iStrm = http.openInputStream(); bStrm = new ByteArrayOutputStream(); while ((ch = iStrm.read()) != -1) { // Ignore any carriage returns/linefeeds if (ch != 10 && ch != 13) bStrm.write(ch); } // Update the textfield with the age tfAge.setString(new String(bStrm.toByteArray())); ...

Code review: PHP script

Session management with J2ME and PHP Page 26 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

The final stop with this MIDlet is to review the code for the PHP script, which determines the age of the user based on the month, day, and year parameters passed into the script. Start by looking at the code in its entirety.
<?php function getAge($month, $day, $year) { // Get the current month, day and year $currentMonth = date("m"); $currentDay = date("d"); $currentYear = date("Y"); // Get starting point for age... $age = $currentYear - $year - 1; // If birth-month has been passed, // or birthday is/was this month // increase the age If ($month < $currentMonth OR ($month == $currentMonth AND $day <= $currentDay)) $age++; return $age; } // Get the parameters from the URL $month = $_GET["month"]; $day = $_GET["day"]; $year = $_GET["year"]; if ($month != "" AND $day != "" AND $year != "") echo getAge($month, $day, $year); else echo "invalid date information"; ?>

I'll start near the bottom and work my way up. My first job is to save the parameters that are passed into the script from the client. Using _GET I can parse and save each value that was previously appended onto the URL on the client code. If there are values for the month, day, and year, I call the method getAge(); otherwise, I echo (return to the client) a text string indicating an error. When all the parameters are present,the getAge() method has all the information it needs to calculate the age based on the birth date entered. I begin by determining the current month, day and year, and storing these values into the variables $currentMonth, $currentDay and $currentYear. Next, I get the age by subtracting the current year from the year passed in by the client. I need an additional check to see if the birth month has already occurred this year (for example, if the current month is December and the client passed in November). If this is true, the client has already had a birthday for this year; therefore, I need to increase the age by 1. Similarly, if the client month equals the current month (for example, the client entered December, and the current month is December) and the client day is the same as the current day or any day prior, then I know the client has had a birthday this month and I need to increase the age by 1.
Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 27 of 48

developerWorks®

ibm.com/developerWorks

Although it might seem a little fuzzy when to trying to decipher the above description, it really comes down to nothing more than determining the age based on subtracting the birth date from today's date, and then determining if I need to add one more year because the requested date has already occurred this year. Simple as that.

Section 6. Session management
Overview
At this point, you have the basic knowledge you need to communicate between a J2ME application and a Web server running PHP. This section builds upon what you have learned in order to show how to manage sessions on a Web server using cookies and PHP. I'll begin with an overview of HTTP and cookies. HTTP is a stateless protocol. When accessing content over HTTP there is no persistent connection established, each request to a Web server is independent. This form of communication is typically not much of an issue, as most users move about the Internet clicking on links, which results in Web pages being loaded on demand. Where this falls short is when you need a way for a remote server to remember information about a visitor. The most common example is that of a shopping cart. As you browse from page to page selecting products, somewhere, somehow, that information needs to be stored. Session management is the term applied to the concept of maintaining state between a browser and server, in our case, between a MIDlet and a server. One way to allow such client and server interaction is through the use of cookies. Without getting into a full-scale discussion of cookies, I'll review the basic concept as it applies to the MIDlet I'll create in this section. The application I'll build allows the mobile device to keep track of a user's golf score as they play a round of golf. Upon completion of each hole, they enter their score into the MIDlet. The MIDlet, in turn, passes the score to a PHP script that calculates the running total for the user and returns this value to the client. Given that HTTP is a stateless protocol, the client and server have no inherent means to stay connected, if you will. I'll provide such capability using cookies. For this discussion, think of a cookie as nothing more than a unique identifier passed back and forth between the MIDlet (client) and the Web server running PHP. Using this identifier, the server can "recognize" a client request and associate this request with a previous visit. The server stores and calculates golf scores for any number of unique clients.

Session management with J2ME and PHP Page 28 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Get user input
I'll go through the steps of how the MIDlet will maintain state using cookies and PHP. It begins by prompting the user for their score on the first hole. See Figure 15. Figure 15. Get first hole score

Pass client information to server
With the score in hand, I need to construct a URL, including the score as a parameter. See the directional arrow from the client to the server in Figure 16. This indicates the URL I'll construct. Notice how the value of the golf score is appended onto the URL. Figure 16. Pass score to server

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 29 of 48

developerWorks®

ibm.com/developerWorks

On the server, the PHP script looks for a cookie passed from the client. If no cookie exists, the server knows this is the first request from this client and generates a random number to act as the unique identifier for the session between the client and server. In a more robust application, this ID would more than likely be stored in a database. However, to keep things simple, I'll create a file using the ID as the file name. With the file created, the golf score passed to the server is written into the file. The final step is to send the new ID back to the client in a cookie, which is done using an HTTP header with the value set-cookie. What I have at this point is a unique identifier on the server side, namely, a file that contains the score for the client's first golf hole. As you'll see momentarily, when a future request comes from a client, passing along this unique ID (cookie), the server can associate the incoming request with a file on the server. This rudimentary scheme is enough to allow a client and server to maintain an ongoing dialog, even though HTTP is stateless.

Subsequent client requests
When the server passes a cookie (the unique ID) to the client on the initial round of communication, the client stores this ID into a variable. For each subsequent golf score sent to the server, the client also passes this unique ID using an HTTP header. See Figure 17. Figure 17. Subsequent client requests

Upon receiving the cookie, the PHP script locates the file name that has the same value. The file is opened, and the contents read. Remember, the first value written to the file was the score for the first golf hole. The script adds the value of the score passed in from the client to that which was read from the file. This becomes the new
Session management with J2ME and PHP Page 30 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

running total for the golfer. Referring back to Figure 17, you'll see the final step is to send the new total back to the client, which is shown on the display. This back and forth dialog, passing a golf score and cookie, and returning a new running total, is the basis for the Golf Calculator MIDlet. Once 18 scores have been entered (a traditional round of golf), the MIDlet displays the final score as shown in Figure 18. Figure 18. Final golf score

Section 7. Golf Calculator MIDlet
Write the Java code
With the groundwork in place, I'll create the MIDlet. This includes creating the project, writing the Java and PHP script code, and compiling and running the application. Near the end of this section, I'll do a short code review to pinpoint the

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 31 of 48

developerWorks®

ibm.com/developerWorks

code that is specific to this MIDlet. Begin by creating a new project in the WTK with the name GolfCalculator. Copy and paste the Java source code below into a text editor and save the file as GolfCalculator.java in the WTK \apps\GolfCalculator\src directory.

/*-------------------------------------------------* GolfCalculator.java *-------------------------------------------------*/ import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.rms.*; import javax.microedition.io.*; import java.io.*; public class GolfCalculator extends MIDlet implements CommandListener { private Display display; // Reference to display object private TextField tfScore; // Textfield to enter gold scores private TextField tfTotal; // Textfield to show golf score running total private Form fmMain; // Main form that displays textfields private Command cmExit; // Exit MIDlet private Command cmSubmit; // Submit golf score private Command cmReset; // Reset textfields and cookie private String cookie = null; // Cookie (ID) private String url = "http://localhost/GolfCalculator.php"; private int holeNumber = 1; // Current hole in play public GolfCalculator() { display = Display.getDisplay(this); // Create commands cmExit = new Command("Exit", Command.EXIT, 1); cmSubmit = new Command("Submit", Command.SCREEN, 2); cmReset = new Command("Reset", Command.SCREEN, 3); // Create textfields tfScore = new TextField("Hole #1 Score:", "", 2, TextField.NUMERIC); tfTotal = new TextField("Total:", "", 3, TextField.NUMERIC | TextField.UNEDITABLE); // Create the form, add commands, listen for events

Session management with J2ME and PHP Page 32 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

fmMain = new Form("Golf Score Calculator"); fmMain.append(tfScore); fmMain.append(tfTotal); fmMain.addCommand(cmExit); fmMain.addCommand(cmSubmit); fmMain.addCommand(cmReset); fmMain.setCommandListener(this); } public void startApp() { display.setCurrent(fmMain); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } /*-------------------------------------------------* Send client request and recieve server response * * Client: If cookie exists, send it to the server * * Server: If cookie is sent back, this is the * clients first request to the server. In * that case, save the cookie for use in * all future requests. *-------------------------------------------------*/ private void connect(String score) throws IOException { InputStream iStrm = null; ByteArrayOutputStream bStrm = null; HttpConnection http = null; String running_total = null; try { // Create the connection http = (HttpConnection) Connector.open(url + "?score=" + score); System.out.println(url + "?score=" + score); //---------------// Client Request //---------------// 1) Send request method http.setRequestMethod(HttpConnection.GET); // If you experience connection/IO problems, try // removing the comment from the following line //http.setRequestProperty("Connection", "close"); // 2) Send header information if (cookie != null) http.setRequestProperty("cookie", cookie); // 3) Send body/data - No data for this request //---------------// Server Response //---------------// 1) Get status Line if (http.getResponseCode() == HttpConnection.HTTP_OK) { // 2) Get header information String tmpCookie = http.getHeaderField("set-cookie");

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 33 of 48

developerWorks®

ibm.com/developerWorks

// Cookie will only be sent back from server only // on the first call to the server if (tmpCookie != null) { // Save cookie variable, we'll use this // each time we call the server in the future cookie = tmpCookie; // Since this step only occurs on the first call // to the server, the current running total is // simply the score the user entered running_total = score; } else { // No cookie sent from server, running total returned

// 3) Get data from server, which is the current // running golf score iStrm = http.openInputStream(); int length = (int) http.getLength(); int ch; bStrm = new ByteArrayOutputStream(); while ((ch = iStrm.read()) != -1) { // Ignore any carriage returns/linefeeds if (ch != 10 && ch != 13) bStrm.write(ch); } running_total = new String(bStrm.toByteArray()); } // Update the total on the display if (running_total != null) tfTotal.setString(running_total); } } finally { // Clean up if (iStrm != null) iStrm.close(); if (bStrm != null) bStrm.close(); if (http != null) http.close(); } } /*-------------------------------------------------* Process events *-------------------------------------------------*/ public void commandAction(Command c, Displayable s) { // If the Command button pressed was "Exit" if (c == cmExit) { destroyApp(false); notifyDestroyed(); } else if (c == cmSubmit) // Submit score { if (holeNumber++ <= 18) { try {

Session management with J2ME and PHP Page 34 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

// Connect to the server, passing in the current score connect(tfScore.getString()); // Reset the textfield containing score for current hole tfScore.setString(""); // Reset the label so the correct hole number is displayed if (holeNumber != 19) tfScore.setLabel("Hole #" + holeNumber + " Score:"); else fmMain.append("Your final score for 18 holes of golf is: " + tfTotal.getString()); } catch (Exception e) { db("connect " + e.toString()); } } } else if (c == cmReset) // Reset all fields/variables { // Reset textfields tfScore.setString(""); tfTotal.setString(""); // Reset the count of which hole we are on holeNumber = 1; // Reset label that shows hole number tfScore.setLabel("Hole #" + holeNumber + " Score:"); // Reset the cookie to null cookie = null; } } /*-------------------------------------------------* Simple message to console for debug/errors *-------------------------------------------------*/ private void db(String str) { System.err.println("Msg: " + str); } }

Write the PHP script
The next step is to write the PHP script, which will process the golf scores. Copy and paste the following GolfCalculator.php into a text editor:
<?php //------------------------------------------------------// Create a file based on $filename passed in, // Write $data into this same file //------------------------------------------------------function create_file($filename, $data) { $retval = true; // Create the file, open in write mode if (!$file_handle = fopen($filename,"w"))

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 35 of 48

developerWorks®

ibm.com/developerWorks

return false; // Write the score into the file if (!fwrite($file_handle, $data)) $retval = false; // Clean up fclose($file_handle); // Return boolean value indicating success or failure return $retval; } //------------------------------------------------------// Open $filename and read the value stored in the file. // Add $score to this value, and write the new // total back into $filename //------------------------------------------------------function read_file($filename, $score) { // Open file for reading ("r") // Return -1 on error if (!$file_handle = fopen($filename,"r")) return -1; // Get the current running total. // No error checking, assumes read will be successful $data = fread($file_handle, filesize($filename)); // Add to the total, the current client value passed in $data += $score; // Truncate file contents to remove previous score ftruncate($file_handle, 0); // Write the new running total to file fwrite($file_handle, $data); // Clean up the open file fclose($file_handle); // The current running total return $data; } ?> <?php //------------------------------------------------------// It all starts here. // Get the 'score' parameter passed in the url //------------------------------------------------------if (isset($_GET)) { $score = $_GET["score"]; } // Get the incoming cookie, which also // represents the filename for reading/writing $cookie = $HTTP_COOKIE_VARS["ID"]; // If no cookie, this is the first time // accessing this running this script // from the client if($cookie == "") { // Generate a random number between 1 and 10 // This is our unique identifier (ID) for this session srand((double)microtime() * 1000000); $id = rand(1,100);

Session management with J2ME and PHP Page 36 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

// Create a cookie to pass back to the client setcookie("ID", $id); // Create the file using the new "id" as the name // Write the score passed in from the client create_file($id, $score); // Since this code is run only on the first call // from the client, the current running total is // simply the score the client passed in $running_total = $score; } else { // Update the running total, with the score // the client passed in $running_total = read_file($cookie, $score); } print $running_total; ?>

Save this file as GolfCalculator.php in the doc root on the Web server.

Compile, preverify, and run
Within the WTK, select Build to compile, preverify, and package our GolfCalculator MIDlet. Following are a series of displays that demonstrate the MIDlet in action, beginning with Figure 19, which shows the launching of the application. Figure 19. Launch and run

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 37 of 48

developerWorks®

ibm.com/developerWorks

Submit golf scores
After the MIDlet is running, you enter a score and select Submit to send the score to the server. When the server responds, the running total is displayed. The display to the left shows submitting a score for the first hole, while the display to the right shows the running total after 5 scores have been entered. Figure 20. Enter scores

Session management with J2ME and PHP Page 38 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

Reset MIDlet
There is one additional option with this MIDlet that I have not discussed: If at any point you would like to reset the application -- that is, restart the scoring process from hole one -- there is a reset option in the menu. See Figure 21. Figure 21. Reset scores

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 39 of 48

developerWorks®

ibm.com/developerWorks

Choosing the reset option results in the following: • Clearing of both the score and total TextFields • Resetting the current hole number to 1 • Deleting the cookie (unique ID) on the client With the cookie deleted, the session between the client and server will essentially end. Although the file I created on the server still exists, it no longer has an association to this MIDlet. For this small example, removing the file is not of concern because if a future MIDlet is assigned the same ID, the PHP script will overwrite the previous file contents when the first score is submitted.

Code review: event processing
The code for managing events is listed below. I have included only the essential details to keep the focus on what is specific to this application.
public void commandAction(Command c, Displayable s) { ... else if (c == cmSubmit) // Submit score { if (holeNumber++ <= 18) { // Connect to the server, passing in the current score

Session management with J2ME and PHP Page 40 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

connect(tfScore.getString()); // Reset the textfield containing score for current hole tfScore.setString(""); // Reset the label so the correct hole number is displayed if (holeNumber != 19) tfScore.setLabel("Hole #" + holeNumber + " Score:"); else fmMain.append("Your final score for 18 holes of golf is: " + tfTotal.getString()); } } else if (c == cmReset) // Reset all fields/variables { // Reset textfields tfScore.setString(""); tfTotal.setString(""); // Reset the count of which hole we are on holeNumber = 1; // Reset label that shows hole number tfScore.setLabel("Hole #" + holeNumber + " Score:"); // Reset the cookie to null cookie = null; } }

If a request is made to submit a score, the first check is to verify that all 18 scores have not been processed. If everything looks good, I initiate a call to the connect() method, passing in the value (the current hole score) entered by the user. The connect() method, which I will discuss in the following sections, is where I establish a connection to the Web server and run the PHP script. I also need to clear the TextField that prompts for the score and change its label to properly indicate the next hole number. If the user has selected to reset the application, the steps for resetting all the variables, including the cookie, are completed.

Code review: connect to server
Let's review the code inside the connect() method, which is the workhorse for this MIDlet. I'll cover this method over the span of three sections, beginning with how I establish a connection to the server.
private void connect(String score) throws IOException { InputStream iStrm = null; ByteArrayOutputStream bStrm = null; HttpConnection http = null; String running_total = null; try

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 41 of 48

developerWorks®

ibm.com/developerWorks

{ // Create the connection http = (HttpConnection) Connector.open(url + "?score=" + score); System.out.println(url + "?score=" + score); //---------------// Client Request //---------------// 1) Send request method http.setRequestMethod(HttpConnection.GET); // If you experience connection/IO problems, try // removing the comment from the following line //http.setRequestProperty("Connection", "close"); // 2) Send header information if (cookie != null) http.setRequestProperty("cookie", cookie); // 3) Send body/data - No data for this request

I am using a GET request; therefore, I append the current golf score onto the url. In contrast, if I had opted to use POST, the score would be sent as a stream of data separate from the connection request. The final step is to see if the MIDlet has a stored value for the cookie variable. If not, this indicates that the MIDlet has not yet established a connection with the server. If yes, then I need to set the proper HTTP header so the server will be able to recognize the incoming request and make an association between the request and this specific MIDlet.

Code review: interpret server response
In processing the server response, the first check is to verify that the server returned a response code indicating the request was processed successfully. Assuming everything is fine, the next step is to look for a cookie sent from the server. If a cookie is returned, I know that this is the first response from the server, and in that case, I need to store the cookie value in a variable that will be accessible for all future requests to the server.
private void connect(String score) throws IOException { ... //---------------// Server Response //---------------// 1) Get status Line if (http.getResponseCode() == HttpConnection.HTTP_OK) { // 2) Get header information String tmpCookie = http.getHeaderField("set-cookie");

Session management with J2ME and PHP Page 42 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

// Cookie will only be sent back from server only // on the first call to the server if (tmpCookie != null) { // Save cookie variable, we'll use this // each time we call the server in the future cookie = tmpCookie; // Since this step only occurs on the first call // to the server, the current running total is // simply the score the user entered running_total = score; } else { // No cookie sent from server, running total returned

// 3) Get data from server, which is the current // running golf score iStrm = http.openInputStream(); int length = (int) http.getLength(); int ch; bStrm = new ByteArrayOutputStream(); while ((ch = iStrm.read()) != -1) { // Ignore any carriage returns/linefeeds if (ch != 10 && ch != 13) bStrm.write(ch); } running_total = new String(bStrm.toByteArray()); } // Update the total on the display if (running_total != null) tfTotal.setString(running_total); } } ... }

Should the server not respond with a cookie, I assume there is already an ongoing dialog with the server. In this case, I open a stream and read the current running golf score as calculated by the PHP script on the server. The final step, regardless of whether this is the server's first response to the MIDlet, is to update the TextField on the display that indicates the current golf score.

Code review: PHP incoming request
Now, I'll shift gears from reviewing the Java code and give you a closer look at how the PHP script handles and processes the submitted scores. I begin by looking for a parameter in the URL with the name score. If found, I save the value into a local variable with the same name. This is followed by a check to

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 43 of 48

developerWorks®

ibm.com/developerWorks

determine if the MIDlet passed in a cookie. If no cookie was sent, the script knows this is the first request from the MIDlet and proceeds to generate a random number (between 1 and 100) that will act as the unique ID to manage a session between the MIDlet and the script. As part of this process, the script will call the create_file() method to create a new file using the ID as the file name, and write the current score into this same file. The next section goes into detail describing how PHP creates and writes to the file system.
<?php //------------------------------------------------------// It all starts here. // Get the 'score' parameter passed in the url //------------------------------------------------------if (isset($_GET)) { $score = $_GET["score"]; } // Get the incoming cookie, which also // represents the filename for reading/writing $cookie = $HTTP_COOKIE_VARS["ID"]; // If no cookie, this is the first time // accessing this running this script // from the client if($cookie == "") { // Generate a random number between 1 and 100 // This is our unique identifier (ID) for this session srand((double)microtime() * 1000000); $id = rand(1,100); // Create a cookie to pass back to the client setcookie("ID", $id); // Create the file using the new "id" as the name // Write the score passed in from the client create_file($id, $score); // Since this code is run only on the first call // from the client, the current running total is // simply the score the client passed in $running_total = $score; } else { // Update the running total, with the score // the client passed in $running_total = read_file($cookie, $score); } print $running_total; ?>

Code review: PHP write file information
In the code below, the variable $filename is the unique identifier assigned to the
Session management with J2ME and PHP Page 44 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

incoming MIDlet request. Here I create a file using this same value, whereas in a database implementation, this would translate to creating a row in a database, with the unique identifier as the key.
//------------------------------------------------------// Create a file based on $filename passed in, // Write $data into this same file //------------------------------------------------------function create_file($filename, $data) { $retval = true; // Create the file, open in write mode if (!$file_handle = fopen($filename,"w")) return false; // Write the score into the file if (!fwrite($file_handle, $data)) $retval = false; // Clean up fclose($file_handle); // Return boolean value indicating success or failure return $retval; }

The score for the first golf hole is written into the file, the file is closed, and the method is exited.

Code review: PHP subsequent requests
If the MIDlet passed in a cookie to the PHP script, I know that the MIDlet and script have previously communicated. Therefore, I call the read_file() method to manage the incoming MIDlet request. Here, I read the score stored in the file, add to this the score passed in from the client, and write the new value back into the file. To keep with the database analogy, these steps would correlate to looking up a specific row in the database, retrieving and updating the value, and writing the new value back into the database.
function read_file($filename, $score) { // Open file for reading ("r") // Return -1 on error if (!$file_handle = fopen($filename,"r")) return -1; // Get the current running total. // No error checking, assumes read will be successful $data = fread($file_handle, filesize($filename)); // Add to the total, the current client value passed in $data += $score;

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 45 of 48

developerWorks®

ibm.com/developerWorks

// Truncate file contents to remove previous score ftruncate($file_handle, 0); // Write the new running total to file fwrite($file_handle, $data); // Clean up the open file fclose($file_handle); // The current running total return $data; }

Code review: PHP return value
Whether the incoming connection to the PHP script is the first or any subsequent request, the end result is that the variable $running_total will be populated with the current golf score. The last step in the script is to return this value to the MIDlet, which will, in turn, read and display the score. The single line of PHP code to return data back to the client is no more complicated than the following:
print $running_total;

At this point, the MIDlet is complete. You've had a chance to see how to communicate between a client and server using HTTP, and have learned how to manage sessions using cookies and PHP.

Section 8. Summary and resources
Summary
In this tutorial I covered a great deal of ground. I began with an introduction to HTTP. This was followed by an overview of PHP, including how to embed PHP in an HTML document and the basic principals of working with PHP variables. The first MIDlet tied together the concepts using a simple calculator that would determine someone's age based on their birth date. The second section of this tutorial focused on session management; specifically, how to create and establish session between a MIDlet and a Web server running PHP. I started with an overview of the stateless nature of HTTP. I then briefly
Session management with J2ME and PHP Page 46 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.

ibm.com/developerWorks

developerWorks®

discussed how cookies can be used to manage state information. I concluded this section by developing a MIDlet that would calculate golf scores by using cookies as the session management protocol. You now have a good base of information to begin developing MIDlets that can manage session information with a server that is running PHP. As with so many software applications, once a basic understanding is in place, you can conquer a great number of projects. Take what you have learned here and see what you can dream up for an interesting application that requires managing of sessions between a client and server.

Session management with J2ME and PHP © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 47 of 48

developerWorks®

ibm.com/developerWorks

Resources
Learn • Additional articles and resources can be found at Core J2ME. • To learn more about the HTTP specification, visit Hypertext Transfer Protocol. • PHP is an open source scripting tool to create dynamic Web content. • The developerWorks Wireless technology content area features an abundance of wireless-related technical content and resources. • The WebSphere Micro Environment provides an end-to-end solution connecting cellular phones, PDAs, and other pervasive devices to e-businesses. • The alphaWorks Web Services Toolkit for Mobile Devices provides tools and a run time environment for developing applications that use Web services on small mobile devices, gateway devices, and intelligent controllers. • MIDlet development with the Wireless Toolkit (developerWorks, March 2003) guides you through the basic steps for MIDlet development with J2ME. • Networking with J2ME (developerWorks, September 2002) guides you through the basic steps of MIDlet networking. Get products and technologies • Download the Java Development Kit 1.4.2. • Click here to get the J2ME Wireless Toolkit. • Download the Apache Web server and documentation.

About the author
John Muchow John Muchow, an independent J2ME consultant, technical writer, and trainer, is the author of Core J2ME Technology and MIDP . Visit Core J2ME for additional source code, articles, and developer resources. Send John e-mail for additional information about consulting, training or writing projects.

Session management with J2ME and PHP Page 48 of 48

© Copyright IBM Corporation 1994, 2008. All rights reserved.


				
DOCUMENT INFO
Shared By:
Stats:
views:6284
posted:5/14/2009
language:English
pages:48
Description: Comprehensive Guide on session management in J2ME and PHP. Session management is an important part when we create a mobile e-commerce application and this document provides a head start on session management in J2ME and PHP.