ToolboxME for iSeries example: JdbcDemo.java

To create this example as a working ToolboxME for iSeries™ program, you need to copy the following .java file into a text or Java™ editor, make a few changes, then compile it.

To copy the source code, simply use your mouse to select all the Java code below, then right-click and select Copy. To paste the code into your editor, create a blank document in the editor, right-click the blank document and select Paste. Make sure to save the new document with the name JdbcDemo.java.

After you create the .java file, return to the instructions for creating and running the example program.

Note: Read the Code example disclaimer for important legal information.
//////////////////////////////////////////////////////////////////////////////////
//
// ToolboxME for iSeries example. This program demonstrates how your wireless
// device can connect to an iSeries server and use JDBC to perform work on a
// remote database.
//
//////////////////////////////////////////////////////////////////////////////////

import java.sql.*;               // SQL Interfaces provided by JdbcMe
import com.ibm.as400.micro.*;    // JdbcMe implementation
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.microedition.io.*;  // Part of the CLDC specification
import de.kawt.*;                // Part of the CLDC specification

class DemoConstants
{
    // These constants are actually used mainly by the demo
    // for the JDBC driver. The Jdbc and JDBC  application
    // creator IDs ( http://www.palmos.com/dev )
    // are reserved at palm computing.
    public static final int demoAppID    = 0x4a444243; // JDBC
    // Make the dbCreator something else so that the
    // user can actually see the Palm DB seperately from
    // the JdbcDemo application.
    public static final int dbCreator    = 0x4a444231; // JDB1
    public static final int dbType       = 0x4a444231; // JDB1
}

/**
 * Little configuration dialog box to display the
 * current connections/statements, the
 * URL being used, user id and password
 */
class ConfigurationDialog extends Dialog implements ActionListener
{
    TextField         data;
    ConfigurationDialog(Frame w)
    {
        super(w, "Configuration");

        // Show/Modify current URL connection
        data = new TextField(JdbcDemo.mainFrame.jdbcPanel.url);
        add("Center", data);

        // Ok button.
        Panel panel = new Panel();
        Button button = new Button("Ok");
        button.addActionListener(this);
        panel.add(button);
        add("South", panel);
        pack();
    }

    public void actionPerformed(ActionEvent e)
    {
        JdbcDemo.mainFrame.jdbcPanel.url = data.getText();
        data = null;
        setVisible(false);
    }
}

/**
 * Little configuration dialog box to display the
 * current connections/statements, the
 * URL being used, user id and password
 */
class MultiChoiceDialog extends Dialog implements ActionListener
{
    Choice            task;
    ActionListener    theListener;
    MultiChoiceDialog(Frame w, String title, String prompt, String choices[], ActionListener it)
    {
        super(w, title);
        theListener = it;

        // Show/Modify current URL connection
        Label txt = new Label(prompt);
        add("West", txt);
        task = new Choice();
        for (int i=0; i<choices.length; ++i)
        {
            task.add(choices[i]);
        }
        task.select(0);
        add("Center", task);

        // Ok button.
        Panel panel = new Panel();
        Button button = new Button("Ok");
        button.addActionListener(this);
        panel.add(button);
        button = new Button("Cancel");
        button.addActionListener(this);
        panel.add(button);
        add("South", panel);
        pack();
    }

    /**
     *  Determine the action performed.
     **/
    public void actionPerformed(ActionEvent e)
    {
        int choice = task.getSelectedIndex();
        setVisible(false);
        if (e.getActionCommand().equals("Ok"))
        {
            if (theListener != null)
            {
                ActionEvent ev = new ActionEvent(this, 
                                                 ActionEvent.ACTION_PERFORMED,
                                                 task.getItem(choice));
                theListener.actionPerformed(ev);
            }
            task = null;
        }
        else
        {
            // No-op
        }
    }
}

/**
 * The JdbcPanel is the main panel of the application.
 * It displays the current connection and statement
 * at the top.
 * A text field for entering SQL statements next.
 * A Results field for displaying each column of data
 * or results.
 * An task list and a 'go' button so that different
 * tasks can be tried.
 */
class JdbcPanel extends Panel implements ActionListener
{
    public final static int TASK_EXIT         =  0;
    public final static int TASK_NEW          =  1;
    public final static int TASK_CLOSE        =  2;
    public final static int TASK_EXECUTE      =  3;
    public final static int TASK_PREV         =  4;
    public final static int TASK_NEXT         =  5;
    public final static int TASK_CONFIG       =  6;
    public final static int TASK_TOPALMDB     =  7;
    public final static int TASK_FROMPALMDB   =  8;
    public final static int TASK_SETAUTOCOMMIT=  9;
    public final static int TASK_SETISOLATION = 10;
    public final static int TASK_COMMIT       = 11;
    public final static int TASK_ROLLBACK     = 12;


    // JDBC objects.
    java.sql.Connection  connObject  = null;
    Statement            stmtObject  = null;
    ResultSet            rs          = null;
    ResultSetMetaData    rsmd        = null;

    String        lastErr     = null;
    String        url         = null;
    Label         connection  = null;
    Label         statement   = null;
    TextField     sql         = null;
    List          data        = null;
    final Choice  task;

    /**
     * Build the GUI.
     */
    public JdbcPanel()
    {
        // The JDBC URL
        // Make sure to edit the following line so that it correctly specifies the 
        // the MEServer and the iSeries server to which you want to connect.
        url = "jdbc:as400://mySystem;user=myUidl;password=myPwd;meserver=myMEServer;";

        Panel    p1left = new Panel();
        p1left.setLayout(new BorderLayout());
        connection = new Label("None");
        p1left.add("West", new Label("Conn:"));
        p1left.add("Center", connection);

        Panel    p1right = new Panel();
        p1right.setLayout(new BorderLayout());
        statement = new Label("None");
        p1right.add("West", new Label("Stmt:"));
        p1right.add("Center", statement);

        Panel    p1 = new Panel();
        p1.setLayout(new GridLayout(1,2));
        p1.add(p1left);
        p1.add(p1right);

        Panel    p2 = new Panel();
        p2.setLayout(new BorderLayout());
        p2.add("North", new Label("Sql:"));
        sql = new TextField(25);
        sql.setText("select * from QIWS.QCUSTCDT"); // Default query
        p2.add("Center", sql);

        Panel    p3 = new Panel();
        p3.setLayout(new BorderLayout());
        data = new List();
        data.add("No Results");
        p3.add("North", new Label("Results:"));
        p3.add("Center", data);

        Panel    p4 = new Panel();

        task = new Choice();
        task.add("Exit");             // TASK_EXIT
        task.add("New");              // TASK_NEW
        task.add("Close");            // TASK_CLOSE
        task.add("Execute");          // TASK_EXECUTE
        task.add("Prev");             // TASK_PREV
        task.add("Next");             // TASK_NEXT
        task.add("Config");           // TASK_CONFIGURE
        task.add("RS to PalmDB");     // TASK_TOPALMDB
        task.add("Query PalmDB");     // TASK_FROMPALMDB
        task.add("Set AutoCommit");   // TASK_SETAUTOCOMMIT
        task.add("Set Isolation");    // TASK_SETISOLATION
        task.add("Commit");           // TASK_COMMIT
        task.add("Rollback");         // TASK_ROLLBACK
        task.select(TASK_EXECUTE);    // Start off here.
        p4.add("West", task);

        Button b = new Button("Go");
        b.addActionListener(this);
        p4.add("East", b);

        Panel prest = new Panel();
        prest.setLayout(new BorderLayout());
        prest.add("North", p2);
        prest.add("Center", p3);
        Panel pall = new Panel();
        pall.setLayout(new BorderLayout());
        pall.add("North", p1);
        pall.add("Center", prest);

        setLayout(new BorderLayout());
        add("Center", pall);
        add("South", p4);
    }

    /**
     * Do a task based on whichever task is
     * currently selected in the task list.
     */
    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource() instanceof MultiChoiceDialog)
        {
            String   cmd = e.getActionCommand();
            processExtendedCommand(cmd);
            return;
        }

        switch (task.getSelectedIndex())
        {
        case TASK_EXIT:
            System.exit(0);
            break;
        case TASK_NEW:
            JdbcPanel.this.goNewItems();
            break;
        case TASK_PREV:
            JdbcPanel.this.goPrevRow();
            break;
        case TASK_NEXT:
            JdbcPanel.this.goNextRow();
            break;
        case TASK_EXECUTE:
            if (connObject == null || stmtObject == null)
                JdbcPanel.this.goNewItems();

            JdbcPanel.this.goExecute();
            break;
        case TASK_CONFIG:
            JdbcPanel.this.goConfigure();
            break;
        case TASK_CLOSE:
            JdbcPanel.this.goClose();
            break;
        case TASK_TOPALMDB:
            if (connObject == null || stmtObject == null)
                JdbcPanel.this.goNewItems();

            JdbcPanel.this.goResultsToPalmDB();
            break;
        case TASK_FROMPALMDB:
            JdbcPanel.this.goQueryFromPalmDB();
            break;
        case TASK_SETAUTOCOMMIT:
            JdbcPanel.this.goSetAutocommit();
            break;
        case TASK_SETISOLATION:
            JdbcPanel.this.goSetIsolation();
            break;
        case TASK_COMMIT:
            JdbcPanel.this.goTransact(true);
            break;
        case TASK_ROLLBACK:
            JdbcPanel.this.goTransact(false);
            break;

        default : 
        {
                Dialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Error", "Task not implemented");
                dialog.show();
                dialog = null;
            }
        }
    }

    public void processExtendedCommand(String cmd)
    {
        try
        {
            if (cmd.equals("true"))
            {
                connObject.setAutoCommit(true);
                return;
            }
            if (cmd.equals("false"))
            {
                connObject.setAutoCommit(false);
                return;
            }
            if (cmd.equals("read uncommitted"))
            {
                connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_UNCOMMITTED);
                return;
            }
            if (cmd.equals("read committed"))
            {
                connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_COMMITTED);
                return;
            }
            if (cmd.equals("repeatable read"))
            {
                connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_REPEATABLE_READ);
                return;
            }
            if (cmd.equals("serializable"))
            {
                connObject.setTransactionIsolation(java.sql.Connection.TRANSACTION_SERIALIZABLE);
                return;
            }
            throw new IllegalArgumentException("Invalid command: " + cmd);
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
            return;
        }
    }

    /**
     * Perform commit or rollback processing.
     */
    public void goTransact(boolean commit)
    {
        if (connObject == null)
        {
            FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame,
                                                       "Skip",
                                                       "Connection not allocated");
            dialog.show();
            dialog = null;
            return;
        }
        try
        {
            if (commit)
                connObject.commit();
            else
                connObject.rollback();
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }

    /**
     * Prompt the user for setting the autocommit value
     * Real work handled by the actionPerformed method
     * calling processExtendedCommand().
     */
    public void goSetAutocommit()
    {
        if (connObject == null)
        {
            FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame,
                                                       "Skip",
                                                       "Connection not allocated");
            dialog.show();
            dialog = null;
            return;
        }
        try
        {
            String currentValue;
            if (connObject.getAutoCommit())
                currentValue = "Now: true";
            else
                currentValue = "Now: false";

            Dialog dialog = new MultiChoiceDialog(JdbcDemo.mainFrame,
                                                  "Set Autocommit",
                                                  currentValue,
                                                  new String[]{ "true", "false"},
                                                  this);
            dialog.show();
            dialog = null;
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }

    /**
     * Prompt the user for setting the isolation level,
     * real work handled by the actionPerformed() method
     * calling processExtendedCommand().
     */
    public void goSetIsolation()
    {
        if (connObject == null)
        {
            FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame,
                                                       "Skip",
                                                       "Connection not allocated");
            dialog.show();
            dialog = null;
            return;
        }
        try
        {
            int   level = connObject.getTransactionIsolation();
            String currentLevel;
            switch (level)
            {
            case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
                currentLevel = "Now: read uncommitted";
                break;
            case java.sql.Connection.TRANSACTION_READ_COMMITTED:
                currentLevel = "Now: read committed";
                break;
            case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
                currentLevel = "Now: repeatable read";
                break;
            case java.sql.Connection.TRANSACTION_SERIALIZABLE:
                currentLevel = "Now: serializable";
                break;
            default : {
                    currentLevel = "error";
                }
            }
            Dialog dialog = new MultiChoiceDialog(JdbcDemo.mainFrame, 
                                                  "Set Isolation Level", 
                                                  currentLevel, 
                                                  new String[]{ "read uncommitted",
                                                                "read committed",
                                                                "repeatable read",
                                                                "serializable"}, 
                                                  this);
            dialog.show();
            dialog = null;
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }

    /**
     * Create a new connection or statement.
     * Only one connection and statement is currently
     * supported.
     */
    public void goNewItems()
    {
        if (connObject != null || stmtObject != null)
        {
            FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame,
                                                       "Skip",
                                                       "Conn/Stmt already allocated");
            dialog.show();
            dialog = null;
        }
        if (connObject == null)
        {
            try
            {
                connObject = DriverManager.getConnection(url);
                //connection.setText(Integer.toString(((JdbcMeConnection)connObject).getId()));
                connection.repaint();
            }
            catch (Exception e)
            {
                JdbcDemo.mainFrame.exceptionFeedback(e);
                return;
            }
        }
        if (stmtObject == null)
        {
            try
            {
                try
                {
                    stmtObject = connObject.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                                            ResultSet.CONCUR_READ_ONLY);
                }
                catch (Exception e)
                {
                    // Try again...  DB2 NT version 6.1 doesn't support
                    // Scollable result sets, so we'll assume other
                    // JDBC 2.0 databases don't either. We'll attempt
                    // to create another.
                    try
                    {
                        stmtObject = connObject.createStatement();
                    }
                    catch (Exception ex)
                    {
                        // If the second try failed, rethrow the
                        // first exception. Its probably
                        // a more meaninful error.
                        throw e;
                    }
                    FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame,
                                                               "2nd try worked",
                                                               "Non-scrollable result set");
                    dialog.show();
                    dialog = null;
                }
                
                statement.repaint();
            }
            catch (Exception e)
            {
                JdbcDemo.mainFrame.exceptionFeedback(e);
                return;
            }
        }
    }


    /**
     *  Close the statement and connection.
     **/
    public void goClose()
    {
        // Close the statement.
        if (stmtObject != null)
        {
            if (rs != null)
            {
                try
                {
                    rs.close();
                }
                catch (Exception e)
                {
                }
                rs = null;
                rsmd = null;
            }
            try
            {
                stmtObject.close();
            }
            catch (Exception e)
            {
            }
            stmtObject = null;
            statement.setText("None");
            statement.repaint();
        }

        // Clost the connection.
        if (connObject != null)
        {
            try
            {
                connObject.close();
            }
            catch (Exception e)
            {
            }
            connObject = null;
            connection.setText("None");
            connection.repaint();
        }
        data.removeAll();
        data.add("No Results");
        data.repaint();
        sql.repaint();
        return;
    }

    /**
     * display the configuration dialog.
     **/
    public void goConfigure()
    {
        // Note there is no model dialog support in KAWT, this only
        // works because the data to be changed (url) is set before
        // this dialog is used, and the user cannot access the
        // main frame while this is up on the palm (i.e. all dialogs
        // in Kawt are modal).
        ConfigurationDialog dialog = new ConfigurationDialog(JdbcDemo.mainFrame); 
        dialog.show();
        dialog = null;
    }

    /**
     *  Execute the specified query.
     **/
    public void goExecute()
    {
        // Get the currently selected statement.
        try
        {
            if (rs != null)
                rs.close();

            rs = null;
            rsmd = null;
            boolean results = stmtObject.execute(sql.getText());
            if (results)
            {
                rs = stmtObject.getResultSet();
                rsmd = rs.getMetaData();
                // Show the first row
                goNextRow();
            }
            else
            {
                data.removeAll();
                data.add(stmtObject.getUpdateCount() + " rows updated");
                data.repaint();
            }
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }


    /**
     *  Move to the next row in the result set.
     **/
    public void goNextRow()
    {
        try
        {
            if (rs == null || rsmd == null)
                return;

            int   count = rsmd.getColumnCount();
            int   i;
            data.removeAll();
            if (!rs.next())
                data.add("End of data");
            else
            {
                for (i=1; i>=count; ++i)
                {
                    data.add(rs.getString(i));
                }
            }
            data.repaint();
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }


    /** 
     *  Move to the previous row in the result set.
     **/
    public void goPrevRow()
    {
        try
        {
            if (rs == null || rsmd == null)
                return;

            int   count = rsmd.getColumnCount();
            int   i;
            data.removeAll();
            if (!rs.previous())
                data.add("Start of data");
            else
            {
                for (i=1; i<=count; ++i)
                {
                    data.add(rs.getString(i));
                }
            }
            data.repaint();
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }

    /**
     *  Perform a query and store the results in the local devices database
     **/
    public void goResultsToPalmDB()
    {
        try
        {
            if (stmtObject == null)
            {
                FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "Skip", "No Statement");
                dialog.show();
                dialog = null;
                return;
            }

            boolean results =
               ((JdbcMeStatement)stmtObject).executeToOfflineData(sql.getText(),
                                                                  "JdbcResultSet",
                                                                  DemoConstants.dbCreator,
                                                                  DemoConstants.dbType);
            if (!results)
            {
                FeedbackDialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, "No Data", "Not a query");
                dialog.show();
                dialog = null;
                return;
            }
            data.removeAll();
            data.add("Updated Palm DB 'JdbcResultSet'");
            data.repaint();
        }
        catch (Exception e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }


    /**
     *  Perform a query from the database that resides on the palm device.
     **/
    public void goQueryFromPalmDB()
    {
        try
        {
            if (rs != null)
            {
                rs.close();
                rs = null;
            }
            rs = new JdbcMeOfflineResultSet ("JdbcResultSet",
                                             DemoConstants.dbCreator,
                                             DemoConstants.dbType);
            rsmd = rs.getMetaData();
            // If we want to debug some output, this
            // method can be used to dump the contents
            // of the PalmDB represented by the result set
            // (Uses System.out so its mostly useful in
            // the Palm emulator when debugging your
            // applications.
            // ((JdbcMeOfflineResultSet)rs).dumpDB(true);

            // show the first row.
            goNextRow();
        }
        catch (SQLException e)
        {
            JdbcDemo.mainFrame.exceptionFeedback(e);
        }
    }
}

public class JdbcDemo extends Frame
{
    /** An ActionListener that ends the application. Only
     * one is required, and can be reused
     */
    private static ActionListener    exitActionListener = null;
    /**
     * The main application in this process.
     */
    static         JdbcDemo mainFrame = null;

    JdbcPanel      jdbcPanel = null;

    public static ActionListener getExitActionListener()
    {
        if (exitActionListener == null)
        {
            exitActionListener = new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    System.exit(0);
                }
            };
        }
        return exitActionListener;
    }

    /**
     *  Demo Constructor
     **/
    public JdbcDemo()
    {
        super("Jdbc Demo");
        setLayout(new BorderLayout());

        jdbcPanel = new JdbcPanel();
        add("Center", jdbcPanel);

        addWindowListener(new WindowAdapter()
         {
             public void windowClosing(WindowEvent e)
             {
                 System.exit(0);
             }
         });
        setSize(200,300);
        pack();
    }

    public void exceptionFeedback(Exception e)
    {
        Dialog dialog = new FeedbackDialog(JdbcDemo.mainFrame, e);
        dialog.show();
        dialog = null;
    }

    /**
     * Main method.
     **/
    public static void main(String args[])
    {
        try
        {
            mainFrame = new JdbcDemo();
            mainFrame.show();
            mainFrame.jdbcPanel.goConfigure();
        }
        catch (Exception e)
        {
            System.exit(1);
        }
    }
}