Oracle9i Application Server Wireless Edition Developer's Guide
Release 1.1

Part Number A86700-01

Library

Solution Area

Contents

Index

Go to previous page Go to next page

7
Using the Data Model API

This document describes the Data Model API. Each section of this document presents a different topic. These sections include:

7.1 Overview

To support interaction with persistent objects programmatically, the Wireless Edition Data Model API provides a set of Java interfaces that constitute a high-level interface to the underlying Wireless Edition Data Model. By implementing the Java interfaces in the Data Model API, you can create, delete, modify, and query Wireless Edition persistent objects.

The intended users of the public interfaces in the Data Model API are developers of services, adapters, and transformers. Developers can implement the interfaces in the Data Model API to develop stand-alone applications which manipulate persistent objects. Developers can also implement the interfaces from their customized Java adapters or Java Server Pages (JSP).

Although these interfaces will preserve the data integrity for the trusted developers, these interfaces will not enforce any security on who can do what. There is no enforcement of authentication and authorization policies. Developers should apply extreme caution when developing services using the interfaces in the Data Model API, and should take appropriate measures to prevent any undesired side effects when these services are invoked by the end users.

7.2 Class Hierarchy

The following sections describe the interfaces within the class hierarchy in the Data Model API. These interfaces are contained in the oracle.panama.model package. For a sample application that implements some of the interfaces, see Section 7.3, "Sample Adapter that Uses the Data Model API".

7.2.1 ModelObject

The ModelObject is the root interface for managing all of the "generic" aspects of a persistent object. It resides in the oracle.panama.model package. The figure below illustrates the structural relationships among all of the interfaces within the oracle.panama.model package.

Figure 7-1 The Data Model API Class Hierarchy


Text description of modclass.gif follows.
Text description of the illustration modclass.gif

The subinterfaces in the ModelObject class hierarchy are all persistent objects. These subinterfaces are (in alphabetical order):

The following sections describe each subinterface.

7.2.1.1 Adapter

Adapter extends the ModelObject root interface. Adapter is the container for the RuntimeAdapter. It is the interface that is to be implemented by all adapters. It inherits methods from the interface oracle.panama.model.ModelObject.

7.2.1.2 AlertAddress

AlertAddress extends the ModelObject root interface. An AlertAddress is the device-specific address, such as a phone or an email address.

For example, an AlertAddress can be a phone number of the logical device SMS or a the same phone number of the logical device WAP. The AlertAddress information is used for sending asynchronous Alert results to an address, or to authenticate a user from an incoming request.

AlertAddress inherits methods from the interface oracle.panama.model.ModelObject.

7.2.1.3 Device

Device extends the ModelObject root interface. A Device is the definition of the target logical device protocol. It can, for example, be WML11 for WML specific devices, but also WML_Nokia7110 for more Nokia specific WML. Other examples are SMS and EMAIL.

Device inherits methods from the interface oracle.panama.model.ModelObject.

Observe that the same physical device can support multiple logical devices; a phone, for example, can support both the SMS and the WAP protocols.

7.2.1.4 Group

Group extends the ModelObject root interface. A Group is a collection of users. It is used to publish specific services to the group members. A user can access those services that are accessible to the group to which the user belongs.

Group inherits methods from the interface oracle.panama.model.ModelObject.

7.2.1.5 LocationMark

LocationMark, which is in the oracle.panama.model package, extends the ModelObject root interface. It also extends the Location class. It is a persistent object that represents the named and geocoded correct physical address.

LocationMark inherits methods from the interface oracle.panama.model.ModelObject.

7.2.1.6 MetaLocator

MetaLocator, which is in the oracle.panama.model package, extends the java.lang.Object interface. The MetaLocator is used to look up factories.

7.2.1.7 ModelFactory

ModelFactory, which is in the oracle.panama.model package, provides the entry point to create model objects.

7.2.1.8 ModelServices

ModelServices, which is in the oracle.panama.model package, provides the entry point to find model objects.

7.2.1.9 Service

Service extends the ModelObject root interface. Service is an "abstract" interface and handles all generic aspects of a service.

It inherits methods from the interface oracle.panama.model.ModelObject.

It contains the following subinterfaces:

7.2.1.10 Transformer

Transformer extends the ModelObject root interface. Transformer is the abstract base interface for all transformation sub-classes. It acts as a bridge between the real transformation implementation (Java or XSL) and the clients.

It inherits methods from the interface oracle.panama.model.ModelObject.

It has the following subinterfaces:

7.2.1.11 User

The User interface extends the root interface ModelObject. The User interface represents the identity of the current actual user.

Each actual user has its own home folder. The actual user can access those services that are accessible to the group to which the user belongs.

The implementation of the User interface may access another provisioning system to manage the information about the current actual user.

It inherits methods from the interface oracle.panama.model.ModelObject.

7.3 Sample Adapter that Uses the Data Model API

The following sample adapter illustrates how you can create new objects by implementing the interfaces in the Data Model API and by using the methods associated with those interfaces. The purpose of the sample is not to show how to create an adapter, but rather how to create a new object (in this case, a new user).

The main focus in this sample adapter is on demonstrating the usage of the methods to create, search for, and finally delete an object.

The complete listing of the sample code is in Section 7.3.1, "Sample Adapter Code". The numbers that appear in brackets next to a line of code in the listing are referenced in the discussion to correlate the explanation with the corresponding lines in the code itself.

This is how you do it:

MetaLocator metaLocator = MetaLocator.getInstance(); 
modelFactory = metaLocator.getModelFactory();
modelServices = metaLocator.getModelServices();

The MetaLocator interface is used to lookup the ModelFactory and ModelServices. The getInstance() method in this interface gets the single instance of this MetaLocator. The method returns the single instance of the MetaLocator. The methods getModelFactory and getModelServices look up the ModelFactory and the ModelServices.

Typically, to create a new object, you should check first if the object already exists. To look up any object, you use the ModelServices interface and the method lookupX(java.lang.String name), where X is the class name of the object. In this sample adapter, to create a new user (the code section for creating a new user starts in reference [2]), you first look up the user by using the lookupUser(userName) method in the ModelServices interface (reference [3]), as the following line of code shows:

modelServices.lookupUser(userName); 

This is the first step in creating any new persistent object in the Data Model.

The lookupUser(userName) method searches for the user by name and, if the user name is found, returns the name of the user. If the user name cannot be found, the method throws a PanamaRuntimeException.

Next, you check if the group to which the user belongs (or should belong) already exists (reference [4]). Following the procedure for looking up any object, you use the ModelServices interface and the lookupGroup(groupName) method to look up a group by name. If the group is found, the method returns the name of the group. If the group is not found, the method throws a PanamaRuntimeException.

After checking if the user and the group already exist, you create the new user object (reference [5] to reference [6]):

     user = modelFactory.createUser(userName, groups); 
} else {
     user = modelFactory.createUser(userName);
}
user.setPassword(userPassword);
user.setEnabled(true); 

You must save the newly created user. Each newly created object must be saved after it is created (reference [7]):

modelFactory.save();

This saves your work. Save applies to all created or modified objects in the current thread. The objects are saved to the persistent storage and the transaction is committed. The method throws PanamaException when it is unable to save the work.

To search for an object after creating it, use the searchElement method with the criteria specified in the form of the parameters rootElement, tagname, atrr1, value1. The method returns Element. In the sample, to search for the user object, you use the following method (reference [8]):

private void searchUser(Document owner, Element container, Arguments 
args)

To get a set of user names (for example, all the names that start with the letter "B"), you work with enumeration. Use ResultSetEnumeration (reference [9]) and the method findUsers (reference [10]). The method findUsers pluralizes users because it is using a template. This is used for getting a set of names; it will return several names. See also references [11] and [12] in the listing of the complete sample code.

You should close the ResultSetEnumeration (reference [13]). It is associated with the database cursor. If you do not close it, you leave a database cursor open.

To delete an object, you use the deleteElement method and the code that matches the code section in reference [14]. In this case, to delete the user you use deleteUser and the specified criteria as the parameters. Note references [15] and [16]. The user name must be exact, because if it is a template, the method will throw an exception.

7.3.1 Sample Adapter Code

/*
 * $Copyright:
 *             Copyright (c) 2001 Oracle Corporation all rights reserved
 * $
 */

package model;

import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import oracle.panama.Arguments;
import oracle.panama.ArgumentType;
import oracle.panama.InputArgument;
import oracle.panama.OutputArguments;
import oracle.panama.PanamaRuntimeException;
import oracle.panama.PAPrimitive;
import oracle.panama.adapter.AdapterException;
import oracle.panama.adapter.RuntimeAdapter;
import oracle.panama.adapter.RuntimeAdapterHelper;
import oracle.panama.model.Group;
import oracle.panama.model.MetaLocator;
import oracle.panama.model.ModelFactory;
import oracle.panama.model.ModelServices;
import oracle.panama.model.ResultSetEnumeration;
import oracle.panama.model.User;
import oracle.panama.rt.Request;
import oracle.panama.rt.ServiceContext;

/**
 * This is a sample adapter demonstrating the usage of the model API.
 *
 * @since     Oracle9i Aplication Server Wireless Edition
 * @version   1.0
 */
public class SampleModelAdapter implements RuntimeAdapter {

    /** Command variable */
    private static final String COMMAND     = "PAsection";
    /** Commands */
    /** Add new user */
    private static final String CREATE_USER = "CreateUser";
    /** Remove a user */
    private static final String DELETE_USER = "DeleteUser";
    /** Search for a user */
    private static final String SEARCH_USER = "SearchUser";
    /** The list of all top level commands */
    private static final String[] COMMANDS  =
        new String[] {CREATE_USER, SEARCH_USER};

    private static final String USER_NAME         = "Name";
    private static final String USER_GROUP        = "Group";
    private static final String USER_PASSWORD     = "Password";
    private static final String[] CREATE_ARGUMENTS  = new String[] {
        USER_NAME, USER_GROUP, USER_PASSWORD};
    private static final String[] SEARCH_ARGUMENTS = new String[] {
        USER_NAME};

    private boolean initialized;
    private Arguments initArguments;
    private Arguments inputArguments;
    private OutputArguments outputArguments;
    
    private ModelFactory modelFactory;
    private ModelServices modelServices;
    
    public SampleModelAdapter() {
        initialized = false;
        MetaLocator metaLocator = MetaLocator.getInstance();      [1]
        modelFactory = metaLocator.getModelFactory();
        modelServices = metaLocator.getModelServices();
    }

    /**
     * Get the init arguments
     * @return  init arguments
     */
    public Arguments getInitArguments() throws AdapterException {
        if (initArguments == null) {
            synchronized (this) {
                if (initArguments == null) {
                    initArguments = RuntimeAdapterHelper.createArguments();
                }
            }
        }
        return initArguments;
    }

    /**
     * Get the input Arguments
     * @return    input arguments
     */
    public Arguments getInputArguments() throws AdapterException {
        checkState();
        return inputArguments;
    }

    /**
     * Get the output Arguments
     * @return    an array of output arguments
     */
    public OutputArguments getOutputArguments() throws AdapterException {
        checkState();
        return outputArguments;
    }

    /**
     * Initialize the adapter using the information from the init arguments.
     * @param args    init arguments
     */
    public void init(Arguments args) throws AdapterException {
        if (initialized == false) {
            synchronized (this) {
                if (initialized == false) {
                    initialized = true;
                    // Create Input Arguments
                    inputArguments = RuntimeAdapterHelper.createArguments();

                    InputArgument arg = inputArguments.createInput(COMMAND);
                    arg.setComment("Command to Adapter. Either 'CreateUser' or 


'SearchUser'");
                    arg.setType(ArgumentType.ENUM);
                    arg.setOptions(COMMANDS);

                    arg = inputArguments.createInput(USER_NAME);
                    arg.setComment("User Name");
                    arg.setType(ArgumentType.SINGLE_LINE);

                    arg = inputArguments.createInput(USER_GROUP);
                    arg.setComment("User Group");
                    arg.setType(ArgumentType.ENUM);
                    arg.setOptions(getGroupNames());

                    arg = inputArguments.createInput(USER_PASSWORD);
                    arg.setComment("User Password");
                    arg.setType(ArgumentType.SINGLE_LINE);
                    
                    // Create Output Arguments
                    outputArguments = 
RuntimeAdapterHelper.createOutputArguments();
                }
            }
        }
    }

    /**
     * Invoke the adapter using the input and output parameters in the
     * service context.
     * @param context   the context that contains input parameters
     */
    public Element invoke(ServiceContext context) throws AdapterException {
        checkState();
        Document doc = context.getXMLDocument();
        Element simpleResult = PAPrimitive.createSimpleResult(doc, null);
        Element simpleContainer = PAPrimitive.createSimpleContainer(doc, null);
        simpleResult.appendChild(simpleContainer);
        
        Arguments args = context.getInputArguments();
        String command = args.getInputValue(COMMAND);
        if (command == null || command.length() == 0) {
            // Create the main menu
            createMenu(doc, simpleContainer, args);
        } else if (command.equals(CREATE_USER)) {
            // Create a new user
            createUser(context, doc, simpleContainer, args);
        } else if (command.equals(SEARCH_USER)) {
            searchUser(doc, simpleContainer, args);
        } else if (command.equals(DELETE_USER)) {
            deleteUser(doc, simpleContainer, args);
        } else {
            Element errMsg = simpleText(doc, "Unknown command", "Error");
        }
        return simpleResult;
    }

    /**
     * Destroy the provider.
     */
    public void destroy() {}

//
// Helper methods
//
    /**
     * Check if the state of this Adapter is all right.
     * @exception AdapterException when the state is illegal
     */
    private synchronized void checkState() throws AdapterException {
        if (!initialized) {
            throw new AdapterException("SampleModelAdapter is not initialized");
        }
    }
    
    /**
     * Find all group names
     * @return String[] with names
     */
    private String[] getGroupNames() throws AdapterException {
        String[] names;
        ResultSetEnumeration result = null;
        try {
            // Find all user groups - use a wildcard for the name expression
            result = modelServices.findGroups("*");
            Vector buffer = new Vector();
            while (result.hasMoreElements()) {
                Group group = (Group)result.next();
                String name = group.getName();
                buffer.addElement(name);
            }
            names = new String[buffer.size()];
            buffer.copyInto(names);
        } catch (PanamaRuntimeException ex) {
            throw new AdapterException(ex);
        } finally {
            if (result != null) {
                result.close();
                result = null;
            }
        }
        return names;
    }

    /**
     * Create a simple menu. <p>
     *
     * There are two choices. Create user or search for users.
     *
     * @param owner the owner document.
     * @param container   an output parameter for the menu.
     * @param args  the arguments.
     */
    private void createMenu(Document owner, Element container, Arguments args) {
        Element menu = PAPrimitive.createSimpleMenu(owner, "");
        container.appendChild(menu);
        String target = RuntimeAdapterHelper.getURLPAoidParameter(args);
        target = target + ((target.indexOf('?') == -1) ? "?" : "&");
        //create the menuitem with submenu
        for (int i = 0; i < COMMANDS.length; i++) {
            Element menuItem = PAPrimitive.createSimpleMenuItem(
                owner, COMMANDS[i],
                target + Request.SECTION + "=" + COMMANDS[i], false);
            menu.appendChild(menuItem);
        }
    }

    /**                                          [2]
     * Create a new user. <p> 
     *
     * The service request contains the parameters.
     *
     * @param context the ServiceContext
     * @param owner the owner document.
     * @param container    an element for the output result.
     * @param args    the service request holds the arguments for the user.
     */
    private void createUser(ServiceContext context, Document owner, Element 
container, 


Arguments args) {
        try {
            String[] missingArgs = getMissingCreateArguments(args);
            if (missingArgs == null || missingArgs.length == 0) {
                // There are no missing arguments - create the new user
                String userName = args.getInputValue(USER_NAME);
                String groupName = args.getInputValue(USER_GROUP);
                String userPassword = args.getInputValue(USER_PASSWORD);
                // First check if the user does not already exists
                try {
                    modelServices.lookupUser(userName);                  [3]
                    // If we are here the user must already exists
                    Element errTxt = simpleText(owner, "The user already             
exists", "Error");
                    container.appendChild(errTxt);
                    return;
                } catch (PanamaRuntimeException ignore) {}

                Group group = null;
                try {
                    // A PanamaRuntimeException will be thrown if the group is
                    // not found
                    group = modelServices.lookupGroup(groupName);         [4]
                } catch (PanamaRuntimeException ex) {
                    group = null;
                }
                User user;
                // NOTE: modelFactory.createUser() will automatically create a
                // home folder for the new user.
                if (group != null) {
                    Group[] groups = new Group[1];
                    groups[0] = group;
                    user = modelFactory.createUser(userName, groups);   [5]
                } else {
                    user = modelFactory.createUser(userName);
                }
                user.setPassword(userPassword);
                user.setEnabled(true);                                   [6]

                // Do not forget to save the newly created object
                modelFactory.save();                                      [7]

                Element successTxt = simpleText(owner, "User \"" + userName + 
"\" was 


created!", "Success");
                container.appendChild(successTxt);
            } else {
                //construct the target parameters
                String target = RuntimeAdapterHelper.getURLPAoidParameter(args);
                target = target.concat("&" + COMMAND + "=" + CREATE_USER);
                Element form = PAPrimitive.createSimpleForm(owner,
                    args.getInputValue(ServiceContext.INP_FIRST_SERVICE_NAME), 
target);
                container.appendChild(form);
                RuntimeAdapterHelper.createInputFields(form, missingArgs, args);
            }
        } catch (Exception ex) {
            Element errTxt = simpleText(owner, ex.getMessage(), "Error");
            container.appendChild(errTxt);
        }
    }

    /**
     * Check that arg has an value for all valid attributes.
     *
     * @param arg Arguments which holds the parameters
     * @exception Exception when required input parameters are missing
     */
    private String[] getMissingCreateArguments(Arguments args) {
        String[] missingArgs;
        Vector buffer = new Vector();
        for (int i = 0; i < CREATE_ARGUMENTS.length; i++) {
            String argValue = args.getInputValue(CREATE_ARGUMENTS[i]);
            if (argValue == null || argValue.length() == 0) {
                buffer.addElement(CREATE_ARGUMENTS[i]);
            }
        }
        missingArgs = new String[buffer.size()];
        buffer.copyInto(missingArgs);
        return missingArgs;
    }

    /**
     * Search for users. <p>
     *
     * The service request contains the parameters.
     *
     * @param owner the owner document.
     * @param container    an element for the output result.
     * @param args    the service request holds the arguments for the user.
     */
    private void searchUser(Document owner, Element container, Arguments 
args) { [8] try { String[] missingArgs = getMissingSearchArguments(args); if (missingArgs == null || missingArgs.length == 0) { // There are no missing arguments - search for the user String userName = args.getInputValue(USER_NAME); // Create the table Element table = owner.createElement(PAPrimitive.TAG_ SIMPLETABLE); container.appendChild(table); Element tableHeader = owner.createElement(PAPrimitive.TAG_SIMPLETABLEHEADER); table.appendChild(tableHeader); Element headerCol = owner.createElement(PAPrimitive.TAG_ SIMPLECOL); headerCol.appendChild(owner.createTextNode("Name")); tableHeader.appendChild(headerCol); headerCol = owner.createElement(PAPrimitive.TAG_SIMPLECOL); headerCol.appendChild(owner.createTextNode("Delete?")); tableHeader.appendChild(headerCol); String target = RuntimeAdapterHelper.getURLPAoidParameter(args); target = target + ((target.indexOf('?') == -1) ? "?" : "&"); ResultSetEnumeration result = null; [9] try { result = modelServices.findUsers(userName); [10] // NOTE: A real adapter should not fetch all users at once. // Instead it should provide a "More..." button. // But this is not the goal of this example ;-) int count = 0; while (result.hasMoreElements() && count < 20) { [11] count++; User user = (User) result.next(); [12] Element row = owner.createElement(PAPrimitive.TAG_ SIMPLEROW); table.appendChild(row); Element col = owner.createElement(PAPrimitive.TAG_ SIMPLECOL); row.appendChild(col); String name = user.getName(); col.appendChild(owner.createTextNode(name)); col = owner.createElement(PAPrimitive.TAG_SIMPLECOL); row.appendChild(col); Element delete = owner.createElement(PAPrimitive.TAG_ SIMPLEHREF); col.appendChild(delete); delete.appendChild(owner.createTextNode("delete")); delete.setAttribute(PAPrimitive.ATTR_TARGET, target + Request.SECTION + "=" + DELETE_USER + "&" + USER_NAME + "=" + name); } } catch (PanamaRuntimeException ex) { } finally { if (result != null) { result.close(); [13] result = null; } } } else { //construct the target parameters String target = RuntimeAdapterHelper.getURLPAoidParameter(args); target = target.concat("&" + COMMAND + "=" + SEARCH_USER); Element form = PAPrimitive.createSimpleForm(owner, args.getInputValue(ServiceContext.INP_FIRST_SERVICE_NAME), target); container.appendChild(form); RuntimeAdapterHelper.createInputFields(form, missingArgs, args); } } catch (Exception ex) { Element errTxt = simpleText(owner, ex.getMessage(), "Error"); container.appendChild(errTxt); } } /** * Check that arg has an value for all valid attributes. * * @param arg Arguments which holds the parameters * @exception Exception when required input parameters are missing */ private String[] getMissingSearchArguments(Arguments args) { String[] missingArgs; Vector buffer = new Vector(); for (int i = 0; i < SEARCH_ARGUMENTS.length; i++) { String argValue = args.getInputValue(SEARCH_ARGUMENTS[i]); if (argValue == null || argValue.length() == 0) { buffer.addElement(SEARCH_ARGUMENTS[i]); } } missingArgs = new String[buffer.size()]; buffer.copyInto(missingArgs); return missingArgs; } /** * Search for users. <p> * * The service request contains the parameters. * * @param owner the owner document. * @param container an element for the output result. * @param args the service request holds the arguments for the user. */ private void deleteUser(Document owner, Element container, Arguments
args) {[14] try { String userName = args.getInputValue(USER_NAME); if (userName != null && userName.length() > 0) { User user = modelServices.lookupUser(userName); [15] user.delete(); [16] // Do not forget to save the changes modelFactory.save(); Element successTxt = simpleText(owner, "User \"" + userName + "\" was removed!", "Success"); container.appendChild(successTxt); } else { //construct the target parameters String target = RuntimeAdapterHelper.getURLPAoidParameter(args); target = target.concat("&" + COMMAND + "=" + DELETE_USER); Element form = PAPrimitive.createSimpleForm(owner, args.getInputValue(ServiceContext.INP_FIRST_SERVICE_NAME), target); container.appendChild(form); String[] missingArgs = new String[1]; missingArgs[0] = userName; RuntimeAdapterHelper.createInputFields(form, missingArgs, args); } } catch (Exception ex) { Element errTxt = simpleText(owner, ex.getMessage(), "Error"); container.appendChild(errTxt); } } /** * Add a single line text * @param text * @return Element with the text */ private Element simpleText(Document owner, String text, String head) { Element simpleText = PAPrimitive.createSimpleText(owner); simpleText.appendChild(PAPrimitive.createSimpleTextItem(owner, head, text)); return simpleText; } }

Go to previous page Go to next page
Oracle
Copyright © 2001 Oracle Corporation.

All Rights Reserved.

Library

Solution Area

Contents

Index