Thursday, December 31, 2009

Examining View Object Attributes in Oracle ADF 11g

In Oracle ADF 11g, you use entity objects to represent tables or UML entities and to implement business rules. And you use view objects to retrieve data from a data source and to expose and shape the data for clients. Using an Entity Fascade design pattern, view objects provides a restricted view of data and behavior of one or more entity objects.
In this article, we'll take a look at different kinds of view object attributes you can create in Oracle ADF.

Different View Object Attributes

View objects provide the means to retrieve data from a data source. In the majority of cases, the data source will be a database and the mechanism to retrieve data is the SQL query. At runtime each view object manages its own query result set. If you connect two or more view objects in master-detail relationships, that coordination is handled automatically. While defining a view object, you can link any of its query columns to underlying entity objects.
The easiest way to create view objects is to launch the Create Business Components from Tables Wizard, which allows you to create multiple entity objects, multiple view objects and other Business Components from database tables.

However, sometimes you need to add new columns to your tables or UML entities or you need to create calculated columns, then you must follow the steps described in this article to create new view object attributes incrementally. But, our focus here is to examine different kinds of view object attributes you can set up in Oracle ADF.

The classification of a view object attribute is mainly based on whether you would map it to a column/SQL or not.

If you map it to a column or SQL, you need to define a query column which either link it to an underlying entity attribute or provide it a SQL expression. View object attributes that are mapped to columns or SQL expressions will be included in the SQL SELECT list.
If your view object attribute is not mapped to a column or SQL, it's a transient attribute. A transient attribute can have a default value which could be either a literal or a Groovy expression.

How to Create a New View Object Attribute

  1. In the Application Navigator, double-click the view object for which you want to add a new attribute.
  2. In the overview editor, click the Attributes navigation tab and click the Create new attribute button (i.e., "+"). Note that Create new attribute button provides a dropdown list with two options:
    • New Attribute...
    • Add New Attribute from Entity...


Entity-Based Attribute

The simplest way to create a new view object attribute is to link it to an entity attribute (i.e., selecting "Add New Attribute from Entity..."). After creating it, its definition will look like this:

As you can see it, "Mapped Column or SQL" is checked and an alias (i.e., "ENAME") is provided in "Query Column." Also notice that it includes an Entity Attribute navigation tab. In this case, view object attribute properties are inherited from underlying entity object.

Transient Attribute

If you choose "New Attribute... " option, it will bring up New View Object Attribute wizard. To define a transient attribute, you can provide its default value using either a literal or a Groovy expression. In the following example, we set ValueUsingVORowFunction attribute's default value to be a Groovy expression:
  • adf.object.myFunctionAtVORowLevel(Sal)

Because a transient attribute is not mapped to a column or SQL, you need to uncheck "Mapped to Column or SQL" (notice that Query Column is grayed out after unchecking). adf.obj can be used to reference the object on which the expression is being applied. Depending on the context in which the Groovy script is applied, adf.obj could point to different objects. The context here is an instance of the view row implementation class (i.e., EmpViewRowImpl.java). Through this object, you can reference custom methods of the custom view row implementation class.

If you want to reference custom methods of the custom view implementation class (i.e., EmpViewImpl.java) from the Groovy script, you specify this instead:

  • adf.object.viewObject.myFunctionAtVOLevel(Sal)
To learn more on Groovy expression, see references in the More Readings section. For the sample implementation of transient attributes, you can download it from Steve Muench's blog here.

SQL-Calculated Attribute

To define SQL based calculated attribute, you also bring up New View Object Attribute wizard by choosing "New Attribute..." In the following example, it shows a SQL-calculated attribute which computes total number of tests in a detail table that is linked to the mater table that this attribute is defined in:
SQL-calculated attribute is mapped to SQL. Therefore, you need to check "Mapped to Column or SQL." Also, you need to provide a SQL expression and its type:
  • select count(*) from xtm_sel_tests xst where xst.test_run_id = TestRunEO.test_run_id

Note that TotalTests is defined in TestRunVO (i.e., a View Object) and TestVO (detail object) is linked to TestRunVO (master object) via a view link. Here detail table is named xtm_sel_tests and referenced in the expression. A Where clause which filters the result set with entries matching the test_run_id value of master table row is specified.
The query column you specified corresponds to an inner query which is embedded in the outer query. The final query generated by Oracle ADF looks like this:
SELECT TestRunEO.TEST_RUN_ID,
        ProductEO.PRODUCT_NAME,
        ProductEO.PRODUCT_ID,
        TestRunEO.START_TIME,
        TestRunEO.END_TIME,
        TestRunEO.TEST_URL,
   (select count(*) from xtm_sel_tests xst  where
    xst.test_run_id = TestRunEO.test_run_id) AS TOTAL_TESTS
FROM XTM_SEL_TEST_RUNS TestRunEO, XTM_SEL_PRODUCTS ProductEO, XTM_SEL_TESTS TestEO
WHERE (TestRunEO.PRODUCT_ID = ProductEO.PRODUCT_ID) AND (TestRunEO.TEST_RUN_ID = TestEO.TEST_RUN_ID)
Note that, in this example, there is also a join between XTM_SEL_RPODUCTS and XTM_SEL_TEST_RUNS tables. If you specify something wrong (for example, changing TestRunEO.test to TestRunVO.test), you can find out the error using Oracle Business Component Browser:

More Readings

  1. Groovy
  2. Overview of Groovy Support
  3. Groovy Scripting Tips for ADF Business Components
  4. Introduction to Groovy Support in JDeveloper and Oracle ADF 11g
  5. Adding Calculated and Transient Attributes to a View Object
  6. Oracle/PLSQL: Subqueries

Thursday, December 17, 2009

Three SQL Modes in Oracle ADF

There are three SQL modes in Oracle ADF:
  1. Declarative SQL mode
  2. Normal SQL mode
  3. Expert SQL mode
where declarative SQL mode is a new addition in Oracle ADF 11g. The declarative SQL mode for view objects lets you create SQL-Independent view objects . You can define query filter predicates by using view object attribute names without having to type in SQL yourself. At runtime, Oracle ADF translates the logical filter expressions into the appropriate SQL automatically.

Declarative SQL mode selection is supported in JDeveloper as a setting that you can apply either to the entire data model project or to individual view objects that you create. After you enable declarative SQL mode, the basic procedure to create a view object is the same as you would follow to create any entity-based view object.

When you create a new view object, keep the default setting Updatable access through entity objects enabled to indicate that you want this view object to manage data with its base entity object. Any other choice for the data selection will disable declarative SQL mode in the Create View Object wizard.

The alternatives to declarative SQL mode are normal mode and expert mode. When you work in either of those modes, the view object definitions you create at design time always contain the entire SQL statement based on the SQL flavor required by your application module's defined database connection. Thus the capability of SQL independence does not apply to view objects that you create in normal or expert mode. For view objects created in normal or expert mode, you must edit the WHERE clause to filter the data as required.
In declarative SQL mode, the view object's metadata causes the ADF Business Components runtime to generate the SQL query statements as follows:
  • Generates SELECT and FROM lists based on the rendered web page's databound UI components' usage of one or more entity objects' attributes
  • Optionally, generates a WHERE clause based on a view criteria that you add to the view object definition
  • Optionally, generates an ORDERBY clause based on a sort criteria that you add to the view object definition.
  • Optionally, augments the WHERE clause to support table joins based on named view criteria that you add to the view object definition
  • Optionally, augments the WHERE clause to support master-detail view filtering based on a view criteria that you add to either the source or destination of a view link definition

Enable Declarative SQL Mode Globally

You can enable declarative SQL mode as a global preference so that it is the Create View Object wizard's default mode. If you did not select Enable declarative SQL mode for new objects, in the Preferences dialog, the wizard displays the default query mode, Normal.
Typically, when you define a declarative SQL mode view object, the attributes that get queried at runtime will be determined by the requirements of the databound UI component as it is rendered in the web page. This is the runtime-generation capability that makes view objects independent of the design time database's SQL flavor. However, you may also need to execute the view object programmatically without exposing it to an ADF data binding in the UI. In this case, you can enable the Include all attributes in runtime-generated query option to ensure that a programmatically executed view object has access to all of the entity attributes.

To enable both options (i..e, "Enable declarative SQL mode for new objects" and "Include all attributes in runtime-generated query") for the entire data model project. Go to:

  • Tools > Preferences > Business Components > View Objects

Enable Declarative SQL Mode per View Object

To enable Declarative SQL Mode per view object, select the View Object you want to edit. Choose Query tab and click on edit icon (i.e., pencil). On Edit Query dialog, you can choose Declarative SQL Mode (vs. Normal or Expert Mode).

Comparisons of Three SQL Modes

  • Normal Mode
    • You can manually enter custom WHERE and ORDER BY clauses in a view object query. However, by default, the FROM clause and SELECT list are automatically derived. When you require full control over the SELECT or FROM clause in a query, you can enable expert mode.
    • The automatic cooperation of a view object with its underlying entity objects depends on correct attribute-mapping metadata saved in the XML component definition. This information relates the view object attributes to corresponding attributes from participating entity usages. JDeveloper maintains this attribute mapping information in a fully automatic way for normal entity-based view objects.
  • Expert Mode
    • In Expert Mode, you are given full control over the entire SQL statement. However, it provides limited Attribute Mapping Assistance.
    • When you enable expert mode, the read-only Generated Statement section of the Query page becomes a fully editable Query Statement text box, displaying the full SQL statement. Using this text box, you can change every aspect of the SQL query.
  • Declarative SQL Mode
    • The view object in declarative SQL mode generates all SQL clauses entirely at runtime. The runtime-generated SQL statements will be determined by the SQL flavor specified in the Business Components page of the Project Properties dialog. Currently, the runtime supports SQL92 (ANSI) style and Oracle style flavors.
    • In declarative SQL mode, since the wizard and editor do not allow you to enter WHERE and ORDERBY clauses, you provide equivalent functionality by defining a view criteria and sort criteria respectively.
      • In declarative SQL mode, view criteria and sort criteria appear in the view object metadata definition and will be converted at runtime to their corresponding SQL clause.
      • In this mode, Query Clauses section changes to show declarative controls for the Where filter expression and the Order By attribute list.
    • Just as with normal mode view objects, you can link view objects that you create in declarative SQL mode to other view objects to form master-detail hierarchies of any complexity. However, in the case of view objects that you create in declarative SQL mode, you can further refine the view object results in the Source SQL or Destination SQL dialog for the view link by selecting a previously defined view criteria in the Create View Link wizard or the overview editor for the view link.

More Readings

Monday, November 30, 2009

Managed Beans in Oracle Fusion Web Applications

In JDeveloper, it helps you create different types of applications using various templates. One of these templates is the Fusion Web Application (ADF) template, which provides the correctly configured set of projects you need to create a web application that uses ADF Faces for the view, ADF Controller for the controller, and ADF Business Components for business services. When you create an application using this template, JDeveloper automatically creates the JSF and ADF configuration files needed for the application.


Oracle ADF framework is a container in the sense that it contains and manages the lifecycle and configuration of application objects. In the ADF framework, you can declare how each of your application objects should be created, how they should be configured, and how they should be associated with each other.

Managed Beans

A managed bean - sometimes simply referred to as an MBean - is a type of JavaBean, created with dependency injection and registered with the application using various configuration files. Managed Beans are particularly used in the Java Management Extensions technology. But with Java EE 6, the specification provides for a more detailed meaning of a managed bean.

The MBean represents a resource running in the Java virtual machine, such as an application or a Java EE technical service (transactional monitor, JDBC driver, etc.). They can be used for getting and setting applications configuration (pull), for collecting statistics (pull) (e.g. performance, resources usage, problems) and notifying events (push) (e.g. faults, state changes).

Backing beans are managed beans that contain logic and properties for UI components on a JSF page. In a standard JSF application, managed beans are registered in the faces-config.xml configuration file.

Three characteristics of a managed bean:
  • Name — way to reference bean in JSF application
  • Class — fully qualified class name of bean
  • Scope — how long the bean will live (i.e., application, session, request)

The managed-bean element can contain zero or more managed-property elements (see example below), each corresponding to a property defined in the bean class. These elements are used to initialize the values of the bean properties. If you don’t want a particular property initialized with a value when the bean is instantiated, do not include a managed-property definition for it in your application configuration resource file. Read this article to learn how to use the managed-property element.

Dependency Injection

The key benefit of Dependency Injection (DI) is loose coupling. When applying DI, objects are given their dependencies at creation time by some external entity that coordinates each object in the system. In other words, dependencies are injected into objects. So, DI means an inversion of responsibility with regard to how an object obtains references to collaborating objects. With DI, your application objects are freed from the burden of fetching their own dependencies and are able to focus on their tasks, trusting that their dependencies will be available when needed.

JavaServer Faces Managed Bean Facility

In this article, it discusses JavaServer Faces Managed Bean Facility which is provided similarly in the ADF framework. In summary, it provides the following functionalities:

  • Control of instantiation (constructor) and setter based injection of managed objects
  • Control when objects are loaded (i.e., eager instantiation vs. lazy loading)
  • Dependency Handling
  • Lifecycle Support
  • Configuration Support

Managed Beans in Fusion Web Applications

The controller used in ADF framework is ADF Controller (ADFc). It is an extension to JSF page flow engine. It allows the definition of managed beans with additional memory scopes[5]:
  • Application scope
  • Session scope
  • Page flow scope
  • Request scope
  • Backing bean scope
  • View scope
In a Fusion web application, managed beans can be registered in:
  • faces-config.xml file
  • adfc-config.xml file
  • task flow definition file[6]
However, registering managed beans within the faces-config.xml file is not recommended in a Fusion web application. Managed beans accessed within the task flow definition must be registered in that task flow's definition file. As a general rule for Fusion web applications, a bean that may be used in more than one page or task flow, or one that is used by pages within the main unbounded task flow (adfc-config), should be registered in the adfc-config.xml configuration file. A managed bean that will be used only by a specific task flow should be registered in that task flow's definition file. For example, a managed bean named updateUserInfoBean is registered in adfc-config.xml below:
<?xml version="1.0" encoding="windows-1252" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
 <view id="TestPage">
   <page>/TestPage.jspx</page>
 </view>
 <view id="Messages">
   <page>/ui/page/Messages.jspx</page>
 </view>
  <managed-bean>
    <managed-bean-name>updateUserInfoBean</managed-bean-name>
    <managed-bean-class>oracle.fodemo.storefront.account.view.managed.UpdateUserInfoBean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
      <property-name>allItemsIteratorName</property-name>
      <value>AvailableCategoriesShuttleListIterator</value>
    </managed-property>
    <managed-property>
      <property-name>allItemsValueAttrName</property-name>
      <value>CategoryId</value>
    </managed-property>    <managed-property>
      <property-name>allItemsDisplayAttrName</property-name>
      <value>CategoryName</value>
    </managed-property>
    <managed-property>
      <property-name>allItemsDescriptionAttrName</property-name>
      <value>CategoryDescription</value>
    </managed-property>
    <managed-property>
      <property-name>selectedValuesIteratorName</property-name>
      <value>CustomerInterestsIterator</value>
    </managed-property>
    <managed-property>
      <property-name>selectedValuesValueAttrName</property-name>
      <value>CategoryId</value>
    </managed-property>
    <managed-property>
      <property-name>addressTable</property-name>
      <property-class>oracle.adf.view.rich.component.rich.data.RichTable</property-class>
      <value></value>
    </managed-property>
  </managed-bean>
</adfc-config>

You can also find another managed bean example in this article. Finally, in a Fusion web application, you should use managed beans to store logic that is related to the UI rendering only. All application data and processing should be handled by logic in the business layer of the application.

More Reading...


  1. Creating and Using Managed Beans (if you use ADF Faces components in a standard JSF application)
  2. Using a Managed Bean in a Fusion Web Application (if you use Oracle ADF Model data binding and ADF Controller)
  3. JavaServer Faces (JSF) Tutorial
  4. Backing Bean in JSF Tutorial
  5. Types of Memory Scopes in Fusion Web Application
  6. Oracle ADF Task Flow in a Nutshell
  7. Using a Managed Bean in a Fusion Web Application

Tuesday, November 24, 2009

Oracle ADF Model In Depth

Oracle ADF Model implements the two concepts in JSR-227 that enable decoupling the user interface technology from the business service implementation:

  • data controls
    • A data control abstracts the implementation of a business service, allowing the binding layer to access the data from all services in a consistent way.
    • At runtime, the ADF Model layer reads the information describing the data controls and bindings from appropriate XML files and implements the two-way connection between the user interface and the business service.
  • declarative bindings
    • Declarative bindings abstract the details of accessing data from data collections in a data control and of invoking its operations.
    • There are 3 basic kinds of declarative binding objects:
      • Iterator bindings -- to allow scrolling and paging through collections of data and drilling-down from summary to detail information
      • Value bindings -- to display data
      • Action bindings -- to invoke built-in or custom operations on data collections of a data control. They are represented as operations in the Data Controls panel.
The following figure shows how bindings connect UI components to data control collections and methods.

In the following sections, we will see what kind of metadata are needed at design time to bind UI components (or widgets) to their associated data collections or methods declaratively and what kind of objects are generated at runtime to support the gluing.

Design Time

When you begin adding content to your page, you typically use the Component Palette and Data Controls panel of JDeveloper. The Component Palette contains all the ADF Faces components needed to declaratively design your page. Once you have the basic layout components placed on the page, you can then drag and drop items from the Data Controls panel to create ADF Model databound UI components.

From the item (i.e., accessor or attribute) dragged over from the Data Controls panel, JDeveloper first compiles a list of compatible BindingsTypes. From this list, JDeveloper can then determine the set of Creators that are applicable to drop on the page. The user is then presented with this list (organized by BindingsType). When the user selects a Creator to use, the Creator builds the databound UI component (by producing a DOM subtree representing what will be inserted into the page).
For example, If you drop the PrincipalName attribute from the Data Controls panel as an Input Text w/Label widget, JDeveloper creates an inputText component. The following code shows the code generated on the JSF page when you drop the PrincipalName attribute as an Input Text w/Label widget. Notice that the value of the component is bound to the inputValue property of the PrincipalName binding.


           shortDesc="#{bindings.PrincipalName.hints.tooltip}" id="it1">


You can change any of these properties to suit your needs. Reference this appendix for the properties of the ADF bindings.

If you build your application using these databound UI components, JDeveloper will create the following metadata files for you:
  • Add a page definition file. The page definition file (pageNamePageDef.xml) defines the group of bindings supporting the UI components on a page.
  • Create a DataBindings.cpx file and addes an entry for the page. The DataBindings.cpx file acts as the table of contents to the data controls in use in this application.
  • Create the adfm.xml file. This file creates a registry for the DataBindings.cpx file, which allows the application to locate it at runtime so that the binding context can be created.

Runtime

At runtime, multiple objects (i.e., binding context, binding containers, and binding objects) are created in memory to hold binding information. The ADF binding context is a runtime map of all data controls and page definitions within the application. The binding context is the one object that lives in the HttpSession for each end user, accessible using the EL expression #{data}.

The group of bindings supporting the UI components on a page are described in a page definition file. The ADF Model layer uses this file at runtime to instantiate the page's bindings. These bindings are held in a request-scoped map called the binding container, accessible during each page request using the EL expression #{bindings}. This expression always evaluates to the binding container for the current page.

  • Binding Context
    • The binding context provides the data environment for your application. It contains all of the data controls and binding containers that your application can access.
    • The ADF lifecycle creates the ADF binding context from the application module, DataBindings.cpx, and page definition files. Binding context contains references that become data control or binding container objects on demand.
    • You can look up ApplicationModule from a managed bean using the BindingContext:
      BindingContext bc = BindingContext.getCurrent();
      DCDataControl dc = bc.findDataControl("AppModuleDataControl");
      ApplicationModule am = (ApplicationModule)dc.getDataProvider();
    • You can retrieve a ControlBinding named "producerMethod" via BindingContext in this way:
      DCBindingContainer bc = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
      JUCtrlActionBinding actionBnd =
      (JUCtrlActionBinding)bc.getControlBinding("producerMethod");
  • Binding Containers
    • A binding container holds value bindings and iterator bindings (or binding objects) for a page. It provides runtime access to all the ADF binding objects for a page.
At runtime, a web request for http://yourserver/yourapp/faces/some.jsp arrives from the client to the application server. The ADFBindingFilter (defined in web.xml) object looks for the ADF binding context in the HTTP session, and if it is not yet present, initializes it for the first time. If the appropriate binding container for the page has never been used before during the user's session, it is created. Also, if it is the first time an application module data control is referenced during the request, it acquires an instance of the application module from the application module pool. Then the control is forwarded to the page to be rendered. The UI components on the page access value bindings and iterator bindings in the page's binding container and render the formatted output to appear in the browser. Finally, the user sees the resulting page in the browser.

References

  1. Using Oracle ADF Model in a Fusion Web Application
  2. Understanding the Fusion Page Lifecycle
  3. Oracle Fusion Middleware Online Documentation Library 11g Release (11.1.1.2)
  4. Oracle ADF BindingContext and BindingContainer

Tuesday, October 20, 2009

Types of Memory Scopes in Fusion Web Applications

At runtime, ADF objects such as the binding container and managed beans are instantiated. Each of these objects has a defined lifespan set by its scope attribute. Different scopes have different durations. The wider the scope, the higher availability of an object. When determining what scope to register a managed bean with, always try to use the narrowest scope possible.


6 Types of Memory Scopes

There are six types of memory scopes in a Fusion web application:


  • Application scope: An application scope object is available for the duration of the application and is shared among users. This scope may be used to hold static objects that are the same for all users.

  • Session scope: The object is available for the duration of the session, which is user instance-specific. A use case for a session scope bean is a user info bean that stores information about a user, which is read from the database or an LDAP server, to avoid unnecessary queries.

  • Page flow scope: A pageFlow scope exists for each task flow instance and has a lifespan between request and session scope. The lifetime of the scope spans across all pages in a bounded task flow.

  • Request scope: The object is available from the time an HTTP request is made until a response is sent back to the client. From another perspective, a request scope starts with a request to be issued from one view to another for navigation cases that don't perform a redirect but a default server-side forward. The scope spans across all non-view activities that follow the view of interest to the next view activity.

  • Backing bean scope: The backing bean scope is comparable to the request scope, with the difference in that it exists for a specific client component. In general, all managed beans used in reusable components should be configured to backingBean scope. For example, bounded task flows that are designed to be regions on a page should use the backingBean scope if more than one instance of the task flow is expected to be on a single page.

  • View scope: The object is available until the view ID for the current view activity changes. This becomes handy when you use partial page rendering. If you have a dependent list box, you might send a server request to refresh the list box. When a response is returned, the request scope will be gone but the view scope will be still there. Therefore, view scope can be used to store data when partial rendering request comes back. The view scope exists not only for views that are rendered by JSPX pages, but also for views rendered by page fragments, as is the case in task flows that are built to execute in a region. The view scope of the parent page is not accessible from components added to a page fragement in a region, and the view scope of a view in a region is not accessible for the parent page.
Some scopes are window-specific and some not. For example, there is no window uniqueness for session scope, all windows in the session share the same session scope instance. On the other hand, page flow or view scope are window-specific.

When you create objects (such as a managed bean) that require you to define a scope, you can set the scope to none, meaning that it will not live within any particular scope, but will instead be instantiated each time it is referenced. You should set a bean's scope to none when it is referenced by another bean.

Note that page flow, backing bean, and view scope are not standard JSF scopes. You access objects in those scopes (under the hood they're java.util.Map's) via expression language with scope qualification. For instance, to reference the MyBean managed bean from pageFlowScope scope, your expression would be #{pageFlowScope.MyBean}.



A Managed Bean Example

In this tutorial provided by Frank Nimphius, it demonstrates the usage of a request-scoped managed bean (i.e., HandleCaptchaBean) which is defined in adfc-config.xml file:
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
<managed-bean>
<managed-bean-name>HandleCaptchaBean</managed-bean-name>
<managed-bean-class>adf.sample.HandleCaptchBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</adfc-config>

At runtime, when user enters the challenged text and hit the try button, a method verifyAnswer defined on the managed bean would be invoked. The definition of the button looks like this:
<af:commandButton text="try" id="cb1"
actionListener="#{HandleCaptchaBean.verifyAnswer}"
partialSubmit="true" immediate="false"/>
The text entered by the user would set a request-scoped attribute (i.e., bestGuess) as follows:
<af:inputText id="it1" value="#{requestScope.bestGuess}"/>
When the action listener verifyAnswer is executed, it would fetch the request-scoped attribute bestGuess in this way:

FacesContext fctx = FacesContext.getCurrentInstance();
ExternalContext ectx = fctx.getExternalContext();
String answer = (String) ectx.getRequestMap().get("bestGuess");

Then fetched text is compared against the correct answer to see if the user is either a human or a robot.



ADF Task Flow

A task flow consists of activities and control flow cases that define the transitions between activities. Control flow rules are based on JSF navigation rules, but capture additional information. JSF navigation is always between pages, whereas control flow rules describe transitions between activities.



In the Figure, an unbounded task flow consists of a view activity, a router activity, a method call activity, a view activity, a bounded task flow, and a view activity and control flows in that order. There is one private scope per task flow, which is called page flow scope. When the outer task flow is executed, a new page flow scope PSF1 is created for it. When you enter the inner task flow, another page flow scope (i.e., PSF2) is created and PSF1 is suspended. After you exit from the inner task flow, PSF1 of the outer task flow is resumed. A task flow stack is maintained to keep track of the calls from task flow to task flow. An ADF Unbounded Task Flow always logically exists as the first entry on the task flow stack but would simply be empty.

When determining what scope to use for variables within a task flow, you should use any of the scope options other than application or session scope. These two scopes will persist objects in memory beyond the life of the task flow and therefore compromise the encapsulation and reusable aspects of a task flow. In addition, application and session scopes may keep objects in memory longer than needed, causing unneeded overhead.

Reusable components, especially those that are added with multiple instances on a single page, should be bound to per instance scope such as pageFlowScope, viewScope, or backingBean scope. If they are bound to broader scoped beans, many problems could ensue.

When you need to pass data values between activities within a task flow, you should use page flow scope. View scope is recommended for variables that are needed only within the current view activity, not across view activities. Request scope should be used when the scope does not need to persist longer than the current request. Lastly, backing bean scope must be used for backing beans in your task flow if there is a possibility that your task flow will appear in two region components or declarative components on the same page and you would like to achieve region instance isolation.


References



  1. Oracle Fusion Developer Guide by Frank Nimphius and Lynn Munsinger

  2. Creating and Using Managed Beans (if you use ADF Faces components in a standard JSF application)

  3. Using a Managed Bean in a Fusion Web Application (if you use Oracle ADF Model data binding and ADF Controller)

  4. JavaServer Faces (JSF) Tutorial

  5. Backing Bean in JSF Tutorial

  6. Managed Beans in Oracle Fusion Web Applications

Tuesday, October 6, 2009

Testing ADF BC Services Protected by HTTP Basic Authentication

Using Oracle JDeveloper 11g and Oracle Application Development Framework (ADF) in tandem, you can implement business services and publish them as SOAP web services using a declarative and component-based approach.

ADF supports open industry standards for ensuring the integrity and privacy of communications and to ensure that only authorized users can access resources in an ADF BC service. It uses the underlying Oracle Platform Security Services (OPSS) as building blocks for its security services.

To secure your ADF BC services with HTTP basic authentication scheme, it's straightforward. You simply attach the following security policy:
  • oracle/wss_http_token_service_policy
to your ADF BC services. The wss_http_token_service_policy uses the credentials in the HTTP header to authenticate users against the OPSS identity store.

Testing ADF BC Services Using HTTP Analyzer

To test ADF BC services protected by HTTP basic authentication scheme, you can use built-in HTTP Analyzer provided in JDeveloper as follows:
  • In the Application Navigator, right-click the AppModuleServiceImpl.java in the serviceInterface folder and select Run.
  • Select Target URL (i.e., http://localhost:7101/EmployeeWS-Model-context-root/AppModuleService) in the Running:DefaultServer Log window and click on it.
  • HTTP Analyzer will be started as shown in the figure.


In our example, we'll use getEmp1() operation which requires a single input (i.e, Employee ID). To provide basic credentials, you can do:
  • Expand Request HTTP Headers and select one of the existing header (e.g., "Content-Type") and click on "+" button.
  • In the Name field, enter "Authorization".
  • In the Value field, enter "Basic weblogic:weblogic1".


Note that basic-credentials is Base64 encoded. However, HTTP Analyzer does the base64-encoding of "username:password" automatically for you. You can see the value field changes to:
  • Basic d2VibG9naWM6d2VibG9naWMx
if you shift the focus away from Authorization header by clicking on other headers.

Testing ADF BC Services Using Test Page

You can also use Web Service Test Page to test your secured ADF BC service:
  • Enter your service's URL (i.e., http://ap6029fses:7102/RestNoSecWS-Model-context-root/AppModuleService) to any browser's address field.
  • Expand Show Transport Info.
  • Enable Http Authentication and provide user name and password as shown in the diagram.


Testing ADF BC Services Using XMLHttpRequest

Finally, you can write a test client written in JavaScript using XMLHttpRequest. XMLHttpRequest object is based on W3C's specification and defines an API that provides scripted client functionality for transferring data between a client and a server.

A sample JavaScript snippet which provides basic-credentials is shown below:
var userName =  form.form_user.value;
var password =  form.form_password.value;
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
xmlHttpReq = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttpReq.open("POST",
"http://ap6029fses:7102/RestNoSecWS-Model-context-root/AppModuleService",
false, userName, password);
xmlHttpReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttpReq.send("");

Saturday, September 19, 2009

Yushan on the Finalists of New 7 Wonders of Nature


New 7 Wonders of Nature have announced the 28 finalists. The list includes some well-known names such as Grand Canyon, Amzon Rainforest, and Great Barrier Reef. It also includes some lesser-known names like Yushan, Jeju Island, and Halong Bay — which are all located in Asia.






Yushan (玉山; also known as Jade Mountain) is the highest mountain in East Asia and the fourth highest mountain on an island. In the winter, Yushan is often capped with thick snow which makes the entire peak shine like stainless jade, hence its name.

Yushan and surrounding mountains belong to Yushan Range, which is part of Yushan National Park in Taiwan. The highest point of the range, Yushan, is 3,952 metres (12,966 ft) above sea level. Yushan was once in the ocean and raised to the current height because the Eurasian Plate slid under the neighboring Philippine Sea Plate. The ocean waters off Taiwan's east coast are deep; in fact, 50 kilometres (31 mi) offshore in the Pacific Ocean, the seabed drops precipitously to a depth of 4,000 metres (13,123 ft). From this perspective, Yushan is even more magnificent if you consider it rises 8,000 metres (vs 8,046 metres of Himalaya's) steeply from its nearby ocean floor in such a short distance — est 100 kilometres (62 mi).


Yushan is one of the favorites among Taiwanese mountain climbers. It also attracts climbers from all over the world. Yushan Range is known for its diverse and rich wildlife and ecology. The flora and fauna around Yushan itself spans from tropical and subtropical at its base to alpine at its peak. Due to humid ocean climate surrounding the island of Taiwan, Yushan is often surrounded by clouds. So, it is famous for the forever-changing cloud formations around the mountain. Because its vantage position, it's also good for watching sunrises and sunsets on top of it.

"Look over there. A magnificent and auspicious blue view has appeared in the heavens. Thus embellished, that row of bare precipices from Yushan's main summit to its eastern peak at that moment is like a rainbow, reflecting a dazzling auburn light. The creases on the mountain walls gently project a restrained cobalt blue." described by the famous Japanese naturalist Kano Tadao awed by Yushan's splendid and unusual sights.







Yushan Trip (Jade Mountain, Taiwan)

Widget powered by EveryTrail: Share GPS Tracks

Yushan National Park





Formosa

Taiwan where mountains meet ocean used to be called Formosa. It was a name called by Portuguese sailors in the 1600s, which means "Beautiful Island". Taiwan is one of the Four Asian Tigers, which were noted for maintaining exceptionally high growth rates and rapid industrialization between the early 1960s and 1990s. Besides rapid economic development, it is also famous for its nature beauty, people's friendliness, and food, tea, and hot spring cultures. Nowadays it attracts tourists from all over the world.

To learn more about Taiwan, you can view the following videos:

Photo Credit Goes to...

  1. http://www.flickr.com/photos/steking/200879728/sizes/o/
  2. http://www.flickr.com/photos/taiwandenmark/3368155874/
  3. http://www.flickr.com/photos/olvwu/3688258937/
  4. http://www.flickr.com/photos/villevaltterihelminen/3543142138/
  5. http://www.flickr.com/photos/yiru/9082308/
  6. http://www.flickr.com/photos/yiru/9090562/
  7. http://www.flickr.com/photos/olvwu/3693814952/
  8. http://www.flickr.com/photos/s_alumi/2838235533/

Friday, July 24, 2009

Recognizing a Stroke

Sometimes symptoms of a stroke are difficult to identify. Unfortunately, the lack of awareness spells disaster. The stroke victim may suffer severe brain damage when people nearby fail to recognize the symptoms of a stroke.

Now doctors say a bystander can recognize a stroke by asking three simple questions:
  • S—Ask the individual to smile.
  • T—Ask the person to talk and speak a simple sentence coherently (i.e. "I am in a BBQ party.")
  • R—Ask him/her to raise both arms.
If he or she has trouble with any one of these tasks, call emergency number immediately and describe the symptoms to the dispatcher.

Another Sign of a "Stroke"

Another 'sign' of a stroke is this: Ask the person to stick out his/her tongue. If the tongue is 'crooked' (i.e., if it goes to one side or the other), that is also an indication of a stroke.

Tuesday, July 14, 2009

Migration Considerations from Ubiquity 0.1.9 to 0.5—Author's Perspective

If you are using Ubiquity 0.1.8 and notice that a newer version (i.e., 0.1.9) is available, you update your Ubiquity extension for Firefox to the newer version. After that, you discover that there is yet another release 0.5 available from the home page (i.e., "about:ubiquity"). Before you jump to 0.5, read on.

Parser and the API used for writing Ubiquity commands have changed in Ubiquity 0.5. In this discussion, the new parser will be named Parser 2 and previous one Parser 1 (i.e, used by Ubiquity 0.1.9 and below). Ubiquity 0.5, by default, uses Parser 2 and Parser 1 (and the Parser 1 API) will be deprecated in the future.

Parser 1 is forward-compatible to use commands written for Parser2, but Parser 2 is not backwards compatible to use commands written for Parser1. If you have commands written for Parser 1 and have updated to Ubiquity 0.5, you have the following options:
  1. Rewrite commands with new API
  2. Go to the Ubiquity 0.5 settings page and turn off "use Parser 2". However, this is an interim solution because Parser 1 will be deprecated in the future.
As a Ubiquity command author, you can go extra miles to make your commands support both Parser 1 and Parser2 by presenting different commands to clients running Parser 1 and Parser2. A command can provide different options to CmdUtils.CreateCommand() and behave differently depending on the value of CmdUtils.parserVersion, allowing a single command feed to cater to whatever parser the user is using.

if (CmdUtils.parserVersion == 2)
//parser 2 command here
else
//parser 1 command here
Ubiquity is still an experimental product. It has evolved and will evolve further in the future. However, Ubiquity designers have tried to make Parser 2 API future-proof and flexible enough to support plans for the foreseeable future. So, hopefully we won't have to migrate again after this. Let's see if Ubiquity designers can keep their promises or not.

References

  1. Ubiquity 0.5 Release Notes
  2. Ubiquity 0.5 Author Tutorial
  3. Parser 2 API Conversion Tutorial

Wednesday, June 3, 2009

Turn on Diagnostic to Debug Oracle ADF BC Applications

When you encounter problems running an ADF BC application, one of the first things you can try is to turn on diagnostic to see if the diagnostic output offer further information on the problem.

jbo.debugoutput

To turn on diagnostics, set the Java system parameter jbo.debugoutput to the value console or file depending on whether you want to see the diagnostics on standard output or whether you want them redirected to a file in your output directory. To turn off diagnostics, you can set the system parameter to silent.

If you're invoking your application (middle-tier application) from command line, include -Djbo.debugoutput=console as in:
java.exe -Djbo.debugoutput=console ...

If you're running your application from within JDeveloper:
  1. Select the project (e.g., "Model").
  2. Do right mouse click and select "Project Properties"
  3. On the property dialog, select "Run/Debug/Profile".
  4. Edit your Run Configuration (e.g., "Default")
  5. On the right pane, you should see "Java Options" input text field. Add the following Java system parameter: -Djbo.debugoutput=console

What to Expect?


When you run again, you'll see an abundant amount of diagnostic tracing printed out that will help narrow down the problem. If you run the application from JDeveloper, you should see the following line in the Log view:
Diagnostics: (BC4J Bootstrap) Routing diagnostics to standard output (use ...)

If not, you need to stop the Server Instance and restart it. The typical diagnostic output looks like below:
[00] Diagnostic Properties: Timing:false Functions:false Linecount:true Threshold:6
    
Diagnostics: (BC4J Bootstrap) Routing diagnostics to standard output (use -Djbo.debugoutput=silent to remove)
[00] Diagnostic Properties: Timing:false Functions:false Linecount:true Threshold:6
[01] JavaVMVersion: 11.0-b16
[02] JavaVMVendor: Sun Microsystems Inc.
[03] JavaVMName: Java HotSpot(TM) Client VM
[04] OperatingSystemName: Linux
[05] OperatingSystemVersion: 2.6.18-53.1.4.el5PAE
[06] OperatingSystemUsername: sguan
[07] jbo.323.compatible Flag: false, str: null
[08] jbo.903.compatible Flag: false, str: null
[09] oracle.adfm.usemds Flag: true, str: null
[10] MDS parser created
...
[297] Loading from individual XML files
[298] Loading the Containees for the Package 'oracle.apps.model.Model'.
[299] Connected to Oracle JBO Server - Version: 11.1.1.53.68
[300] No XML file /oracle/apps/model/model.xml for metaobject oracle.apps.model.model
[301] MDS error (MetadataNotFoundException): MDS-00013: no metadata found for metadata object "/oracle/apps/model/model.xml"
[302] Cannot Load parent Package : oracle.apps.model.model
[303] Business Object Browsing may be unavailable
[304] Loading Typemap entries from oracle.apps.fnd.applcore.oaext.typemap.OATypeMapEntries
[305] Stringmanager using default locale: 'en_US'
[306] CSMessageBundle (language base) being initialized

References

  1. How to Get More Details Error Information

  2. BC4J Helper by Sung Im

Sunday, April 12, 2009

Ubiquity vs. Smart Keyword--Two Firefox Addons

What's Smart Keyword

A smart keyword (also known as bookmark keyword, or keymark for short) is a special kind of bookmark that replaces a special sequence, %s, in the bookmark location field (URL) with the text entered after the keyword in the address bar. For example, if you define "g" for Google Search as shown below:



Pressing Ctrl+L sets the input focus to the address bar and selects the entire content. Then, you enter "g Oracle" in the location bar. After pressing Enter, "g Oracle" will be expanded into:
  http://www.google.com/search?hl=en&q=Oracle&aq=f&oq
In summary, the following keystroke sequence let you Google Search "Oracle":

  Ctrl+L > "g Oracle" > Enter


The Similarity

Similarly, Ubiquity command "google" allows you to Google Search "Oracle" in the following keystroke sequence:

  Ctrl+Space > "g Oracle" > Enter

assuming command "google" is the top one on the suggestion list. You can read another post for how Ubiquity works here. Both Ubiquity and Smart Keyword allow users to save mouse clicking and word typing to achieve everyday's browser tasks easier and quicker. Then, what's the difference between Ubiquity and Smart Keyword?


The Difference

In a nutshell, Ubiquity can do what Smart Keyword can do and more. For example, if you select "Oracle" in the browser window, selected word(s) can become the input of Ubiquity command. In this case, you can achieve the same task by:

  Selecting "Oracle" > Ctrl+Space > "g " > Enter


Both Ubiquity commands and Smart Keywords function like command templates. Firefox selects one of the commands to execute with command variable replaced with user's input. In Smart Keyword, there is one variable one command. However, you can have more than one variable in a single Ubiquity command.

The centerpiece of Ubiquity architecture is a natural language parser which can provide user a list of candidate commands based on partially matched results. For the top candidate command on the suggestion list, it immediately generates a preview of the top command results in the preview panel. If the top command on the suggestion list is what user wants, user can hit TAB to automatically complete the command name. As user types more characters or uses arrow key to select commands on the suggestion list, Ubiquity dynamically changes the content of suggestion list and command preview.

Besides good for search, Ubiquity commands can be designed to do almost anything. For example, you can translate selected paragraph from one language to another language, insert selected image from search results to the current cursor position, italicize or underline text, etc.

Based on the group activity on ubiquity-firefox@googlegroups.com, you can tell that Ubiquity has active community supports and it evolves fast. This Firefox addon is still in experimental phase (the latest beta is 0.2pre29). There are a lot of design details to be ironed out. But, I think it has potential to become a big hit. At least, I have found it handy and used it on a daily basis.

Friday, April 3, 2009

What's Ubiquity--User's Perspective

Ubiquity is a Firefox extension and it provides you with a different way to navigate and interact with your computer through the use of keyboard shortcuts and typed commands. Ubiquity let you apply textual commands (called "verbs") to whatever you're looking at on your screen. See here for its formal introduction. You can also view the video below:



Ubiquity for Firefox from Aza Raskin on Vimeo.

Platforms Supported

Ubiquity is cross-platform. Here are a list of platforms it supports with descriptions:



























Mac OS X



  • Need to have Growl installed




    • This is a Mac OS X system extension that applications can use to display unobtrusive transparent messages



Windows



  • On Windows (XP and later), you don't need to install anything special.


Linux



  • On Linux, you shouldn't have to do anything special: just make sure you're updated to the latest version of Firefox.




Where to find Ubiquity?


Ubiquity is still in flux. The latest release is 0.1.7. If you're viewing this post from Firefox, you can get the latest version here. If you're a brave soul, you can get the latest beta vesion here. The installation is a simple Firefox add-on installation. After installation of Ubuiquity, you can start playing with its commands from standard feeds. To see a list of commands available to you, paste the following URL to your Firefox address field:

chrome://ubiquity/content/cmdlist.html



How to launch Ubiquity?

  1. Open up Ubiquity (CTRL+SPACE on Windows and ALT+SPACE on other platforms), and type any command name.

  2. You should see command options on suggestion list or preview pane, complete the command and hit Enter.

Where to get more commands?

There are two sources that you can get more Ubiquity commands from:

After you get started, you'll have a need to manage all your Ubiquity commands. To do that, go to the command management page by pasting the following URL into your Firefox address field:

about:ubiquity


How to subscribe new commands?

After navigating to the command source page in Firefox, you should see a bar at the top of the page asking you to subscribe to the Ubiquity command. If not, then you either do not have Ubiquity installed or you are already subscribed to the command.

What happens when you click on subscribe button?

Ubiquity commands are implemented in Javascript. All Javascripts are deemed potentially dangerous. So, what happens if you click on the subscribe button? At ease. It will bring you to a subscription page like this:



It will show you the content of Javascript source. At the bottom of the page, it shows two buttons for you to either accept or reject the subscription. In Ubiquity 0.2, it redesigns the security model of Ubiquity with command feed plugins. So, you can identify and/or trust your command feeds more easily.

To learn more, check out other blog posts here.

Thursday, April 2, 2009

Understanding URL Syntax of Oracle Application Express

Oracle Aria (i.e., Oracle people search site; this is located in the intranet of Oracle) is built using Oracle Application Express. Oracle Application Express (Oracle APEX) is a rapid web application development tool for the Oracle database.

To build a Ubiquity command for Oracle Aria, you need to understand its URL syntax. Web application built using Oracle APEX is composed of multiple pages. Each application is identified by a unique number (i.e., application ID). Similarly, each page is uniquely identified by its page number.
Applications and pages may also have alphanumeric aliases. Application aliases are unique within a workspace and page aliases are unique within each application.

Understanding URL Syntax

The URL that displays for each page identifies the address of Oracle Application Express, the application ID, page number, and session ID. For example:

http://xxx.us.oracle.com/pls/oracle/f?p=8000:1:7528859885365

This example indicates:
  • xxx.us.oracle.com is the URL of the server
  • pls is the indicator to use the mod_plsql cartridge
  • oracle is the database access descriptor (DAD) name. The DAD describes how HTTP Server connects to the database server so that it can fulfill an HTTP request.
  • f?p= is a prefix used by Oracle APEX
  • 8000 is the application being called
  • 1 is the page within the application to be displayed
  • 7528859885365 is the session ID

You can create URLs to access pages in your application using the following syntax:
  f?p=App:Page:Session:Request:Debug:ClearCache:itemNames:itemValues:PrinterFriendly

Table 1 describes the arguments you can pass when using f?p syntax.

Syntax Description
App Indicates an application ID or alphanumeric alias.
Page Indicates a page number or alphanumeric alias.
Session Identifies a session ID. You can reference a session ID to create hypertext links to other pages that maintain the same session state by passing the session number.
Request Sets the value of REQUEST. Each application button sets the value of REQUEST to the name of the button. This enables accept processing to reference the name of the button when a user clicks it.
Debug Displays application processing details. Valid values for the DEBUG flag are YES or NO. Setting this flag to YES displays details about application processing.
See Also: "Debugging an Application"
ClearCache Clears the cache. This sets the value of items to null. To clear cached items on a single page, specify the numeric page number. To clear cached items on multiple pages, use a comma-separated list of page numbers. Clearing a page's cache also resets any stateful processes on the page. Individual or comma-separated values can also include collection names to be reset or the keyword RP, which resets region pagination on the requested page. The keyword APP clears cache for all pages and all application-level items in the current application and removes sort preferences for the current user. The keyword SESSION achieves the same result as the APP keyword, but clears items associated with all applications that have been used in the current session. See Also: "Clearing Session State"
itemNames Comma-delimited list of item names used to set session state with a URL.
itemValues List of item values used to set session state within a URL. Item values cannot include colons, but can contain commas if enclosed with backslashes. To pass a comma in an item value, enclose the characters with backslashes. For example:
\123,45\
PrinterFriendly Determines if the page is being rendered in printer friendly mode. If PrinterFriendly is set to Yes, then the page is rendered in printer friendly mode. The value of PrinterFriendly can be used in rendering conditions to remove elements such as regions from the page to optimize printed output. When the value is Yes, the Application Express engine will not display tabs or navigation bars, and all items will be displayed as text and not as form elements.



What Is a Session?

HTTP is a stateless protocol. In web browser, each page request is treated by the server as an independent event, unrelated to any page requests that happened previously or may occur in the future. Typically, when a user enters values into a form on one page, those values are not accessible on later pages.

A session is a logical construct that establishes persistence (or stateful behavior) across page views. Each session is assigned a unique identifier. The Application Express engine uses this identifier (or session ID) to store and retrieve an application's working set of data (or session state) before and after each page view. It transparently maintains session state and provides developers with the ability to get and set session state values from any page in the application.

Using Zero as Session ID

Application pages that do not require authentication can be accessed with "f?p" URLs where the session ID is zero (that is, the single digit 0). When you request a page by either entering the URL in the browser or by clicking on a link having 0 for the session ID, the Application Express engine assigns a new session ID and sends a session cookie containing this new session ID to your browser. As you navigate through the application's public pages, you will see that all generated links to public pages will contain 0 for the session ID and all branches to public pages will have new URLs that use 0 as the visible session ID. Behind the scenes, however, the Application Express engine uses the session ID in the cookie as the actual session ID to locate session state.

This feature is useful when you want to hide the actual session ID. By hiding the session ID, you enable users to bookmark pages without needing to include the session ID in the bookmark link. As an added benefit, using zero as the session ID also keeps the actual session ID hidden from search engines.

Sunday, March 29, 2009

Ubiquity Command - Dissected

It's easy to create a Ubiquity command by yourself if you know JavaScript. Using Ubiquity command editor, you can start creating new commands such as this:

CmdUtils.CreateCommand({
name: "ses-login-search",
takes: {"adc60019fems or adc60037fems": noun_type_ses_url },
modifiers: {"for": noun_arb_text, "with": noun_arb_text},
homepage: "http://xteam.us.oracle.com/blogs/index.php?blog=10",
author: { name: "Stanley Guan", email: "xmlandmore@gmail.com"},
description: "Search adc60019fems or adc60037fems for keywords" +
" with given userName/password",
help: "Search server for keywords with given credentials." +
" If server name is not specified, default server will be used." +
" Specify credentials with usename and password (in that order) " +
" and separate them by space.",
license: "GPL",
preview: function(pblock, directObj, mods) {
var server = directObj.text createList(sesNicknames);
var keywords = mods["for"].text "keywords";
var creds = mods["with"].text "userName/password";
pblock.innerHTML = "search " + server + " for " + keywords +
" with " + creds;
},
execute: function(directObj, mods) {
// This function gets executed when user hits ENTER.
// You can have different approaches:
// 1. Launch a new window to display command output.
// 2. Replace selection with command output.
}
});

In the above example, new command is named "ses-login-search" and it takes one direct object and two modifiers. This means that our command should look like this:

ses-login-search (adc60019fems or adc60037fems) for (keywords)
with (username/password)

Ubiquity command parser supports natural language processing. You can choose verbs as your command names. Now it only supports single-word command names. So, you should use "-" to connect multiple words as we've done here. Our command will allow SES users to login and search at the same time. The direct object of our command is a server name. It can be either "adc60019fems" or "adc60037fems".

To pass more arguments, you can use modifiers. Modifiers are prepositional phrases (i.e., prepositions followed by nouns in English). In our case, we use "for" to specify keywords to be searched for and "with" to provide user's credentials.

Other parts of command include the following properties:
  • homepage
  • author
  • description
  • help

These properties are used to compose detailed description of our command on Ubiquity's command list. If our command were subscribed, it could look like this:



Help text provided in "help" property is also displayed in the preview pane when user type "help ses-login-search" in the command entry field as shown below:
As described in Ubiquity's UI Design , preview function is used by command designer to provide preview content (as defined by HTML snippet) to be displayed in the preview pane. For example, if your command is a search command, you can display top-ranked search results here for the user to see. Sometimes, if users find the result they need in the preview pane, they can click on the link and jump directly to the target URL and skip the command execution phase.

If users need to see the full command output, they can execute command (defined by the "execute" property) by hitting ENTER after command is fully specified. Two arguments are passed to "execute" function:

  1. directObj (i.e., direct-object)
  2. mods (i.e., modifiers)

They contain the command options as specified by the users. To access them, you use:

  1. directObj.text for direct-object
  2. mods["with"].text or mods["for"].text for modifiers

As I say, it's easy to create a new Ubiquity command if you know JavaScript. Hopefully, this post has provided enough information for you to begin with. To view more examples, you can find them from:
  1. Commands in the wild
  2. Ubiquity Herd