OpenSubsystems

Business Components for Java Applications

Open Patterns

Quick Start

Documentation
Last modified

$Author: bastafidli $
$Date: 2007/03/24 08:35:37 $
$Revision: 1.7 $
$RCSfile: quickstart.html,v $

The goal of Open Patterns is to expand the foundation created by Open Core and further increase development speed and quality of developed applications by providing reusable blocks of high level functionality. There are many features, which the developer can take advantage of and this document provides a brief summary of the most important ones.

How do I start with Open Patterns?

Open Patterns builds on the foundation created by Open Core. If your project's structure and build process follows the recommendation from Open Core Quick Start guide then the only thing you will need to do to use Open Patterns is to download the Open Patterns binary distribution package and extract it to

   [Your Project Name]\external\patterns 
               

directory. Then modify the external.properties file and add there line

   patterns_home=${external_projects_home}/patterns
               

Finally modify your Ant build file build-[your project name].xml and in the target preparelibs add line

               
   <ant antfile="${build.files}/build-external.xml" 
           target="installpatterns"/>
               

The Open Core based build process will take care of the rest and will install all the necessary Open Patterns libraries, configuration files (e.g. .tld files), images, style sheets, JavaScript files and JSP layouts when you build your project.

If you use your own build process, you will need to manually configure and add all the required files. The Open Patterns class libraries can be found in the lib folder of the binary distribution package. The sources folder of the binary distribution package contains all the other files you may need during development of your application or subsystem in the source form (.properties, .tld, .xml, .css, .js, .jsp, etc.).

List data pattern

How do I implement the list data pattern?

The list data pattern allows to access large amount of data in small chunks either page by page or accessing the specified page directly. This functionality is available to any subsystem that is using the concept of data objects constructed by data factories as defined by Open Core. The Open Patterns provides classes that implement this pattern for data stored in relational databases. This implementation works efficiently with all supported databases and you do not have to write any SQL code.

List data pattern implementation require that you modify your persistence tier classes so that they implement or extend some of the interfaces and classes provided by Open Patterns (ListFactory, ListDatabaseFactory, ListDatabaseFactoryImpl, ListDatabaseSchema, ListDatabaseSchemaImpl, ModifiableListDatabaseSchemaImpl). You will also need to define set of symbolic constants in your data object that will represent its attributes when describing the definition and behavior of the data list. Once your persistence tier is modified you can take advantage of ListController API and ListBrowserServlet functionality to access your data page by page without any further coding. You will be also able to use provided custom JSP tags to easily implement JSP pages displaying the retrieved data and navigate between them.

How does my data object change for the list data pattern?

Throughout the implementation of the list data pattern you will have to provide information about data object attributes that should be displayed in the list. This information should be defined as symbolic constants in your data object class, one constant for each attribute and several constants for the default definition of the data object list as demonstrated by the following code snippet:

   public class MyData extends ModifiableDataObject
   {
      public static final int COL_MYDATA_ID = DataConstant.MYDATA_DATA_TYPE + 1;

      public static final int COL_MYDATA_NAME = DataConstant.MYDATA_DATA_TYPE + 2;

      public static final int COL_MYDATA_DESCRIPTION = DataConstant.MYDATA_DATA_TYPE + 3;
      
      ...
      
      public static final int[] DEFAULT_LIST_COLUMNS = {COL_MYDATA_NAME,
                                                        COL_MYDATA_DESCRIPTION,
                                                        COL_MYDATA_MODIFICATION_DATE,
                                                       };
   
      public static final int[] DEFAULT_LIST_SORT_COLUMNS = {COL_MYDATA_NAME};

      public static final String[] DEFAULT_LIST_SORT_ORDER
                                      = ListDefinition.ORDER_ASCENDING_ARRAY;
      ...
   }               
               
How does my database schema change for the list data pattern?

Your database schema class must either implement ListDatabaseSchema interface or it can extend one of the provided base classes. Depending on if your database schema allows to modify the data it manages or not you can choose either from ListDatabaseSchemaImpl or ModifiableListDatabaseSchemaImpl class. If you choose to implement the interface, you will have to provide implementation of all the required methods yourself. If you choose to extend one of the base classes, it will provide implementation of most of the methods for you. In that case you will need to supply to the parent constructor several values that describe features of individual database columns:

   public abstract class MyDataDatabaseSchema extends ModifiableDatabaseSchemaImpl
   {
      ...
   
      public static final int[] MYDATA_MANDATORY_RETRIEVE_COLUMNS 
                                   =  {MyData.COL_MYDATA_ID, 
                                       MyData.COL_MYDATA_NAME,
                                      };
  
      public static final int[] MYDATA_SORT_COLUMNS = {MyData.COL_MYDATA_NAME,
                                                       MyData.COL_MYDATA_DESCRIPTION,
                                                       ...
                                                       MyData.COL_MYDATA_MODIFICATION_DATE,
                                                      };

      public static final int[] MYDATA_FILTER_COLUMNS = {MyData.COL_MYDATA_NAME,
                                                         MyData.COL_MYDATA_DESCRIPTION,
                                                         ...
                                                         MyData.COL_MYDATA_MODIFICATION_DATE,
                                                       };
                                                       
      ...   
      
      public MyDataDatabaseSchema(
      ) throws OSSException
      {
         super(null, MYDATA_SCHEMA_NAME, MYDATA_SCHEMA_VERSION, true, 
               MYDATA_TABLE_NAME, MYDATA_MANDATORY_RETRIEVE_COLUMNS, 
               MYDATA_SORT_COLUMNS, MYDATA_FILTER_COLUMNS);
      }   
   
      ...
   
   }
               

The getColumns method that you have to implement in your database schema class is responsible for mapping the symbolic constants identifying individual data object attributes to the actual database table column names:

   public StringBuffer getColumns(
      final boolean  specific,   
      final int[]    columns,
      final Object[] prefixes, 
      final Object[] postfixes, 
      StringBuffer   buffer      
   ) throws OSSException
   {
      if (buffer == null)
      {
         buffer = new StringBuffer();
      }
      for (int iIndex = 0; iIndex < columns.length; iIndex++)
      {
         if (iIndex > 0)
         {
            buffer.append(",");
         }
         
         if ((prefixes != null) && (prefixes.length > 0) && (prefixes[iIndex] != null))
         {
            buffer.append(prefixes[iIndex]);            
         }
         
         if (specific)
         {
            buffer.append(MYDATA_TABLE_NAME);
            buffer.append(".");
         }

         switch(columns[iIndex])
         {
            case (MyData.COL_MYDATA_ID):
            {
               buffer.append("ID");
               break;
            }
            case (MyData.COL_MYDATA_NAME):
            {
               buffer.append("NAME");
               break;
            }
            case (MyData.COL_MYDATA_DESCRIPTION):
            {
               buffer.append("DESCRIPTION");
               break;
            }
            ...
            case (Entry.COL_BLOGENTRY_MODIFICATION_DATE):
            {
               buffer.append("MODIFICATION_DATE");
               break;
            }
            default:
            {
               assert false : "Unknown column ID " + columns[iIndex];
            }
         }

         if ((postfixes != null) && (postfixes.length > 0) && (postfixes[iIndex] != null))
         {
            buffer.append(postfixes[iIndex]);            
         }
      }

      return buffer;
   }
               
How does my database factory change for the list data pattern?

Your data factory interface has to extend ListFactory interface as is demonstrated by this code snippet:

   public interface MyDataFactory extends ModifiableDataFactory, 
                                          ListFactory
   {
      ...
   }               
               

Your database factory class must either implement ListDatabaseFactory interface or it can extend ListDatabaseFactoryImpl base class instead. If you choose to implement the interface, you will have to provide implementation of all the required methods yourself. If you choose to extend the base class, it will provide implementation of most of the methods for you. We suggest extending the provided base class in order to simplify your implementation.

   public class MyDataDatabaseFactory extends    ListDatabaseFactoryImpl
                                      implements MyDataFactory, 
                                                 ModifiableDatabaseFactory
   {
      ...
   }
               

When extending your database factory from ListDatabaseFactoryImpl you will need to supply to the parent constructor several values that describe what data to return when user requests a list of your data objects for the first time:

   public MyDataDatabaseFactory(
   ) throws OSSException
   {
   {
      super(DataConstant.MYDATA_DATA_TYPE,
            MyData.DEFAULT_LIST_SORT_COLUMNS,
            MyData.DEFAULT_LIST_SORT_ORDER,
            MyData.DEFAULT_LIST_COLUMNS,
            ((MyDataDatabaseSchema)DatabaseSchemaManager.getInstance(
                     MyDataDatabaseSchema.class))
            );
      ...
   }
               

The load method that you have to implement in your database factory class is responsible for constructing your data object using the columns that were requested from the database:

   public DataObject load(
      ResultSet rsQueryResults,
      int[]     selectedColumns,
      int       initialIndex
   ) throws OSSDatabaseAccessException
   {
      MyData data;

      try
      {
         int         id                    = DataObject.NEW_ID;
         String      name                  = "";
         String      description           = "";
         ...
         Timestamp   modified              = null;

         for (int columnCount = initialIndex; 
              columnCount < (initialIndex + selectedColumns.length); 
              columnCount++)
         {
            switch (selectedColumns[columnCount - 1])
            {
               case (MyData.COL_MYDATA_ID) :
               {
                  id = rsQueryResults.getInt(columnCount);
                  break;
               }
               case (MyData.COL_MYDATA_NAME) :
               {
                  name = rsQueryResults.getString(columnCount);
                  break;
               }
               case (MyData.COL_MYDATA_DESCRIPTION) :
               {
                  description = rsQueryResults.getString(columnCount);
                  break;
               }
               ...
               case (MyData.COL_MYDATA_MODIFICATION_DATE) :
               {
                  modified = rsQueryResults.getTimestamp(columnCount);
                  break;
               }
               default:
               {
                  assert false : "Unknown column ID " + selectedColumns[columnCount - 1];
               }
            }
         }

         data = new MyData(id,
                           name,
                           description,
                           ...
                           modified);
         data.setFromPersistenceStore();
      }
      catch (SQLException sqleExc)
      {
         throw new OSSDatabaseAccessException("Failed to load data from the database.",
                                              sqleExc);
      }

      return data;
   }
               
How can I use the list data pattern functionality implemented by my database factory?

Once your persistence tier implements all the changes required by the list data pattern you can use it to retrieve your data from the database page by page. If you want to retrieve the data programmatically you can call the get(ListOptions) method from the ListFactory interface to retrieve any amount and portion of your data exactly the way you want. You will have to correctly configure ListOptions data structure to specify exactly what data to retrieve. Here is how you can get instance of your database factory:

   myDataFactory = (MyDataFactory)DataFactoryManager.getInstance(MyDataFactory.class);               
               

Here is an example how you can construct initial instance of ListOption required by the get(ListOptions) method.

   ListOptions options = new ListOptions(
      MyDataFactory.class,
      null, // Optional list definitions
      ListDefinition.DEFAULT_PAGE_SIZE,
      0, // We don't know what is the actual list size
      MyData.DEFAULT_LIST_SORT_COLUMNS,
      MyData.DEFAULT_LIST_SORT_ORDER,
      0, // Optional client side sorting support
      null, // Optional client side sorting support
      0, // begin position
      0, // We don't know what is the end position
      iPageNumber,
      0, // We don't allow client to 
      DataConstant.NO_DATA_TYPE, // MyData doesn't have parent 
      DataObject.NEW_ID, // MyData doens't have parent
      null, // Optional client side selection
      null, // Optional client side highlighting
      MyData.DEFAULT_LIST_COLUMNS,
      null, // Optional support excluding any items
      false, // Optional support for distinct
      false, // Optional support client side selection
      CallContext.getInstance().getCurrentDomainId()
      );
               

There is of course an easier way to use the list data pattern using the API provided by the ListController class.

How do I use the ListController API provided by the list data pattern?

The easiest way to programmatically use the list data pattern is to use API provided by the ListController interface. The user interface and web tiers components as well as other subystems must use controller anyway to follow the OpenSubsystems architectural guidelines. First get an instance of the controller:

   controller = (ListController)ControllerManager.getInstance(ListController.class);
               

Then construct instance of ListOptions and supply parameters that fit your needs. Provide values for those you know and use reasonable default values (0, null) for the rest. Next call one of the getShowList, getExactPage or getSetDefinition methods of the ListController instance. Either one of these methods will retrieve the initial list based on your settings and overwrite any settings that do not make sense with reasonable alternatives. You can then call any of the other getXYZ methods, such as getNextPage or getPrevious page using the updated ListOptions returned from the first call. The following code snippet demonstrates how you can easily iterate the entire list page by page:

   ListOptions    listData = new ListOptions(...);
   Object[]       data;
   List           lstData;
   
   data = controller.getShowList(listData);
   if (data != null)
   {
      listData = (ListOptions)data[0];
      lstData = (List)data[1];                           
      while ((listData != null) && (lstData != null) && (!lstData.isEmpty()))
      {
      
         ... // process data in lstData
         
         if (!listData.getIsLastPage())
         {
            data = listLoader.getNextPage(listData);
            if (data == null)
            {
               break;
            }
            else
            {
               listData = (ListOptions)data[0];
               lstData = (List)data[1];                           
            }
         }
         else
         {
            break;
         }
      }
   }
               
How do I use the ListBrowserServlet provided by the list data pattern?

List data pattern makes it very easy to construct a web user interface that allows user to browse your data page by page using a web browser. The pattern provides fully functional ListBrowserServlet class that you just need to configure in your web application web.xml file:

   <servlet>
      <servlet-name>mydatalist</servlet-name>
      <servlet-class>org.opensubsystems.security.www.ListBrowserServlet</servlet-class>
      <init-param>
         <param-name>oss.listbrowser.list.page</param-name>
         <param-value>/mydata/jsp/page/mydatalist.jsp</param-value>
      </init-param>
      <init-param>
         <param-name>oss.listbrowser.datafactory.classname</param-name>
         <param-value>org.opensubsystems.mydata.persist.MyDataFactory</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>
   
   ...
   
   <servlet-mapping>
      <servlet-name>mydatalist</servlet-name>
      <url-pattern>/mydata/*</url-pattern>
   </servlet-mapping>
               

Notice how we have configured the servlet to use your data factory to retrieve the data and we have instructed it to use your own JSP page to render the data. The pattern provides set of custom JSP tags that makes implementation of such JSP pages straight forward. The easiest way to start is to examine the provided taglig API documentation. The following code snippet demonstrates the structure of a simple JSP page created using some of these tags:

   The list data pattern  has to be initialized to properly include CSS and JS
   this tag has to be placed before the tiles:insert specifying template derived
   from empty page layout.
   
   <listdata:init dataAlias="mydata"/>

   ...

   Display the data sent from the servlet

   <bean:define id="mydata" name="mydata" scope="request" type="java.util.List"/>
   <logic:iterate id="onedata" name="mydata" type="net.sourceforge.MyData">
      <bean:write name="onedata" property="name"/>
      ...
   </logic:iterate>

   ...

   Declare page variable that represents ListOptions sent from the servlet

   <bean:define id="listoptions" name="listoptions" scope="request" 
                type="org.opensubsystems.patterns.listdata.data.ListOptions"/>

   Create static navigation that will allow user to access other parts of the 
   data items list as well as display current position in the list

   <a href="<listdata:gotopage page="1"/>">First</a>
   <a href="<listdata:previouspage/>">Previous</a>
   
   | Page <bean:write name="listoptions" property="actualPage" format="#"/>
   of <bean:write name="listoptions" property="relativePageCount" format="#"/>
   (Records <bean:write name="listoptions" property="beginPosition" format="#"/>
   - <bean:write name="listoptions" property="endPosition" format="#"/>
   of <bean:write name="listoptions" property="actualListSize" format="#"/>) |
   
   <a href="<listdata:nextpage/>">Next</a>
   <a href="<listdata:gotopage page="<%=listoptions.getAbsolutePageCount()%>"/>">Last</a>
               

The previous code snippet demonstrates how to provide navigation when none of the list definition parameters can be changed by user. But what to do when you want to for example allow user to dynamically select the number of displayed items at a page or select the page to display? The ListBrowserServlet allows you to define HTML form, modify it's values using the JavaScript functions provided in the listdata.js file and then submit it to the ListBrowserServlet to retrieve the list data using the modified settings. Definition of such form is very easy thanks to custom JSP tag provided by the list data pattern. The following code snippet demonstrates how to construct such form and how to let user select what page to display.

   <form id="DATA_LIST_FORM" name="DATA_LIST_FORM" method="post" 
            action="<%=servletpath%>">
      <listdata:formcontent/>
      ...
               
      <a onclick="previousPage('<%=servletpath%>');" href="#">Previous</a>
      <select size="1" id="GOTO_PAGE" name="GOTO_PAGE">
         <logic:iterate name="listoptions" property="goToPages" id="pageIndex">
            <option <%=((pageIndex.equals(Integer.toString(listoptions.getActualPage()))) 
                   ? "selected" : "")%>><bean:write name="pageIndex"/></option>
         </logic:iterate>
      </select>
      <a onclick="goToPage('<%=servletpath%>');" href="#">Go</a>
      <a onclick="nextPage('<%=servletpath%>');" href="#">Next</a>
      
   </form>
               
How do I display data retrieved by the list data pattern using datalist layout?

The list data pattern provides templating layout datalist.jsp and custom JSP tag base class ListTag to make implementation of your web pages easier. If you decide to use this layout, you will get professionally looking web pages without any HTML coding. First step is to implement your own version of the custom JSP list tag by deriving new class from the base class provided by the list data patterns:

   public class MyDataListTag extends ListTag 
   {
      static
      {
         ColumnDefinition temp;
         
         COLUMN_DEFINITIONS = new HashMap();
         temp = new ColumnDefinition("Id", "Internal Id",
                   DataCondition.VALUE_TYPE_ID, 0);
         COLUMN_DEFINITIONS.put(MyData.COL_MYDATA_ID_OBJ, temp);
         temp = new ColumnDefinition("Name", "Name identifying the data",
                   DataCondition.VALUE_TYPE_STRING, 1);
         COLUMN_DEFINITIONS.put(MyData.COL_MYDATA_NAME_OBJ, temp);
         ...
         temp = new ColumnDefinition("Modified", "Modification date and time",
                   DataCondition.VALUE_TYPE_TIMESTAMP, 1.3);
         COLUMN_DEFINITIONS.put(MyData.COL_MYDATA_MODIFICATION_DATE_OBJ, temp);
      }
      
      public MyDataListTag()
      {
         super(DataConstant.MYDATA_DATA_TYPE_IDENTIFICATOR,
               MyData.DEFAULT_LIST_COLUMNS,
               MyData.DEFAULT_LIST_SORT_COLUMNS,
               MyData.DEFAULT_LIST_SORT_ORDER,
               COLUMN_DEFINITIONS);
      }

      protected void getBodyDefinition(
         int          iColumnId,
         int          iCounter,
         int          iItemCounter,
         Object       objListItem,
         StringBuffer sbHtml
      )
      {
         MyData data = (MyData)objListItem;
         
         switch(iColumnId)
         {
            ...
            case(User.COL_MYDATA_NAME):
            {
               generateTableCell(sbHtml, mydata.getName(), 40, null, null);
               break;
            }
            ...   
            default:
            {
               sbHtml.append("Unknown value\n");            
               break;
            }
         }
      }
   }               
               

Before you can use this tag, you need to create taglibrary configuration file mydata.tld and then add there definition for your tag:

   <tag>
      <name>mydatalist</name>
      <tag-class>org.opensubsystems.mydata.www.MyDataListTag</tag-class>
      <body-content>empty</body-content>
      <attribute>
         <name>options</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
         <name>function</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
         <name>data</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
         <name>check</name>
         <required>false</required>
         <rtexprvalue>true</rtexprvalue>
      </attribute>
   </tag>
               

Once your taglibrary configuration file is ready, you will need to add reference to it in your web application web.xml file.

   <taglib>
      <taglib-uri>/mydata</taglib-uri>
      <taglib-location>/WEB-INF/mydata.tld</taglib-location>
   </taglib>
               

At last you can now create your own web page that allows user to browse the data page by page. The following code snippet demonstrates how the templating layout is combined with the custom JSP tag to define fully featured web page in just few lines:

   <%@ taglib uri="/mydata" prefix="mydata" %>
   <%@ taglib uri="/tiles" prefix="tiles" %>
   <%String contextpath = request.getContextPath();%>
   <%-- This page is reusing the data list layout --%>
   <tiles:insert page="/patterns/jsp/layout/datalist.jsp" flush="true">
      <tiles:put name="datalistpagetitle" value="My data"/>
      <tiles:put name="datalistloadingmessage" value="Loading list of my existing data elements..."/>
      <tiles:put name="datalisthead" direct="true">
         <link href="<%=contextpath%>/mydata/css/mydata.css" rel="StyleSheet"
               type="text/css" media="screen">      
      </tiles:put>
      <tiles:put name="datalistjscallback" value="onMyDataCallback"/>
      <tiles:put name="datalistcolumnheadings" direct="true">
         <mydata:userlist function="header" options="listoptions"/>
      </tiles:put>
      <tiles:put name="datalistmessages" direct="true"> 
         <mydata:userlist function="messages" options="listoptions"/>
      </tiles:put>
      <tiles:put name="datalistsortselect" direct="true"> 
         <mydata:userlist function="sort" options="listoptions"/>
      </tiles:put>
      <tiles:put name="datalistfilterselect" direct="true"> 
         <mydata:userlist function="filter" options="listoptions"/>
      </tiles:put>
      <tiles:put name="datalistcolumnsettings" direct="true">
         <mydata:userlist function="settings" options="listoptions"/> 
      </tiles:put>
      <tiles:put name="datalistrows" direct="true">
         <mydata:userlist function="body" options="listoptions" data="listdata"/> 
      </tiles:put>
   </tiles:insert>
               

How do I implement the mapped data pattern?

The mapped data pattern allows creation, access and management of relations between data in a generic way. For example if you have two data objects (of the same or different types), you can create link between these two data objects, associate type with the link and also attach certain amount of data to the link. You can then query these links and find out how the data are related to each other.

The pattern provides superior performance when storing and retrieving links between data objects in the relational database by creating separate tables for each subsystem managing links to its data. To take advantage of this automated persistence mechanism you have to create empty interface derived from the MappingFactory interface:

   public interface XtoYMappingFactory extends MappingFactory
   {
   }
               

This interface will be later on used to persist and retrieve data object links. Mapped data pattern provides implementation of this entire interface in the form of the MappingDatabaseFactory class. You have to create your own class derived from the MappingDatabaseFactory class to use this implementation:

   public class XtoYMappingDatabaseFactory extends MappingDatabaseFactory 
                                            implements XtoYMappingFactory
   {
      public XtoYMappingDatabaseFactory(
      ) throws OSSException 
      {
         super((XtoYMappingDatabaseSchema)DatabaseSchemaManager.getInstance(
                                              XtoYMappingDatabaseSchema.class));
      }
   }
               

In the above example we are passing to the parent class instance of the XtoYMappingSchema class that you will have to create. This class is responsible for creating all the database elements (tables, indexes, stored procedures, etc.) when the application runs for the first time. The class also provides queries to the database factory class. Fortunately you do not have to create this class from scratch since the pattern provides base class MappingDatabaseSchema that contains the entire implementation. What's left for you is to derive your own version of this class:

   public class XtoYMappingDatabaseSchema extends MappingDatabaseSchema
   {
      public XtoYMappingDatabaseSchema(
      ) throws OSSException
      {
         super("X_TO_Y", 
               XDatabaseSchema.class, getSchemaPrefix() + "X_TABLE_NAME", "ID",
               YDatabaseSchema.class, getSchemaPrefix() + "Y_TABLE_NAME", "ID");
      }
   }
               

Your application or subsystem controllers can now use all the APIs defined in the MappingFactory interface to manage and retrieve mappings between your data objects. The following code snippet demonstrates how to get access to an instance of this interface:

   m_xToYFactory = (XtoYMappingFactory)DataFactoryManager.getInstance(
                                          XtoYMappingFactory.class);               
               

The user interface and web tiers must use controller to access this API in order to follow the OpenSubsystems architecture guidelines. The pattern provides all the necessary implementation in the form of MappingController interface and MappingControllerImpl class. In a similar fashion as you did with the database factory you have to derive your own interface and implementation class:

   public interface XtoYMappingController extends MappingController
   {
   }
   
   public class XtoYMappingControllerImpl extends MappingControllerImpl 
                                          implements XtoYMappingController
   {
      public void constructor(
      ) throws OSSException
      {
      {
         m_xToYFactory = (XtoYMappingFactory)DataFactoryManager.getInstance(
                                                XtoYMappingFactory.class);               
      }
   }
               

You can now get access to the instance of the controller using following code snippet:

   m_xToYcontroller = (XtoYMappingController)ControllerManager.getInstance(
                                                XtoYMappingController.class);
               

How do I implement the ordered data pattern?

The ordered data pattern makes as its name suggests easier to manage order of data objects, especially if the order can change due to some user action. Your data object class has to implement interface OrderedData, that exposes its order number attribute. You are still responsible for persisting the order number attribute together with the rest of the attribute your data object consist of.

   public class MyData extends ModifiableDataObject
                       implements OrderedData
   {
      /**
       * Order number of this data object. 
       */
      protected int m_iOrderNumber;
   
      ...
      
      /**
       * @return int
       */
      public int getOrderNumber(
      ) 
      {
         return m_iOrderNumber;
      }
   
      /**
       * @param orderNumber - new order number
       */
      public void setOrderNumber(
         int orderNumber
      )
      {
         m_iOrderNumber = orderNumber;
      }
   }
               

In your web application tier you can use the OrderedDataUtils class to easily propagate the order of your data objects to the web page using following code snippet

   hsrqRequest.setAttribute("MYDATA" + OrderedDataUtils.ORDERED_ITEMS_POSTFIX, 
                     OrderedDataUtils.getEncodedOrder(myDataCollection));
               

This snippet creates request attribute that contains encoded order of all data objects in the specified collection. This attribute is then used by the custom JSP tags to allow user to manipulate the order of the data objects on the web page.

The easiest way to display the orderable data in your web page is using list data custom tag in a scrollable table generated using custom tags. The order of the data objects in this table can be then manipulated using four buttons Top, Up, Bottom, Down generated using custom JSP tag provided by this pattern. This is the most powerful feature of the pattern since no changes are required in the code you would have to anyway write to implement the scrollable table. The detailed description of the custom tags provided by this pattern is available in the taglig API documentation. The following code snippet demonstrates structure of a page with such table and buttons:

   The ordered data  has to be initialized to properly include CSS and JS
   this tag has to be placed before the tiles:insert specifying template derived
   from empty page layout.
   
   <ordereddata:init/>
               
   ...

   Generate buttons and hidden variable for ordering data displayed in the 
   scrollable table using single custom JSP tag supplied by the ordered data 
   pattern
   
   <dialog:row id="mydataorderbuttons">
      <ordereddata:buttons id="mydatascrollabletable" prefix="MYDATA" disabled="true"/>
   </dialog:row>
   
   ...
   
   The buttons generated above will allow user to reorder the data displayed in
   the following table
   
   <dialog:row id="mydatat">
      <scrolltbl:table id="mydatascrollabletable">
         <scrolltbl:settings>
            <mydata:mydatalist function="settings" /> 
         </scrolltbl:settings>
         <scrolltbl:header>
            <mydata:mydatalist function="header"/>
         </scrolltbl:header>   
         <scrolltbl:body summary="List of orderable data objects">
            <mydata:mydatalist function="body" data="mydatalist"/> 
         </scrolltbl:body>
         <scrolltbl:footer>
            <span id="mydatacounter">
                <logic:notEmpty name="mydatalist">
                   <%= mydatalist.size() %> data element(s) defined
                </logic:notEmpty>
                <logic:empty name="mydatalist">
                   No data elements defined
                </logic:empty>
            </span> 
         </scrolltbl:footer>
      </scrolltbl:table>
   </dialog:row>
               

Once the user is done modifying the order and submits the form back to the server, you can again use the OrderedDataUtils class in your web tier to retrieve the updated order. First, parse all the data objects user was modifying on the screen into a collection and then use following code snippet to set their updated order:

   OrderedDataUtils.updateOrder(hsrqRequest, myUpdatedDataCollection, "MYDATA");
               

When you sand the data objects to the database, the data objects will be persisted with correct order numbers so that when they are retrieved next time, their order will be preserved.

How do I implement the scrollable table pattern?

The scrollable table pattern comes in two varieties, as a templating layout and as a custom JSP tag library. The templating layout is the easiest way how to create table that fills the entire page. The page then consists of only the table header, body and a table footer. You can either link to this page and display it in the original browser, in a new window or browser tab or in an iframe. The custom tags give you more flexibility and allow you to place the scrollable table anywhere on the page. This way you can create pages that combine the scrollable table with other content or even pages that contain multiple scrollable tables.

How do I use the scrollable table layout?

The scrollable table layout allows you to easily create scrollable table than completely fills the entire page. Assuming you are familiar with the templating engine used by Open Subsystems you will need to create new JSP page that utilizes the scrollable table layout

   <tiles:insert page="/patterns/jsp/layout/scrolltable.jsp" flush="true">
      ... content of the table goes here ...
   </tiles:insert>
               

and then supply the content of the table by specifying values for all the elements required by the layout, mainly for tablecolumnheadings, tablecolumnsettings, tablebody, tablefooterleft and tablefooterright. The scrolltabletest6.jsp View source test page available in the Open Patterns demonstration distribution package represents very simple scrollable table created using this layout.

How do I use the scrollable table custom tags?

The scrollable table custom JSP tags allow high degree of flexibility when creating the scrollable table. These tags allow you to control the context in which the table exists and even combine multiple such tables in one page. The easiest way to start is to examine the provided taglig API documentation. The following code snippet demonstrates the structure of the simple scrollable table created using these custom JSP tags:

   The scrollable table has to be initialized to properly include CSS and JS
   this tag has to be placed before the tiles:insert specifying template derived
   from empty page layout.
   
   <scrolltbl:init/>
   
   ....
   
   In your methods that are hooked to onload and onresize handlers for the body
   tag you need to call the scrollble table handlers
   
   <script type="text/javascript" language="JavaScript">
      function myOnLoad()
      {   
         ...
         <scrolltbl:js id="mytable" function="onload"/>
         ...
      }
      function myOnResize()
      {   
         ...
         <scrolltbl:js id="mytable" function="onresize"/>
         ...
      }
   </script>
   
   ....
   
   Create your scrollable table at the desired location of your page
   
   <scrolltbl:table id="mytable">
      <scrolltbl:settings>
         Specify here settings to customize look of your table
      </scrolltbl:settings>
      <scrolltbl:header>
         Specify here column headings of your table
      </scrolltbl:header>   
      <scrolltbl:body>
         Specify here body of your table
      </scrolltbl:body>
      <scrolltbl:footer>
         Specify here information to display in the footer of your table
      </scrolltbl:footer>
   </scrolltbl:table>
   
   ...
               

How do I implement the tabbed dialog pattern?

The tabbed dialog pattern is implemented as a set of custom JSP tags that allow you to control the appearance, the context in which the tabbed dialog exists on the page, and even combine multiple tabbed dialogs in one page. The easiest way to start is to examine the provided taglig API documentation. The following code snippet demonstrates the structure of the simple tabbed dialog created using these custom JSP tags:

   The tabbed dialog  has to be initialized to properly include CSS and JS
   this tag has to be placed before the tile:insert specifying template derived
   from empty page layout.
   
   <tab:init/>
   
   ....
   
   Since you control the content of the tab headers, you need to configure the
   page to display them properly by setting their width and position at which
   each header starts
   
   <style type="text/css" media="screen">
      #mydialogfirstheader {
         left: 0px;
         width: 100px;
      }
      #mydialogsecondheader {
         left: 100px;
         width: 100px;
      }
   </style>
   
   ....
   
   In your methods that are hooked to onload and onresize handlers for the body
   tag you need to call the tabbed dialog handlers
   
   <script type="text/javascript" language="JavaScript">
      function myOnLoad()
      {   
         ...
         <tab:js id="mydialog" function="onload"/>
         ...
      }
      function myOnResize()
      {   
         ...
         <tab:js id="mydialog" function="onresize"/>
         ...
      }
   </script>
   
   ....
   
   Create your tabbed dialog at the desired location of your page
   
   <tab:dialog id="mydialog">
      <tab:tab id="first" header="First tab" accesskey="F" active="true">
         Specify the content of the first tab
      </tab:tab>
      <tab:tab id="second" header="Second tab" accesskey="S">
         Specify the content of the second tab
      </tab:tab>
      <tab:helptab id="help" header="? Dialog help title">
         Specify the content of the help tab, which is hidden tab that can be
         displayed programmatically for example using button created bellow.
      </tab:helptab>
   </tab:dialog>

   Here we demonstrate how you can display the hidden tab programmatically using
   JavaScript generated using tabbed dialog custom tag combined with button
   generated using the dialog layout pattern custom tag. 

   <tab:js id="mydialog" cacheas="mydialoghelp" function="ondialoghelp" 
              param1="help"/>
   <dialog:imagebutton id="mydialoghelp" cssclass="clsImageHelpTextButton"
           title="Show more information about my dialog" accesskey="H"
           onclick="cache:mydialoghelp">Help</dialog:imagebutton>
         
               

How do I implement the dialog layout pattern?

The dialog layout pattern is implemented as a set of custom JSP tags that can be divided into three parts. The first is set of tags allowing to control the layout of the web dialogs. These tags support the most common and intuitive web dialog layout that places controls into rows and columns. The tags allow to easily specify what rows contain single control and what rows are split into left and right column with a separate control in each column.

The second set of tags allows to easily create individual controls by specifying the label of the control, the control itself and the context help for the control. With minimal coding the tags immediately provide support for mnemonics, displaying of context help using mouse, keyboard or hotkey. All the elements are tied together so that there is no need to specify duplicate or related information, such as id for each one of dialog row controls elements.

The third set of tags is a group of commonly used dialog controls such as edit box, list, combo box, checkbox that are integrated with the rest of the dialog layout pattern tags. These tags also provide more complex controls that enhance user experience, such as double select list control that allows user to move items between two lists, dynamic list control that allows user to add new items to the list or modify content of the list, calendar control representing full featured calendar, etc.

The easiest way to start with the dialog layout patterns is to examine the provided taglig API documentation.

How do I layout controls within my dialog?

The dialog layout pattern allows you to place your dialog controls into rows. Each row spans by default the entire width of the enclosing container (by default the webpage). Row can be optionally split into left and right column. This makes the dialog layout and structure obvious and easy to follow. The dialog row or each of its halves can contain individual control.

   The dialog:row tag spans the entire row and can directly contain control.
                  
   <dialog:row id="myfistcontrolid">
      Specify here the control that should span the entire dialog row 
   </dialog:row>

   The dialog:splitrow tag spans the entire row but it is split into two halfs
   each one of them containing a control.
                  
   <dialog:splitrow>
      <dialog:lefthalf id="mysecondcontrolid">
         Specify here the control that should be displayed in the left half of 
         the dialog row
      </dialog:lefthalf>
      <dialog:righthalf id="mythirdcontrolid">
         Specify here the control that should be displayed in the right half of 
         the dialog row
      </dialog:righthalf>
   </dialog:splitrow>
               

When you specify id of the dialog row or its left or right half you do not have to specify id for any other element within that row since the dialog layout pattern will take care of that and automatically generate user friendly ids that tie all the elements together.

How do I construct single dialog control?

The dialog control consists of label identifying the control to which it is related, the control itself and a context help that describes the purpose and usage of the control. The mnemonic character associated with the label ensures that when user presses ALT+[mnemonic character] the focus is transferred to the associated control. The label is also presented as a clickable hyperlink, which when clicked displays associated context help. The context help can be also displayed using keyboard or hotkey ALT+F1. For example dialog control where user can enter his or her address constructed using text area would look like this:

   <dialog:label accesskey="A">Address:</dialog:label>
   <dialog:textarea name="ADDRESS"><bean:write name="userdata" property="address"/></dialog:textarea>
   <dialog:contexthelp title="? Address">
      Postal address of the user in the format that is common in the country 
      where the user using this application resides.
   </dialog:contexthelp>
               

Notice that we intentionally didn't specify id for any of the dialog control elements, since we expect this snippet to be placed within dialog row with specified id. That id will tie all the dialog control elements together.

What dialog controls are available and how do I use them?

The dialog layout pattern provides many controls that can be used within dialog row in combination with label and context help as demonstrated in the above example. Among these controls are the traditional HTML controls such as edit box, list, combo box, checkbox as well as complex controls that provide enhanced user experience, such as double select list control that allows user to move items between two lists, dynamic list control that allows user to add new items to the list or modify content of the list, calendar control representing full featured calendar. Refer to the taglig API documentation for complete up-to-date list of available controls as well as attributes that can be specified for each one of these controls.

How do I implement the background task pattern?

The background task pattern simplifies development and execution of tasks that are executed by the subsystem or application independently of user activities. The background task is represented by an object derived from BackgroundTask class. Each background task has associated setup reader, derived from SetupReader class and implementing BackgroundTaskSetupReader interface. The setup reader allow to configure default settings for the background task as well as configure specific setting for each concurrent instance of the background task. At last, the pattern provides web application listener base class BackgroundTaskListener that allows to initiate the background task execution.

When you have a need to implement an automatic task that runs without user intervention, you will derive new classes from each of the mentioned base classes. If the background task is part of a web application you will then configure the listener in your web.xml file using the listener element:

   <listener>
      <listener-class>full class name of your BackgroundTaskListener derived class</listener-class>
   </listener>