Friday, May 27, 2011

Setting up Task List portlets in WebCenter

The Task List is a standard JSR-168 portlet that allows you to check the ToDo tasks and take actions on those. Since the task list is a WSRP portlet producer application, it must be deployed on a managed server configured as a portlet container, such as WC_Portlet.
The objective of this post is to have a Cookbook format. The same steps can be found in Oracle’s documentation, except for some caveats and  images that should smooth the process.

Steps

image

The picture above describes the deployment architecture as well as some basic interaction between the involved managed servers. Please notices that we have two different domains in the picture.

Deploying Task List Portlet
1. Because the task list portlet producer application uses the deployed library oracle.soa.workflow.wc, you must confirm that the library is targeted to the Oracle WebLogic Server portlet managed server.
a. Log in to Oracle WebLogic Server Administration Console.
b. Go to Deployments > oracle.soa.workflow.wc >Targets.
c. See if WLS_Portlet is checked. If not, check it and save your updates.
image

2. In WebCenter PS3 there’s a shared lib issue. You also need to deploy rules.jar as a shared library in WC_Portlet. You can find rules.jar under <JDEV_INSTALL>/jdeveloper/soa/modules/oracle.rules_11.1.1/rules.jar.

3. Deploy the TaskListPortlet.ear file WC_Portlet.
a. You can find it under /Oracle_Home/SOA_Home/soa/applications/TaskListPortlet.ear.
b. Ensure that the WSRP producer application is running by accessing the WSDL from a web browser http://server:port/TaskListPortlet/portlets/wsrp2?WSDL.

Connecting Task List Producer to SOA Server

The next step is to configure the remote JNDI providers on WebCenter. As mentioned before, the task list portlet bring the info from SOA server through remote EJB calls.



1. Log in to WLS Console and navigate to Domain Structure > Services > Foreign JNDI Providers.
a. Click New. In the Name field, enter ForeignJNDIProvider-SOA, target it to WC_Portlet, and click OK.
b. Click the ForeignJNDIProvider-SOA link and enter the values in the table below.


Initial Context Factory weblogic.jndi.WLInitialContextFactory
Provider URL t3://[soa_hostname]:[port]/soa-infra
User weblogic
Password Enter weblogic password.
Confirm Password Password confirmation.
image
2. Click the Links tab. Under Foreign JNDI Links, click New. Now enter the same values on the table below to Name, Local JNDI Name, and Remote JNDI Name.
RuntimeConfigService
ejb/bpel/services/workflow/TaskServiceBean
ejb/bpel/services/workflow/TaskMetadataServiceBean
TaskReportServiceBean
TaskEvidenceServiceBean
TaskQueryService
UserMetadataService
image

 

Configuring EJB Identity Propagation

We’ll start by enabling global trust. Log in to the WLS Adm Console for WebCenter.

On the left side of the page, click on Domain > Security > Advanced and modify the domain credentials.

image

Log in to the SOA server Admin Console and modify the domain credentials to the same password as entered for WebCenter.
Regarding application authorization, the same user logged-in to the Spaces application must be present in the Porlet and SOA identity stores, or the three servers could point to the same identity store. For this post we have OID setup as the common identity store. For more info please see Oracle doc.

Securing the Task List Portlet Producer Application Using Web Services Security

We’ll start by enabling WS-Security for the task list portlet producer application.
1. Open Oracle Enterprise Manager.

2. In the navigator on the left side, select Farm_wc_domain > WebLogic Domain.

3. Right-click wc_domain and select Security > Security Provider Configuration.
image
4. Access the Keystore section at the bottom of the provider configuration page and click Configure.

image
a. Let’s generate the keystore.
keytool -genkeypair -keyalg RSA -alias orakey -keypass welcome1 -keystore default-keystore.jks -storepass welcome1 -validity 3600

image
b. Copy default-keystore.jks file to WEBCENTER_DOMAIN/config/fmwconfig.
c. Enter the details for keystore management and identity certificates as shown below.
image

d. Click OK.
e. Restart WC_Portlet and AdminServer in the WebCenter domain.
f. Follow the same steps starting at b, but now for the SOA domain. To make your life easier we’ll use the same default-keystores.jks file, which means that you don’t need to run the keytool command again.


Specifying the Inbound Security Policy

1. Open Oracle Enterprise Manager.

2. Right-click Application Deployments > TaskListPortlet (WC_Portlet).

image

3. Select Web Services.

4. Click on WSRP_v2_Markup_Service.

image
5. Attach oracle/wss10_saml_token_with_message_protection_service_policy.

image

6. Click OK.

7. Restart WC_Portlet.


Consuming Task List Portlet from WebCenter Spaces

1. Right-click Farm_wc_domain > WebCenter > WebCenter Spaces > webcenter. Select Settings > Service Configuration.

image

2. Register a new portlet producer with the following information.

image

3. Once the portlet producer is successfully register, open WebCenter Spaces and drop the portlet into any page. That’s how it should look like.

image

You can double check your task list content by logging in into Business Process Workspace with the same user, obviously. You should see the same tasks.

image

Monday, May 23, 2011

WebCenter domain configuration for WebCenter Spaces APIs

While using your WebCenter Portal application, users may encounter situations where a Space would be useful to help them complete a particular task. In such cases, it would be much less disruptive to remain within the context of the current application, rather than having to switch to the WebCenter Spaces application. To this end, WebCenter Spaces provides access to a subset of its Space functionality through several APIs. Using these APIs, you can integrate powerful Space functionality into your WebCenter Portal application.
You can use WebCenter Spaces APIs to:
  • Create and manage Spaces and Space templates. You can create and delete Spaces, and add custom attributes. For more information, see (WebCenter Developer's Guide) Section 50.2.5.1, "Managing Spaces and Space Template."Manage Space membership.
  • You can add and remove Space members. For more information, see (WebCenter Developer's Guide) Section 50.2.5.2, "Managing Space Membership."
  • Retrieve information about Spaces and Space templates. For example, you can retrieve the WebCenter Spaces URL or the URL of a specific Space. You can also retrieve Space and Space template metadata. For more information, see (WebCenter Developer's Guide) Section 50.2.5.3, "Retrieving Information for Spaces and Space Templates."

WebCenter Spaces APIs are contained within several classes. For more information on the different classes with descriptions on the purpose of the APIs within each class, see Table 50-1 in the WebCenter Developers Guide.  In this post I will explain how to set up your portal application, and how to prepare your environment to support using the WebCenter Spaces APIs.

The first step describes the administrator tasks required to configure WS-Security for WebCenter Spaces so that the communication between the an application exposing WebCenter Spaces APIs (the client) and WebCenter Spaces (the producer) is secure, and that the identity of the user invoking the APIs is protected. In this section I will give examples of only the actual commands. If you would like more information on each of the command arguments are, please see Section 32 in the WebCenter Administration Guide.

Creating the WebCenter (Producer) Domain Keystore

To create and manage the keys and certificates in the JKS, use the keytool utility that is distributed with the Java JDK 6. Using keytool, generate a key pair:

keytool -genkeypair -keyalg RSA -dname "cn=spaces,dc=example,dc=com" -alias webcenter -keypass welcome1 -keystore webcenter.jks -storepass welcome1 -validity 1064

Export the Certificate containing the public key

keytool -exportcert -v -alias webcenter -keystore webcenter.jks -storepass welcome1 -rfc -file webcenter_public.cer

Importing the Certificate

keytool -importcert -alias webcenter_public -file webcenter_public.cer -keystore webcenter.jks -storepass welcome1

Note: If you are deploying your application to the same domain, you do not have to create the client keystore and keys. However, if the client is in a different domain, for example, testing your application in JDeveloper embedded WebLogic Server, you will need to do the next steps.

Creating the JDeveloper (Client) Domain Keystore

keytool -genkeypair -keyalg RSA -dname "cn=external_webcenter_custom,dc=example,dc=com" -alias external_webcenter_custom -keypass welcome1 -keystore external_webcenter_custom.jks -storepass welcome1 -validity 1024

Export the Certificate containing the public key

keytool -exportcert -v -alias external_webcenter_custom -keystore external_webcenter_custom.jks -storepass welcome1 -rfc -file external_webcenter_custom_public_key.cer

Import the Certificates

keytool -importcert -alias external_webcenter_custom_public_key -file external_webcenter_custom_public_key.cer -keystore webcenter.jks -storepass welcome1

This step is IMPORTANT as it contains the certificate from the WebCenter Domain

keytool -importcert -alias webcenter_public -file webcenter_public.cer -keystore external_webcenter_custom.jks -storepass welcome1

Once that is done you should have created 2 keystores, (producer) webcenter.jks (alias=webcenter) and (client) external_webcenter_custom.jks (alias=external_webcenter_custom). Pay close attention to the client alias name. This name is important as it will be used as a parameter in Spaces API code.  The next steps are to register the keystores with both the WebCenter domain and JDeveloper (client) domain. This is a 2 step process. The first step is to modify the jps-config,xml and then use WLST to update the security credentials. Note before doing any of the proceeding modifications, be sure to BACK UP both the jps-config.xml and the cwallet.sso files.

Register Keystore in WebCenter (producer) Domain

Copy the keystore that you created for the WebCenter domain (webcenter.jks) to the fmwconfig directory. This directory is located in the [Oracle_Home]/user_projects/domains/[wc_domain]/config directory. In the same directory, open the jps-config.xml in a text editor. In this file, locate the "serviceInstance" node for the keystore.provider Provider: Update the "location" property for the new file name (i.e ./webcenter.jks).

serviceInstance name="keystore" provider="keystore.provider" location="./webcenter.jks" 

Update Security Credentials in WSLT

Invoke WLST from [webcenter_home]/common/bin. Execute the following commands, note that the user= references the alias name (webcenter):

updateCred(map="oracle.wsm.security", key="keystore-csf-key", user="owsm", password="welcome1", desc="Keystore key")


updateCred(map="oracle.wsm.security", key="enc-csf-key", user="webcenter", password="welcome1", desc="Encryption key")


updateCred(map="oracle.wsm.security", key="sign-csf-key", user="webcenter", password="welcome1", desc="Signing key")

Register Keystore in JDeveloper (client) Domain

Copy the keystore that you created for the JDeveloper domain (external_webcenter_custom.jks) to the fmwconfig directory. This directory is located in the [JDeveloper_sys_home]/DefaultDomain/config directory. For example, on my systems this location is:

C:\Users\[your-user]\AppData\Roaming\JDeveloper\system11.1.1.4.37.59.23\DefaultDomain\config\fmwconfig

In the same directory, open the jps-config.xml in a text editor. In this file, locate the "serviceInstance" node for the keystore.provider Provider: Update the "location" property for the new file name (i.e ./external_webcenter_custom.jks).

serviceInstance name="keystore" provider="keystore.provider" location="./external_webcenter_custom.jks"

Update Security Credentials in WSLT

Invoke WLST from [JDeveloper_Home]/oracle_common/common/bin. Execute the following commands, note that the user= references the alias name (external_webcenter_custom):

updateCred(map="oracle.wsm.security", key="keystore-csf-key", user="owsm", password="welcome1", desc="Keystore key")

updateCred(map="oracle.wsm.security", key="enc-csf-key", user="external_webcenter_custom", password="welcome1", desc="Encryption key")

updateCred(map="oracle.wsm.security", key="sign-csf-key", user="external_webcenter_custom", password="welcome1", desc="Signing key")

Commands for checking the keystores and credentials

Once you have completed the above steps there are commands that can enable you to check to see if everything is setup correctly (i.e. the alias names match to the correct domain).   For checking the credentials, run the following from WLST:

listCred(map="oracle.wsm.security", key="keystore-csf-key")
listCred(map="oracle.wsm.security", key="enc-csf-key")
listCred(map="oracle.wsm.security", key="sign-csf-key")

* Executing these commands against the WebCenter domain will give the following response:

[Name : owsm, Description : Keystore key, expiry Date : null]
PASSWORD:welcome1

[Name : webcenter, Description : Encryption key, expiry Date : null]PASSWORD:welcome1

[Name : webcenter, Description : Encryption key, expiry Date : null]PASSWORD:welcome1

* Executing these commands against the JDeveloper domain will give the following response:

[Name : owsm, Description : Keystore key, expiry Date : null]
PASSWORD:welcome1

[Name : external_webcenter_custom, Description : Encryption key, expiry Date : null]PASSWORD:welcome1

[Name : external_webcenter_custom, Description : Encryption key, expiry Date : null]PASSWORD:welcome1

For checking the keystores

keytool -list -v -keystore [keystore-name] -storepass [keystore-password]

Example of using the WebCenter Spaces API in JDeveloper

The following code snippet invokes a response from Spaces to return a list of group space names. Note the reference to the key alias from the keystore:

GroupSpaceWSContext context = new GroupSpaceWSContext(); context.setEndPoint("http://[host]:[port]/webcenter/SpacesWebService");

context.setSamlIssuerName(http://www.oracle.com/);
context.setRecipientKeyAlias("external_webcenter_custom");
try {

GroupSpaceWSClient groupSpaceWSClient = new GroupSpaceWSClient(context);
List gspaceList = groupSpaceWSClient.getGroupSpaces(null);
for(String name : gspaceList){
System.out.println(name);
}
} catch (Exception e) {...}

One final important note.  In order for the client code to work, you must also have a security token to provide the user.  This can be accomplished by enabling ADF security on the application, which is invoking the Spaces API code.

Example of using native Webcenter page service API

Recently I received a request to create a task flow, which would be able to programmatically set security permissions to a (Spaces) group space page.  Of course WebCenter Spaces OOTB already has a supporting UI (from the Manage Page Link) for this task.  However, whatever the requirement is for enabling this functionality, it is good to know that there is a public API to code against.  You can view the documentation here.

In this example, since I need to interact with the Page Service, I need to create an instance of the Service:

      Scope mScope = ServiceContext.getContext().getScope();
      String scopeToUse = "defaultScope";
      if (mScope != null){
        scopeToUse = mScope.getName();
      }
      PageService mPageService =
          PageServiceFactory.createInstance(new PageServiceConfig((MDSSession)ADFContext.getCurrent().getMDSSessionAsObject(),
                                                                  scopeToUse));


In this code fragment mScope contains the MDS based information of the particular group space.  For example, in this example:

 Scope[name=MyGroupSpace, guid=s6dbba758_c69f_4602_af4d_0834b84b3dde]

There are also 2 methods that will enable the extraction of useful information about the scope itself. One is the getName(), which return the group space name, and the other getGUID(), which returns the unique id of the group space location in MDS.  These methods are great for deriving code, which can be use to pass as parameters of certain methods. Later on I will give an example of this to find the "path" of the page I want to add security on.  Once I have established the page service, I can now create code to complete my use case:

      mPageService.invalidateUserCache(getUserName());
      String grantee = "martin";
      String permisssions = "edit, view";
      String initPath = "/oracle/webcenter/page/scopedMD/";
      String testPath = initPath + mScope.getGUID() + Page2.jspx;
      PageDef pageDef = mPageService.getPage(testPath);
      // This get page in MDS at location:
      // oracle/webcenter/page/scopedMD/s6dbba758_c69f_4602_af4d_0834b84b3dde/Page2.jspx
      mPageService.changePagePermission(CustomPagePermission.class.getCanonicalName(),
                                        pageDef.getContentMRef(), true);
      mPageService.grantPagePermission(pageDef.getContentMRef(), grantee, 
      permissions);
      mPageService.saveChanges();
      mPageService.invalidateScopeCache();


There are 2 steps actually in getting this to work correctly.  The first step is that the page permission must be set to use "CustomPagePermission" page security.  The default is "PagePermission".  This is achieved by using the changePagePermisssion().  The next step is to set the new grants by using the grantPagePermission().  This method takes as its parameters, the page "path" (notice how I use the scope methods to help me create the page path), and grantee name (either a user or group, which has been defined in ldap provider, for example) , and the new permission(s), a String that has the values separated by commas.  Valid values are: manage, update, delete, personalize, view.

After invoking the code, I can query the PageSecurity Manager to check my policy updates:

page policy oracle.webcenter.page.model.security.PagePolicy@137fa30
Page : /oracle/webcenter/page/scopedMD/s6dbba758_c69f_4602_af4d_0834b84b3dde/Page2.jspx
 granted to martin

    with permission(s) [edit, view]



 Well there you have it.  A simple example showing how easy it is to use the WebCenter APIs!

Friday, May 13, 2011

Add LoV to new and existing taskflow

Introduction

Configuring a new portal site is easy, right?! However this statement is probably made by someone who knows his way around.
To ease this process the development team can assist there portal administrators by introducing LoV (List of Values) for the available taskflows. This applies to new and existing taskflow, yes you can add List of Values to existing taskflows.
There is following types of LoV:
  • Static LOV
    To display a list of predefined values.
  • Dynamic LOV
    To display a list of values generated by evaluating an EL value that is computed when the page is run.
  • Global LOV
    To display a global list of values that can be used in any task flow in the application.
  • Picker
    To display all values in a picker format, for example, a document picker.
This post will only go through a Static example, however the other options are straight forward.

Configuration

Assume following scenario to understand the context:
Step one create a new WebCenter Portal Project, add a desired navigation, add few pages, make sure they are customizable and support composer. All pages will be empty so the administrator has to add the taskflow  using the Runtime administration and edit the page.
It will look something like this:
image
The parameters now are open text boxes that is completely open, even though we declared them mandatory, one problem here is that we cannot guarantee the value the user will enter
There is an remedy for this, by using the new Oracle Composer extension file, pe_ext.xml
We are now going to introduce LoV for parameters  Colour and Language parameter, the process below can be repeated for any taskflow, new or existing.
Create new XML file called pe_ext.xml under Portal\adfmsrc\META-INF
Add following xml chunk:

   1: <?xml version="1.0" encoding="UTF-8" ?> 
   2: <pe-extension xmlns="http://xmlns.oracle.com/adf/pageeditor/extension">   
   3:   <lov-config> 
   4:   </lov-config> 
   5: </pe-extension>
Now we are going to add the taskflow reference for the affected taskflow
Add following:



   1: <task-flow-definition taskflow-id="/oracle/webcenter/siteresources/scopedMD/shared/taskflow/demo-taskflow.xml#demo-taskflow">
   2:  
   3: </task-flow-definition>

The best approach to find the id for the taskflow is to open the resource catalog in runtime and copying it

image

Now the final part, each parameter can now be configured with one of the four options of LoV, below is two static examples:
Parameter Colour


   1: <name>Colour</name>   
   2:      <enumeration inline="true">     
   3:              <item>       
   4:                       <name>Blue Colour</name>       
   5:                       <value>Blue</value>
   6:                       <description>Select ... Blue</description>     
   7:               </item>     
   8:               <item>       
   9:                    <name>Green Colour</name>       
  10:                    <value>Green</value>       
  11:                    <description>Select ... Green</description>    
  12:                </item>   
  13:          </enumeration> 
  14: </input-parameter-definition>

Parameter Language




   1: <input-parameter-definition>    
   2:       <name>Language</name>   
   3:       <enumeration inline="true"> 
   4:              <item>       
   5:                  <name>English</name>       
   6:                  <value>en</value>       
   7:                  <description>Select ... English</description>     
   8:             </item>     
   9:             <item>       
  10:                   <name>Swedish</name>
  11:                   <value>sv</value>       
  12:                   <description>Select ... Swedish</description>     
  13:              </item>   
  14:          </enumeration> 
  15: </input-parameter-definition> 
The entire xml should look like this:
image
Deploy the Portal project to see following result:
image


References

For more information on how to configure LoV see documentation:
http://download.oracle.com/docs/cd/E17904_01/webcenter.1111/e10148/jpsdg_page_editor_adv.htm#CACGHHAI

Tuesday, May 10, 2011

Running Human Task in the Integrated WLS

If you are currently developing a Human Task you might have wasted some time testing and redeploying your application many times. You also might have been remote debugging it, which takes quite some time due to the unresponsiveness of your remote WLS.
The steps I describe below will make your BPM Workspace application point to the Human Task running inside the Integrated WLS in JDeveloper, which means that for any changes done in the UI layer you will only need to refresh the browser to see it or rebuild a Java class to get it reflected on the business layer. Kudos go to the BPM Product Management team that has put this ant script together, I’m just making the setup process more clear.

Setup

1. Open $JDEV_DOMAIN_HOME/config/fmwconfig/system-jazn-data.xml and add  the following grant for BPM. $JDEV_DOMAIN_HOME is usually located under C:\Users\<username>\AppData\Roaming\JDeveloper\system11.1.1.4.37.59.23\DefaultDomain. C:\Oracle\Middleware is where JDeveloper is installed ($JDEV_HOME).

   1: <grant>
   2:     <grantee>
   3:         <codesource>
   4:             <url>file:C:\\Oracle\\Middleware\\jdeveloper\\soa\\modules\\oracle.soa.workflow_11.1.1\\-</url>
   5:         </codesource>
   6:     </grantee>
   7:     <permissions>
   8:         <permission>
   9:             <class>oracle.security.jps.JpsPermission</class>
  10:             <name>VerificationService.createInternalWorkflowContext</name>
  11:         </permission>
  12:         <permission>
  13:             <class>oracle.security.jps.service.policystore.PolicyStoreAccessPermission</class>
  14:             <name>context=APPLICATION, name=*</name>
  15:             <actions>getApplicationPolicy</actions>
  16:         </permission>
  17:         <permission>
  18:             <class>oracle.security.jps.service.policystore.PolicyStoreAccessPermission</class>
  19:             <name>context=SYSTEM, name=*</name>
  20:             <actions>getConfiguredApplications</actions>
  21:         </permission>
  22:         <permission>
  23:             <class>oracle.security.jps.service.policystore.PolicyStoreAccessPermission</class>
  24:             <name>context=SYSTEM, name=*</name>
  25:             <actions>getSystemPolicy</actions>
  26:         </permission>
  27:         <permission>
  28:             <class>oracle.security.jps.service.credstore.CredentialAccessPermission</class>
  29:             <name>context=SYSTEM, mapName=BPM-SERVICES, keyName=BPM-SERVICES</name>
  30:             <actions>read</actions>
  31:         </permission>
  32:         <permission>
  33:             <class>oracle.security.jps.service.credstore.CredentialAccessPermission</class>
  34:             <name>context=SYSTEM, mapName=BPM-CRYPTO, keyName=BPM-CRYPTO</name>
  35:             <actions>read,write</actions>
  36:         </permission>
  37:         <permission>
  38:             <class>oracle.security.jps.JpsPermission</class>
  39:             <name>IdentityAssertion</name>
  40:             <actions>*</actions>
  41:         </permission>
  42:     </permissions>
  43: </grant>

2. Start your embedded WLS instance.

image

3. Download and unzip bpm-jdev.zip. Open build.properties and set the properties shown below appropriately.

image

4. Run ant.

5. Now we’ll check if the Human Task is pointing to the machine that hosts JDeveloper. Go to Enterprise Manager in your SOA domain and select the corresponding BPM process.

image

6. Click on the Human Task, in my case, CreateOrder.

image
 

7. Under the Administration tab you should see the Human Task pointing to JDeveloper’s machine.

image


Running


1. Expand the Human Task project in JDeveloper, right click in the bounded task flow that references the Human Task form, and click either Run or Debug.

image

2. It will start JDev’s Integrated WLS and deploy the human task to the server

3. Open BPM Workspace application.

a. Create a new composite by clicking in process name under Applications.

image

b.Check if the address bar in the popup windows points to your Integrated WLS.

image