3.2 Creating a Task: An Example

To show how to create a task plug-in, we will use the BasicTaskExample sample task that is included in the iManager 2.7 SDK. The source files for the sample plug-ins are in SDK_HOME/samples/src. For information on how to build the sample plug-ins, see Section 1.4, Building the Sample Plug-Ins.

This section contains information on the following:

3.2.1 Creating the Java Class

To create a Java class for your task, extend the com.novell.emframe.dev.Task class and override its execute(TaskContext context, Properties resultStrings) method. The BasicTaskExampleTask.java sample task shows how to do this:

 package com.company.plugins;
 
 import com.novell.emframe.dev.*;
 import java.util.Properties;
 
 public class BasicTaskExampleTask extends Task
 {
   public boolean execute(TaskContext context, Properties resultStrings)
   {
     setUIPage("sdk/BasicTaskExampleTemplate.jsp");
     return true;
   }
 }
 

The execute method calls the inherited setUIPage(String UIPage) method to tell iManager which JSP to load in the content area of the iManager UI. You can add conditional statements to specify different JSPs for different task states. Tasks might have states that correspond with steps in the flow of the UI. For example, suppose a task has an initial page that asks for the name of an object that is to be created. After entering a name and clicking a Create button, users proceed to the next step in which they are presented with either a confirmation message or a message indicating that an error ocurred. A Cancel button causes the task to end without creating the object.

The execute method should

  • Check the value of the nextState parameter from the HTTP request, if the task has more than one state.

  • Perform any processing required for the current state.

  • Set the next JSP by calling setUIPage(String UIPage).

The following example shows how you might modify the BasicTaskExampleTask.java file so that it can handle two states:

 package com.company.plugins;
 
 import com.novell.emframe.dev.*;
 import java.util.Properties;
 import javax.servlet.http.HttpServletRequest;
 
 public class BasicTaskExampleTask extends Task
 {
   private HttpServletRequest req = null;
 
   public boolean execute(TaskContext context, Properties resultStrings)
   {
     req = context.getRequest();
     String nextState = req.getParameter(eMFrameConsts.NEXTSTATE);
 
     if (nextState.equalsIgnoreCase(eMFrameConsts.INITIALSTATE))
     {
       setUIPage("sdk/BasicTaskExampleTemplate.jsp");
     }
     else if(nextState.equalsIgnoreCase("state2"))
     {
       req.setAttribute("paramName","paramValue");
       setUIPage("sdk/BasicTaskExampleTemplate2.jsp");
     }
     return true;
   }
 }
 

In the preceding example, the eMFrameConsts.NEXTSTATE parameter is set to the current state of the task. If the task is in its initial state, the initial JSP is set. If the task is in state 2, the JSP for state 2 is set. Note that the initial JSP must specify the next state of the task. This is typically done using a hidden input field named nextState:

 <INPUT type="hidden" name="nextState" value="state2">
 

Use the methods of the HttpServletRequest class, such as getAttribute(String name) or getParameter(String name), to retrieve data from the JSP, as shown in the preceding example. To send data to the JSP, use HttpServletRequest.setAttribute(String name, Object o).

The preceding examples do little more than display a UI. To add the business logic required by your task, you might add methods to your class or create other classes. The following example adds a doSomething method to the BasicTaskExampleTask sample task:

 package com.company.plugins;
 
 import com.novell.emframe.dev.*;
 import java.util.Properties;
 import javax.servlet.http.HttpServletRequest;
 
 public class BasicTaskExampleTask extends Task
 {
   private HttpServletRequest req = null;
 
   public boolean execute(TaskContext context, Properties resultStrings)
   {
     req = context.getRequest();
     String nextState = req.getParameter(eMFrameConsts.NEXTSTATE);
 
     if (nextState.equalsIgnoreCase(eMFrameConsts.INITIALSTATE))
     {
       setUIPage("sdk/BasicTaskExampleTemplate.jsp");
     }
     else if(nextState.equalsIgnoreCase("state2"))
     {
       String value = doSomething();
       req.setAttribute("paramName",value);
       setUIPage("sdk/BasicTaskExampleTemplate2.jsp");
     }
     return true;
   }
 
   private String doSomething()
   {
     String result = "paramValue";
     return result;
   }
 }
 

3.2.2 Creating the UI

To create the UI for a task, create one or more JSPs. Use the JSPs to display forms, instructions, and the results of the processing performed by your task. Avoid putting the business logic of your task in the JSP. The SDK_HOME/samples/web/portal/modules/skd/skins/default/devices/default/BasicTaskExampleTemplate.jsp file shows the JSP for the BasicTaskExample sample task:

 <%@  page pageEncoding="utf-8" contentType="text/html;charset=utf-8" %>
 
 <%@ taglib uri="/WEB-INF/iman.tld" prefix="iman" %>
 <%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
 <%@ taglib uri="/WEB-INF/x.tld" prefix="x" %>
 
 <iman:stringtable bundle="DevResources"/>
 <iman:stringtable bundle="FwResources"/>
 
 <HTML>
 <HEAD>
   <TITLE><iman:string key="ProductName"/></TITLE>
   <LINK rel="stylesheet" href="<c:out value="${ContextPath}" />/portal/modules/dev/css/hf_style.css">
   <iman:eMFrameScripts/>
 </HEAD>
 
 <BODY>
   <iman:taskHeader title="Basic Task Example"/>
   This task simply exposes the minimum code needed to create an iManager task, specifically: Java code, JSP template, XML install file, and a Properties file for string management.
   <br>
   <br>
   The code for this task can be found in the "BasicTaskExample" folder found in the iManager SDK.
   <BR><BR>
   <iman:bar/>
   <iman:button key="OK" type="input"/>
   <iman:cancelBtn/>
 </BODY>
 </HTML>
 

This example does nothing more than display text. It uses the iman tag library to insert common UI elements: a header, a horizontal rule, an OK button, and a Cancel button.

The following example shows how you might modify BasicTaskExampleTemplate.jsp to enable the BasicTaskExample task to handle two states:

 <%@  page pageEncoding="utf-8" contentType="text/html;charset=utf-8" %>
 
 <%@ taglib uri="/WEB-INF/iman.tld" prefix="iman" %>
 <%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
 <%@ taglib uri="/WEB-INF/x.tld" prefix="x" %>
 
 <iman:stringtable bundle="DevResources"/>
 <iman:stringtable bundle="FwResources"/>
 
 <HTML>
 <HEAD>
   <TITLE><iman:string key="ProductName"/></TITLE>
   <LINK rel="stylesheet" href="<c:out value="${ContextPath}" />/portal/modules/dev/css/hf_style.css">
   <iman:eMFrameScripts/>
 </HEAD>
 
 <BODY>
   <iman:taskHeader title="Basic Task Example - State 1"/>
   This is the UI for the first state of the task.
   <BR><BR>
   <form name="next" method="post" action="webacc?Autoparse=true" enctype="multipart/form-data">
     <INPUT type="hidden" name="error" value="dev.GenErr">
     <INPUT type="hidden" name="User.context" value="<c:out value="${User.context}" />">
     <INPUT type="hidden" name="taskId" value="sdk.BasicTaskExampleTask">
     <INPUT type="hidden" name="nextState" value="state2">
     <iman:bar/>
     <iman:button key="Next" type="input"/>
     <iman:cancelBtn/>
   </form>
 </BODY>
 </HTML>
 

This version encloses Next and Cancel buttons in a form element, and it uses hidden input fields to pass data back to the task Java class. The nextState field identifies the next state of the task. The Java class uses the value of the nextState parameter to determine which state it is in so it can display the JSP for the current state.

The following example is the JSP for the second state of the task, which displays the data passed to it from the Java class:

 <%@  page pageEncoding="utf-8" contentType="text/html;charset=utf-8" %>
 
 <%@ taglib uri="/WEB-INF/iman.tld" prefix="iman" %>
 <%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
 <%@ taglib uri="/WEB-INF/x.tld" prefix="x" %>
 
 <iman:stringtable bundle="DevResources"/>
 <iman:stringtable bundle="FwResources"/>
 
 <HTML>
 <HEAD>
   <TITLE><iman:string key="ProductName"/></TITLE>
   <LINK rel="stylesheet" href="<c:out value="${ContextPath}" />/portal/modules/dev/css/hf_style.css">
   <iman:eMFrameScripts/>
 </HEAD>
 
 <BODY>
   <iman:taskHeader title="Basic Task Example - State 2"/>
   This is the UI for the second state of the task.
   <BR><BR>
   Param: <c:out value="${paramName}"/>
   <BR><BR>
   <iman:bar/>
   <iman:button key="OK" type="input"/>
 </BODY>
 </HTML>
 

The JSP for the second state uses the c tag library to print the value of the paramName parameter.

3.2.3 Creating the Registration File

Tasks and other plug-ins must be registered with iManager. You register a plug-in by creating an XML file that describes the plug-in and placing the file in the appropriate directory. A single registration file can contain descriptions for multiple tasks. The registration file for the sample plug-ins is SDK_HOME/samples/web/portal/modules/sdk/install/iManagerCodeExamplesInstall.xml:

 <install>
   <module>
     <id>sdk</id>
     <version>2.0.1</version>
     <required-version>2.7.0</required-version>
     <resource-properties-file>com.company.plugins.iManagerCodeExamplesResources</resource-properties-file>
     <display-name-key>iManagerCodeExamples.InstallDisplayName</display-name-key>
     <description-key>iManagerCodeExamples.Description</description-key>
   </module>
   <role>
     <id>iManager Code Examples</id>
     <version>2.0.0</version>
       <display-name-key>iManagerCodeExamples.RoleDisplayName</display-name-key>
     <resource-properties-file>com.company.plugins.iManagerCodeExamplesResources</resource-properties-file>
   </role>
   <task>
     <id>sdk.BasicTask</id>
     <version>2.0.0</version>
     <required-version>2.7.0</required-version>
     <class-name>java:com.company.plugins.BasicTaskExampleTask</class-name>
     <display-name-key>BasicTaskExample.TaskDisplayName</display-name-key>
     <description-key>BasicTaskExample.Description</description-key>
     <resource-properties-file>com.company.plugins.iManagerCodeExamplesResources</resource-properties-file>
     <role-assignment>iManager Code Examples</role-assignment>
   </task>
 
   . . . (Other tasks removed)
 
 </install>
 

This registration file defines a module, a role, and the sample tasks. The definitions use the <id> tag to specify the ID of the module, role, and tasks. The task definitions use the ID of the role (“iManager Code Examples”) as the value of the <role-assignment> tag to specify that the tasks are assigned to the role:

 <role-assignment>iManager Code Examples</role-assignment>
 

The task ID should use the module ID as a prefix to its ID. For the BasicTaskExample task, the ID is:

 <id>sdk.BasicTask</id>
 

The module ID is the name of the directory under SDK_HOME/tomcat/webapps/nps/portal/modules where iManager expects to find files for plug-ins that are part of the module. For more information about modules, see Section 2.4, Module ID.

The definition of the BasicTaskExample task includes several other tags besides ID. The <id>, <version>, <required-version>, and <class-name> tags are required. The <version> tag is used to specify the task version. The <required-version> tag specifies the version of iManager that the task requires. The <class-name> tag identifies the Java class for the task.

For more information about registration files, see Section 3.5, Creating Registration Files. For more information about the available elements for registration files, see Section 12.2, XML Schema for Installation and Registration Files.

3.2.4 Localizing the Task

To localize your task, you need to

  • Create properties files that contain translated strings.

  • Specify the name of the default properties file in the task registration file.

The registration file for BasicTaskExample includes a <resource-properties-file> element, which identifies a properties file that contains strings used by the task:

 <resource‑properties‑file>com.company.plugins.iManagerCodeExamplesResources</resource‑properties‑file>
 

Multiple plug-ins can share a properties file and the strings it contains. The SDK_HOME/samples/resources/com/company/plugins/iManagerCodeExamplesResources.properties file contains strings for most of the SDK sample plug-ins. The strings in the properties file are in the default language for the task, organized in key-value pairs. For example, iManagerCodeExamplesResources.properties contains the following entry:

 BasicTaskExample.TaskDisplayName=Basic Task Example
 

You can insert this string in your JSP by referencing the key:

 <iman:string key="BasicTaskExample.TaskDisplayName"/>
 

In fact, iManager uses the <display-name-key> and <description-key> elements of registration files to retrieve the task display name and description:

 <display-name-key>BasicTaskExample.TaskDisplayName</display-name-key>
 <description-key>BasicTaskExample.Description</description-key>
 

To retrieve localized strings, you must create a properties file for each language you want to support, including English. The keys are not translated, but the values change for each language. For each translated properties file, name it by appending an undescore and the language code to the name of the default properties file before the .properties extension. For example, a Spanish version of iManagerCodeExamplesResources.properties would be named iManagerCodeExamplesResources_es.properties.

iManager automatically selects the string value from the appropriate properties file, based on the language settings of the browser.

For a complete example, see the StringLocalizationExample sample task included in the SDK.

3.2.5 Deploying the Task

To deploy a task, you must copy the task files to several locations in the iManager directory structure, depending on the file type, as explained in the following table:

Table 3-1 iManager task file locations

File Type

Location

Java class and properties files

If your class and properties files are in a JAR file, copy the JAR file to webapps/nps/WEB-INF/lib; otherwise, copy them to webapps/nps/WEB-INF/classes.

JSPs

Copy JSPs to webapps/nps/portal/modules/module_id/skins/skin_name/devices/device_name.

Registration files

Copy <install> registration files to webapps/nps/portal/modules/module_id/install. Copy <plugin> registration files to webapps/nps/portal/modules/module_id/plugins.

Other files

If you have other files, such as UI pages, JavaScript, and images, copy them to subdirectories of webapps/nps/portal/modules/module_id. Follow the pattern used by the modules that ship with iManager.

The sample tasks included in the SDK are deployed automatically when you use the build script included with the SDK.