Friday, January 21, 2011

UCM 11g: Desktop Integration Suite Walkthrough - Adding custom metadata to Office properties



Here’s a quick post to show the added power of the DesktopTag component which comes bundled with the Desktop Integration Suite.

DIS 11g allows for much more dynamic and flexible handling of native content. One of the mechanisms used to do this is Outside In’s BitLocker SDK (acquired by Stellent in 2006). The containing jar can be located here:

../<middleware_home>/Oracle_ECM_prod/ucm/idc/components/OracleCleanContent/libs/java/CleanContent.jar

This SDK is typically used by UCM to clean content of hidden metadata, revisions, comments, etc; but, in this case, it is being used to embed metadata information into the content’s native format.

The metadata usually embedded by the DesktopTag component are:



  • DISidcName
  • DISdID
  • DIScgiUrl
  • DISProperties
  • DISTaskPaneUrl
  • DISdUser
  • DISdDocName



All of these are what you expect them to be, except the TaskPaneUrl, which is a url to the DESKTOP_DOC_INFO service for the specific document.

These variables work together to determine the validity of the current doc compared to the version currently within the content server. For more information on DIS and its new features, please see:

http://download.oracle.com/docs/cd/E14571_01/doc.1111/e10624/c01_introduction.htm#BABHAEHF
 






Now that we’ve had a quick peak under the covers of DIS, let’s see how we can leverage that for our own custom metadata.




The DesktopTag component sets a number of environmental variables. One of the variables is DesktopTagFieldsCustom, but it’s currently commented out. So let’s create our own component to set this variable.

You can get a look at my sample component here.

This component overrides all values to allow testing, but specifically, focus on the following:


DesktopTagFieldsCustom=xComments,xkeywords(Keywords)

This test implements two different syntax options: standard & special syntax, as defined in the original cfg:
# Special syntax: binderName(propertyName)
# Example: dID(DISMyId) will create a custom property named DISMyID with
# the value of dID.


For our customization, we’re adding xComments and xkeywords to the list of embedded metadata. We want to leverage this metadata, which is managed within the content server, within our native content. I will be demonstrating using Microsoft Word, but this technique should work with any compatible application.




  • To start, let’s create a new blank Word document




  • Now, let’s add some static text.


I have added some static text to the header & body


  • At this time, we'll add a quick part for the keywords. This is a standard Word property.
    • Place the cursor after the "Keywords:" text
    • Click on the Insert Word Ribbon (i.e., the menu tab)
    • Click on  Quick Parts à field










      • Could also shortcut buy using Quick Parts à Document Property à Keywords
    • Click on “DocProperty” in the Field Names list
    • Click on “Keywords” in the Property list
    • Click Ok


  • Note: Nothing appears immediately in the document as there are no keywords assigned

  • Commit doc as new to UCM, applying metadata as it is checked in. specifically the comments and keywords.



  • Open the document from UCM


  •  Note: Nothing appears in the document, but this time it’s specifically due to Microsoft Word not auto-updating Quick Parts
    • Out of the box, Word would require right-clicking and manually updating each field.

  • Now that we have opened the document via DIS, our custom UCM metadata have been applied as Word properties


    • Notice the value of “under review” for the DISCxCo… property
    • Also notice that because we targeted our custom UCM metadata at a standard Word property, it appears in the standard field


  • Let’s add our custom property now:
    • Place the cursor after the “Status:” text in the header
    • Click on the Insert Word Ribbon (i.e., the menu tab)
    • Click on  Quick Parts --> field
    • Click on “DocProperty” in the Field Names list
    • Click on “DISCxCommets” in the Property list
    • Click Ok 



  • Now both of our values are showing in the document 



  • To show the lack of auto update, let’s save the document and update the metadata
    • On the Oracle UCM ribbon, click Check In With Metadata
    • Alter the Comments & keywords 


    • Click Ok
  • Re-open the document from UCM
    • On the Oracle UCM ribbon, click Open
    • Search for your document
    • Select it to be opened

  • Notice that the metadata values did not update automatically.
  • It appears that this is a often encountered issue as Microsoft has put out a support article addressing it.
    • http://support.microsoft.com/kb/832897/en-us
    • We will use the Method 2 workaround, Creating a macro to automatically update the field
    • The step-by-step procedure is listed on Microsoft’s site, so I’ll skip that for now 



  • Save & reopen from UCM

  • Notice that the metadata is applied automatically. 




Thanks it, now we have a word document that receives updates from UCM during each re-open. This ensures that any metadata applied to a document is current during each edit session.


Get a copy of the SenaDIS component here.


Thanks again for reading & I hope you've found some part of this useful and perhaps even reusable.


Disclaimer: The code, opinions, and other content on this page are my own and are not necessarily representative of my employer. There is no expressed support for any code contained herein. Most code supplied within these pages has been created to proof out a specific concept or to show a specific case. No code should be considered production-ready without your own testing and validation.

Tuesday, January 4, 2011

WCI vs Webcenter Spaces

This post will describe some of the differences between Webcenter Interaction and Webcenter Spaces. It is meant to be used as an informal guide to the choices available within Webcenter Suite and future paths for those who may already be invested in the Webcenter Interaction product. Before we get too much further we should first define some of the products and terms used in connection with Webcenter Suite.

Webcenter Suite is an enterprise portal platform made up of many products including 3 portal products, Webcenter services and the Webcenter development framework. Also included is limited-use licensing for Universal Content Management, Secure Enterprise Search and Presence and Communications Services.

Webcenter Interaction refers to the cross-platform portal product and services previously known as Plumtree and BEA's Aqualogic Interaction. It has portal versions native to both .net and Java.

Webcenter Services is a set of Enterprise ready social services that can be integrated with existing portals as well as custom applications. It includes products for wikis, blogs, RSS, activity streams, discussions, tags and links.

Webcenter Spaces is the portal application that provides the UI and administration layer to the products that make up Webcenter Suite. It has out of the box features that closely match the features provided with Webcenter Interaction’s portal. It is the product with the highest level of integration to Webcenter Services, Fusion Middleware and other Oracle products.

So what are the differences?

To understand the differences it is good to know the history of the products. Webcenter Interaction grew up as a pure play portal product. This meant that the product was originally meant to be a top layer portal product that did not care too much about the backing technologies that needed to be surfaced. That being said, many of WCI’s components were built using Java and only the core portal product was 'jumped' to .net using a java to .net conversion technology. Also, most of WCI’s add-on products and services are black box java apps that run on packaged tomcat or JBoss app servers. Development against WCI can be done using your IDE of choice depending on the technology you are using (.net,java,php,rails or any html emitting technology) and the functionality or product you are surfacing. An SDK and API web services are used for writing portlets and composite applications that take advantage of portal services and intrinsic functionality. Exposing and consuming JSR 168 and WSRP 1.0 compliant portlets is also possible with WCI.

Webcenter Spaces, on the other hand is a pure java based application that is supported for deployment to Weblogic Application Server. It was built to be the presentation layer to the Fusion Middleware product line. Customizing and developing for Spaces involves the use of Oracle's Jdeveloper IDE. You can use another Java IDE but that would be painful. Jdeveloper has deep integration not only with the Webcenter stack but with ADF development and fusion middleware overall. The Webcenter framework used with Spaces allows for consumption of JSR 168 as well as WSRP 1 and 2 compliant portlets. Additionally, ADF taskflows can be exposed as JSR 168 portlets using the portlet bridge available as part of the framework.

Which do I go with?

If you are in the process of deciding on a portal suite and framework be assured that the Webcenter Suite provides everything you need to stand up an enterprise strength portal with many out of the box features. Enterprise 2.0 functions come out of the box for both Spaces and WCI. For WCI the integration levels range from simple installation/configuration to custom integration work or even the dreaded iframe. If you have not yet decided on the portal product to use also be assured that Webcenter Interaction and Webcenter Spaces both provide enterprise strength portal functionality and customization capabilities.

With the 11g release of Spaces there is no longer much that Spaces lacks in comparison with WCI. Both products are fully supported by Oracle. Both portal products have or will have 11g versions and future versions/enhancements. Going forward, though, pieces of WCI functionality will be replaced by Webcenter services and other Oracle solutions as consolidation and convergence happens with the Webcenter products and shared services. This may be the biggest reason to choose Spaces as the portal of choice if you are not invested in either portal yet and if you are not absolutely tied to the .net development environment. Even if your preference is to develop using .net you can wrap .net apps with WSRP 2.0 and maintain functionality within Spaces.

My experience has been that most companies have a blend of technologies in the enterprise and either have teams that know both technologies or have separate teams to handle .net or java development. In either of these two situations you might be better served to go with Webcenter Spaces as your choice of portal product since integration is tighter with the other Webcenter pieces and Spaces will only be enhanced while the WCI product may have some functionality replaced with newer Oracle products or services.

What if you are already invested in Webcenter Interaction?

If you are already on the Webcenter Interaction product stack you have your choice of paths. The decision on whether to move to Webcenter Spaces is dependent on a longer list of decision points than we can discuss here. So what kinds of paths might you take to transition to Spaces from Webcenter Interaction portal?

Stay with the product for the foreseeable future. If you are heavily invested in the WCI product set and are only interested in modest changes for the foreseeable future you can certainly stay with WCI. You can augment functionality with Webcenter Services and integration with UCM. These integrations are not yet mature but they will be soon.

Start a piecemeal migration. You can stay with the core portal product and start smaller migrations of functionality. For example, you can migrate from Publisher to UCM or start migrating portlets or apps to be exposed via JSR 168 or WSRP and surfaced through Spaces.

Yank the band-aid and start a full migration effort. Knowing that the Spaces product is fairly mature should help if you decide to make the full blown migration effort. Depending on the size of your user base, app/portlet inventory and points of integration a migration effort might take a few months to a year or more. Just remember that the effort will put you on the latest version of Spaces and in the middle of the best of breed products and services that make up the Webcenter Suite offering.

In future posts we will take a look at specific mappings of functionality between WCI and Webcenter Spaces.

Monday, November 22, 2010

UCM 11g: Sourcing of metadata fields and/or How to create metadata during component installation





Just wanted to note an interesting and useful new feature of 11g: metadata can now be sourced.

It appears that this functionality is specifically designed to be leveraged by components, but perhaps this will be expanded to metadata created via the Config Manager applet in the future (or perhaps someone will create an enhancement will allow admin access to these values).

This ability is useful for any system where multiple custom, or component,  attributes are in use. The ability to track an attribute back to the component that’s leveraging it allows for better understanding of its intended purpose. This can prevent illogical hijacking of attributes which could potentially confuse programmers and users alike. On the other hand, if it is decided to share an attribute across components, this also can be detailed.

Anything that helps answer the question, “why is this here?”, is useful in my opinion.


As previously mentioned, it appears that there is no admin-level UI to modify this field. To leverage this, I’ll show how the ‘dComponentName’ property can be appended to the standard set of attribute metadata in order to use this feature. 

I’ve created a simple component to demonstrate this functionality. I’ll start by briefly reviewing the functional aspects, then I’ll go into the different features of the component.


The SenaSampleManageMetadata component is an example of a starting template one could use to create components. Some people prefer to work out of the ComponentWizard for editing, modifying, and generally managing their components. I prefer to use Eclipse and my svn to keep a history of each component I create. 

That being the case, I have a few different starting templates I use to jump-start my component building. This component has two useful maintenance features: managing of metadata & tracing information. Side note: I’m working on building an ant build file that will automate the cloning and renaming of the template files into the new template. I also would like it to auto increment the version information (<today’s date> <previous build # + 1).

The first feature will allow for the simultaneous deployment of metadata with their associated components instead of creating a component bundle or manual creation via an IQ/OQ document or implementation notes. Anything that simplifies and streamlines deployment and implementation is typically going to be a step in the right direction.

The second feature is an important step in keeping log files tidy and useful. Developers can easily enable or disable debugging output from their custom components by leveraging custom trace sections. Using custom trace sections will not only allow for easy isolation (e.g., by grepping a tail) of output, but it will ensure that I/O is limited when the trace is disabled. Think about the last project you were on where all code utilized the system trace… it’s not pretty.


Now that the reasons for the maintenance features have been defined, we can discuss how we approach these via component additions. 

The first feature is handled by leveraging a component installation filter. The ComponentWizard creates a starting class that includes a conditional structure for handling multiple filter events within the same class. I’m using the extraAfterServicesLoadInit filter as well as the SenaSampleManageMetadataComponentUninstallFilter filter.

As defined in the template, the extraAfterServicesLoadInit filter is called after the last standard activity of a server side application initialization. These events are triggered as the content server starts during the post-installation restart. This is a good place to manipulate cached data or override standard configuration data. The SenaSampleManageMetadataComponentUninstallFilter filter is called for custom un-installation steps. NOTE: Change the uninstall filter name to have your component name prefix. For example: <ComponentName>CompnentUninstallFilter. This event is triggered after confirmation of component uninstallation via the UCM admin server. I’ve modified the descriptions a bit for added clarity, but they’re basically lifted from the filter template comments.

Code added for the extraAfterServicesLoadInit filter condition:

 else if (param.equals("extraAfterServicesLoadInit"))
    {
      SystemUtils.trace("senasamplemeta", "\n\n\nSenaSampleManageMetadata: Found install filter\n\n\n");
      processMeta(loader, ws, binder, cxt, true);
    }

Code added to the SenaSampleManageMetadataComponentUninstallFilter filter condition:

else if (param.equals("SenaSampleManageMetadataComponentUninstallFilter"))
    {
      SystemUtils.trace("senasamplemeta", "\n\n\nSenaSampleManageMetadata: Found uninstall filter\n\n\n");
      processMeta(loader, ws, binder, cxt, false);
    }

The function created to handle the create/delete of metadata:

protected int processMeta(IdcExtendedLoader idcextendedloader,
      Workspace ws, DataBinder binder,
      ExecutionContext cxt, boolean isInstall)
  {
    SystemUtils.trace("senasamplemeta", "Starting to process custom meta..");

    try
    {
      1: DataResultSet dataresultset = SharedObjects
          .getTable("SenaSampleManageMetadata_Metadata");
      SystemUtils.trace("senasamplemeta", "after get table");
      if (dataresultset != null)
      {
        SystemUtils.trace("senasamplemeta", "table not null");
        dataresultset.first();
        for (; dataresultset.isRowPresent(); dataresultset.next())
        {
          2: Properties properties = dataresultset.getCurrentRowProps();
          String metaDefName = properties.getProperty("dName");
          SystemUtils.trace("senasamplemeta", "retrieved metadata name: " + metaDefName);
          SystemUtils.trace("senasamplemeta", "hasDocMetaDef: " + MetaFieldUtils.hasDocMetaDef(metaDefName));
          3: if (metaDefName == null || metaDefName.length() == 0
              || ( isInstall && MetaFieldUtils.hasDocMetaDef(metaDefName))
              || ( !isInstall && !MetaFieldUtils.hasDocMetaDef(metaDefName)))
            continue;
          try
          {
            SystemUtils.trace("senasamplemeta", "is install: " + isInstall);
            4: if (isInstall)
              MetaFieldUtils.updateMetaDataFromProps(ws, null, properties,metaDefName, true);
            else
              MetaFieldUtils.deleteMetaData(ws, cxt, metaDefName);
            SystemUtils.trace("senasamplemeta", "after Meta call");
          } catch (ServiceException serviceexception)
          {
            SystemUtils.error(serviceexception, (new StringBuilder()).append(
                "Error:").append(metaDefName).append(
                " senasamplemeta -- metadata field was not installed.").toString());
          }
        }

      }
    } catch (Exception exception)
    {
      SystemUtils.error(exception,
          "senasamplemeta: Unable to execute install filter.");
    }
    return 0;
  }

There are four main points of interest:

  1. Instead of hard-coding metadata values, they can be externalized into an UCM static table (see below)
  2. While looping over the rows in the table, this retrieves the property keysets for each row
  3. Verification check: ensure that the current metaField exists; if this is an install request, verify that the metaField doesn’t already exist; if this is an uninstall, verify that the metaField exists 
  4. Choose function based upon install/uninstall

The MetaFieldUtils helper class supplies the heavy lifting by encapsulating the COLLETION_UPDATE_META_TABLE and DEL_METADEF services.
Below is the detail of my static table:
<@table SenaSampleManageMetadata_Metadata@>
<table border=1><caption><strong>

<tr>
      <td>dsdComponentName</td>
      <td>dComponentName</td>
      <td>dsdVersion</td>
      <td>dName</td>
      <td>dCaption</td>
      <td>dType</td>
      <td>dIsRequired</td>
      <td>dIsEnabled</td>
      <td>dIsSearchable</td>
      <td>dIsOptionList</td>
      <td>dOptionListKey</td>
      <td>dOptionListType</td>
      <td>dDefaultValue</td>
      <td>dOrder</td>
      <td>dIsPlaceholderField</td>
      <td>dsdCheckFlag</td>
      <td>dsdDisableOnUninstall</td>
</tr>
<tr>
      <td>SenaSampleManageMetadata</td>
      <td>SenaSampleManageMetadata</td>
      <td>1.0.0</td>
      <td>xSampleMetaField1</td>
      <td>Sample Meta Field 1</td>
      <td>BigText</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td></td>
      <td></td>
      <td></td>
      <td>25000</td>
      <td>0</td>
      <td></td>
      <td></td>
</tr>
<tr>
      <td>SenaSampleManageMetadata</td>
      <td>SenaSampleManageMetadata</td>
      <td>1.0.0</td>
      <td>xSampleMetaField2</td>
      <td>Sample Meta Field 2</td>
      <td>BigText</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td></td>
      <td></td>
      <td></td>
      <td>25100</td>
      <td>0</td>
      <td></td>
      <td></td>
</tr>

</table>
<@end@>
After installing this component, you can verify that the metadata has been added:

Uninstalling the component will remove the attributes. Again, this is a POC, whether this is a feature you would want to implement is up to your specific requirements.

Going forward:

This code can be enhanced to include much more functionality. Different datatypes can be introduced and managed. The creation and population of views, drop-down lists (ddl), user attributes, etc can all be handled within this filter. Modification of these variables can also occur. Other possibilities include sharing an existing component attribute. You could check if the attribute exists, then modify the dComponentName attribute by appending your component name to the end of the existing string.

Values could also be maintained via component install strings and/or component configurations which would allow users to review and potentially modify during install. Component configurations can also be configured to be modifiable while the component is installed.



For the second feature, I’ve added a custom trace to the standard ddl so that it’s easily remembered and accessible by developers and admins alike. Remember, just because the initial developer that added the custom trace remembers the exact string doesn’t preclude that the next developer will remember when it comes time to debug … or, the even the initial developer just a few months down the road for that matter…



The table where the custom trace section is defined:
<@table SenaSampleManageMetadataTraceSections@>
<table border=1><caption><strong>SenaSampleManageMetadata Tracing Sections</strong></caption>
<tr>
  <td>itsSection</td>
  <td>itsDescription</td>
  <td>itsDefaultEnabled</td>
</tr>
<tr>
  <td>senasamplemeta</td>
  <td>Sena Sample Manage Metadata Tracing</td>
  <td></td>
</tr>
</table>
<@end@>
This table is merged into IdcTracingSections.


You can find the component here.


I hope you’ve found some part of this useful and perhaps even reusable.

Thanks,
-ryan

edits: 
12/17/2012: updated download link


Disclaimer: The code, opinions, and other content on this page are my own and are not necessarily representative of my employer. There is no expressed support for any code contained herein. Most code supplied within these pages has been created to proof out a specific concept or to show a specific case. No code should be considered production-ready without your own testing and validation.