Skip to Content

iGoogle Gadget (featuring UWL,BPM,JSON & OAuth) – Part 1

Introduction


On november 20th I joined the SAP Inside Track Netherlands 2010 to present my iGoogle Gadget at the Demo Jam.
I created a gadget that shows the Universal Worklist tasks of a user on my iGoogle start page.

This is how the end result looked at the Demo Jam:

 

To do this in a secure way i used the OAuth protocol for authentication and authorization, which is also commonly used by Twitter and Facebook.

In this weblog I want to show you how i have developed this OAuth Provider on SAP NetWeaver CE 7.2 and created an iGoogle Gadget for consuming data from that OAuth provider.
Used in this demo:

NetWeaver CE 7.2 Trial Version, which you can download from SDN (your server should be accessible from the internet so that iGoogle can access your application)

An existing BPM Process with Tasks and Users running on CE 7.2. There are some great tutorials on SDN which you can use. I used this tutorial

    1. iGoogle Account for the creating and testing the iGoogle Gadget

The weblog will consists of three parts:
1. Introduction + initial setup and retrieving the BPM Task from the UWL
2. Create an OAuth Provider on NetWeaver CE
3. Create the iGoogle Gadget for consuming the data

h3. Retrieving BPM Tasks from the UWL

To create the applications we need we will use a new Software Component in the Development Infrastructure.
In NetWeaver Developer Studio go to the Development Infrastructure Perspective and right-click on “Local Development” and select “Create Software Component”. You can use the attributes below:

!https://weblogs.sdn.sap.com/weblogs/images/252125299/CreateSC.PNG|height=448|alt=image|width=396|src=https://weblogs.sdn.sap.com/weblogs/images/252125299/CreateSC.PNG|border=0!

Click Next and select the following dependencies:

ENGFACADE sap.com

SAP_BUILDT sap.com

UWLJWF sap.com

Click Finish. Note: You may have to download the UWLJWF.sca file from http://service.sap.com and import it into your NWDS and deploy it on your server.

h3. Create Development Components

In the newly created SC create the following Development Components:

    1. oauth/lib (External Library)
    2. oauth/provider/web (Java EE Web Module)
    3. oauth/provider/ear (Java EE Enterprise Application)

In the Component properties go to the Dependencies tab and add the dependencies for the two development components:

oauth/provider/web: tc/je/usermanagement/api, tc/kmc/bc.uwl/api, tc/bl/exception/lib and oauth/lib (all build time)
oauth/provider/ear: tc/kmc/bc.uwl/api (build time and run time)

h3. OAuth Libraries

In part 2 of this weblog we will start using OAuth. The libraries are not available for download as binaries so we have to generate the binaries ourself with Maven. 
Follow the instructions below to create the jar files:

Download maven from http://maven.apache.org/download.html
Follow the instructions on the download page to configure Maven for your machine (you probably need to set JAVA_HOME).

    1. Check out the java code and maven repository to temporary directory with:

svn co https://oauth.googlecode.com/svn/code/java java
svn co https://oauth.googlecode.com/svn/code/maven maven

Add the jar files to the public parts api and archives: Right click onthe jar files and select Development Component -> Publish as Archive.
!https://weblogs.sdn.sap.com/weblogs/images/252125299/APIArchives.PNG|height=293|alt=image|width=377|src=https://weblogs.sdn.sap.com/weblogs/images/252125299/APIArchives.PNG|border=0!

Now it’s time for the coding part:

h3. Retrieving the BPM tasks

In the DC oauth/provider/web start with creating a class which represents a Task object. ();
 
            try {
                 // Look up UWL service
                 IUWLService uwlService = getUWLService();
                 // Session timeout period
                 final int sessionIdleTimeout = 200;
 
                 UWLContext uwlContext = new UWLContext();
                 
                 // Find logged in user.
                 IUser user = UMFactory.getAuthenticator().getLoggedInUser();
                 uwlContext.setUser(user);
 
                 Locale locale = user.getLocale();
                 if (locale == null) {
                      locale = new Locale(“en”);
                 }
                 uwlContext.setLocale(locale);
 
                 // Begin session
                 IUWLSession uwlSession;
                 uwlSession = uwlService.beginSession(uwlContext, sessionIdleTimeout);
                 uwlContext.setSession(uwlSession);
                 IUWLItemManager itemManager = uwlService.getItemManager(uwlContext);
 
                 QueryResult result = itemManager.getItemsForItemType(uwlContext, ItemType.UWL_ITEM_TASK, null, null);
 
                 ItemCollection items = result.getItems();
                 Item item = null;
                 for (int i = 0; i < items.size(); i++) {
                      item = items.get(i);
 
                      UWLTask task = new UWLTask();
                      task.setId(i);
                      if (item.getDueDate() != null)
                      task.setDueDate(item.getDueDate().getTime());
                      task.setSubject(item.getSubject());
                      task.setPriority(textByKey(locale, “PRIORITY_” + item.getPriority().getText()));
                      task.setStatus(textByKey(locale, “STATUS_” + item.getStatus().getText()));
                      if (item.getCreatedDate() != null)
                      task.setSendDate(item.getCreatedDate().getTime());
 
                      String executionURL = host
                                + “/webdynpro/dispatcher/sap.com/tcbpemwdui~taskinstance/ATaskExecution?taskId=”
                                + item.getExternalId().substring(0, item.getExternalId().lastIndexOf(‘@’));
                      task.setExecutionUrl(executionURL);
 
                      tasks.add(task);
                 }
 
            } catch (Exception e) {
                 e.printStackTrace();
            }
            return tasks;
       }
       
       private IUWLService getUWLService() throws NamingException {
            Properties env = new Properties();
            env.put(InitialContext.INITIAL_CONTEXT_FACTORY, “com.sapportals.portal.prt.registry.PortalRegistryFactory”);
            // create initial context
            InitialContext ctx = new InitialContext(env);
            // retrieve UWL service
            IUWLService uwlService = (IUWLService) ctx.lookup(“/broker/services/” + IUWLService.ALIAS_KEY);
            return uwlService;
       }
 
       private String textByKey(Locale locale, String key) {
            String textMessage = null;
            try {
                 UWLTaskResourceAccessor ra = new UWLTaskResourceAccessor(BUNDLE_NAME);
                 textMessage = ra.getMessageText(locale, key);
            } catch (MissingResourceException e) {
                 e.printStackTrace();
            }
            return textMessage;
       }
  }
 
 

Some explanation about the UWLTaskService code above: The IUWLService is retrieved by looking it up via JNDI. This is why we need the reference to tc/kmc/bc.uwl/api for both the web and ear module.

Properties env = new Properties();
env.put(InitialContext.INITIAL_CONTEXT_FACTORY, "com.sapportals.portal.prt.registry.PortalRegistryFactory");
// create initial context
InitialContext ctx = new InitialContext(env);
// retrieve UWL service
IUWLService uwlService = (IUWLService) ctx.lookup("/broker/services/" + IUWLService.ALIAS_KEY);

With

IUser user = UMFactory.getAuthenticator().getLoggedInUser();

we retrieve the current logged-in user and with the following code we can retrieve the UWL Tasks assigned to that user.

IUWLSession uwlSession;
uwlSession = uwlService.beginSession(uwlContext, sessionIdleTimeout);
uwlContext.setSession(uwlSession);
IUWLItemManager itemManager = uwlService.getItemManager(uwlContext);

QueryResult result = itemManager.getItemsForItemType(uwlContext, ItemType.UWL_ITEM_TASK, null, null);

After that we loop through the results and put it in a java List as a UWLTask object. Because the status and priority values from the UWL API are formatted in uppercase like INPROGRESS and NORMAL value, we have to convert them to nicely formatted values. In the standard Web Dynpro application this done by using resource bundles. A few weeks ago I discoverd the blog from Matthias Steiner describing a way to load resource bundles from another application. You can find the blog over here: I18N | How-to support custom resource bundles (on NWCE)

Let’s use this and extend the ResourceAccessor class. Create a new class UWLTaskResourceAccessor with the following implementation:

package nl.ciber.uwl.task;

import com.sap.localization.ResourceAccessor;

public class *UWLTaskResourceAccessor *extends ResourceAccessor {
   
    public UWLTaskResourceAccessor(String bundleName) {
        super(bundleName);
    }
   
}

This way in the UWLTaskService class the resource bundle com.sap.netweaver.bc.uwl.ui.i18n.TextMessages can be used to retrieve the right values for status and priority see here:**

private static final String BUNDLE_NAME = "com.sap.netweaver.bc.uwl.ui.i18n.TextMessages";>

private String textByKey(Locale locale, String key) {
String textMessage = null;
try {
UWLTaskResourceAccessor ra = new UWLTaskResourceAccessor(BUNDLE_NAME);
textMessage = ra.getMessageText(locale, key);
} catch (MissingResourceException e) {
e.printStackTrace();
}
return textMessage;
}

In the application-j2ee-engine.xml file we add the weak-reference to tckmcbc.uwl.ui~wd_ui. So that the resourcebundle can be found from our applicationtckmcbc.uwl.uiwd_ui</reference-target><br />  </reference></pre><p>The link to the BPM tasks is also stored in the task object and is constructed like this:</p><pre>String executionURL = host<br />                             + “/webdynpro/dispatcher/sap.com/tcbpemwduitaskinstance/ATaskExecution?taskId=”
                        + item.getExternalId().substring(0,item.getExternalId().lastIndexOf(‘@’));

The basic part for retrieving tasks is now finished. For testing the service and not make this first blog to extensive, we will write a simple test servlet to see if we can retrieve tasks from the Universal Worklist. Create a new Servlet by right clicking on the “Java resource: source” folder and select New -> Servlet

image
Fill in the name of the servlet and the package and click Finish.

h3. JSON

For the communication between the iGoogle Gadget and the OAuth provider i use JSON. JSON is a lightweight data interchange format and is excellent for using with an iGoogle Gadget which we will see in part 3 of this blog.

More info on JSON you can find here: http://json.org

To use JSON in our project we download the java classes from http://www.json.org/java/json.zip and unzip them in the “Java resource: source” folder of our Web Module. 

!https://weblogs.sdn.sap.com/weblogs/images/252125299/JSON.png|height=212|alt=image|width=262|src=https://weblogs.sdn.sap.com/weblogs/images/252125299/JSON.png|border=0!

Next the implementation of our test servlet to retrieve the tasks.
Create a new Servlet with NetWeaver Developer Studio. Right click on your Web project and select New -> Servlet.

    package nl.ciber.task.uwl.task.servlet;
   
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.List;
   
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
   
    import nl.ciber.uwl.task.UWLTask;
    import nl.ciber.uwl.task.UWLTaskService;
   
    import org.json.JSONArray;
   
    import com.sap.security.api.UMFactory;
    import com.sap.security.api.logon.ILoginConstants;
   
    /**
    

  1. Servlet implementation class RetrieveTasksServlet

     */
    public class RetrieveTasksServlet extends HttpServlet {
         private static final long serialVersionUID = 1L;
          
        /**
        

  1. @see HttpServlet#HttpServlet()

         */
        public RetrieveTasksServlet() {
            super();
        }
   
         /**
         

  1. @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

          */
         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              UWLTaskService service = new UWLTaskService();
              PrintWriter out = response.getWriter();
              
              try {
                   UMFactory.getLogonAuthenticator().logon(request, response, null);
              } catch (Exception e) {
                   e.printStackTrace();
                   out.println(e.toString());
              }
              
              String serverName = request.getServerName();
              String host = “http://” + serverName + “:” + request.getServerPort();
              
              // Retrieve Tasks
              Listciber.nloauthprovider~web.wartask_retrieval

Now deploy the ear-file from NetWeaver Developer Studio and open the servlet in a browser.

Login with a user which has some tasks in his Universal Worklist and the JSON output should look like this:

!https://weblogs.sdn.sap.com/weblogs/images/252125299/JSONResult.png|height=205|alt=image|width=606|src=https://weblogs.sdn.sap.com/weblogs/images/252125299/JSONResult.png|border=0!

In part 2 we will create the OAuth Provider to add authentication and authorization to our application.

/
image
9 Comments
You must be Logged on to comment or reply to a post.