Translate

Sunday, June 28, 2015

Creating custom Event Listeners

Oracle WebCenter Sites (erstwhile FatWire) provides few API's to perform general auditing tasks or housekeeping processes like generating reports/weekly assessment on asset operations and publishing process which may or may not required by an organization but certainly is demanding feature for many customers.

Albeit there is no such simple button/process to do so within Oracle WebCenter Sites UI and hence, developers have to provide custom solutions to meet their customer requirements. And to do so, this custom business logic has to be implemented in form java classes and deploy to <webapps>/WEB-INF/lib folder.

Before browsing through this blog, it better to understand this topic: Event Listener from developer's guide. The process of registering listener is already mentioned in the guide, hence, I won't describe here but rather a sample snippet of code code on how to implement listener.

Note: All the below methods and classes are available with latest Oracle WebCenter Sites patch which may or may not be present in older version of FatWire/Oracle WCS.

There are 2 type of event listener which are of more importance:

Asset Event Listener: which fires on following asset operations: Add/Update/Delete/UndoCheckout/Approved/UnApproved

 public final class MyAssetEventListener extends AbstractAssetEventListener  
   {  
     public void assetAdded(AssetId id)  
     {  
       log.info("Asset Type: " + id.getType() + " and id:" + id.getId() + " added");  
     }  
     public void assetUpdated(AssetId id)  
     {  
      log.info("Asset Type: " + id.getType() + " and id:" + id.getId() + " updated");  
     }  
     public void assetDeleted(AssetId id)  
     {  
      log.info("Asset Type: " + id.getType() + " and id:" + id.getId() + " deleted");  
     }  
     public void assetApproved(AssetId id)  
     {  
      log.info("Asset Type: " + id.getType() + " and id:" + id.getId() + " approved");  
     }  
     public void assetUnapproved(AssetId id)  
     {  
      log.info("Asset Type: " + id.getType() + " and id:" + id.getId() + " unapproved");  
     }  
     public void assetUnapproved(AssetId id, Map<String, Object> properties)  
     {  
      log.info(" User " + properties.get("user") + " has unapproved an asset:" + id + " for the target:" + properties.get("targetId") + ".");  
     }  
   }  

Publish Event Listener: which fires on publishing tasks

 public class MyPublishEventListener implements PublishingEventListener {  
      public void onEvent(PublishingEvent event) {  
           PublishingTasks task = event.getTaskName();  
           /*  
            * task can be any one of the following: GATHERER, PACKAGER, TRANSPORTER, UNPACKER, CACHEUPDATER, NOTEPUBLISH, SESSION  
            */  
           PublishingStatusEnum status = event.getStatus();  
           /*  
            * status can be one of the following: STARTED, DONE, FAILED, CANCELLED, SUBTASK_FINISHED  
            */  
           List<AssetId> assetids = event.getAssetIds();  
           /*  
            * AssetId contains info about type and id in following format: ASSETTYPE:ID  
            */  
           String pubSessionId = event.getPubSessionId();  
           /*  
            * Publication Session  
            */  
           /*  
            * Publishing target Id and target Name  
            */  
           String targetId = event.getTargetId();  
           String targetName = event.getTargetname();  
           /*  
            * Username  
            */  
           String userName = event.getUsername();   
           if (PublishingTasks.NOTEPUBLISH.equals(task)) {  
                if (PublishingStatusEnum.STARTED.equals(status)) {  
                     for (AssetId id : assetids) {  
                          // do something  
                     }  
                }  
                if (PublishingStatusEnum.DONE.equals(status)) {  
                     for (AssetId id : assetids) {  
                          // do something  
                     }  
                }  
                if (PublishingStatusEnum.FAILED.equals(status)) {  
                     for (AssetId id : assetids) {  
                          // do something  
                     }  
                }  
           }  
      }  
 }  
Required jars: basic.jar, assetapi.jar, cs-core.jar, cs.jar, xcelerate.jar and log jars if logging.

Performance: There are caveats associated using custom listeners as it can affect authoring experience if frequent amount of asset activity is carried out. But again it depends on the method which you have implemented. Even if you are using single method of particular listener class, it then boils down to what further actions are taken. For e.g. Just printing a single message in log will not affect much but if process includes asset retrieval, streaming output in file system or database and notifying certain other processes, etc. can really degrade performance.

----------------------------------------------------
SUGGESTIONS/COMMENTS ARE INVITED
----------------------------------------------------


Sunday, June 21, 2015

Creating a simple custom WEM application

WEM - Web Experience management is a feature in webcenter sites/fatwire where in separate module can be implemented/deployed to integrate external content/repository via REST API or by deploying applications. All possible use of this feature are listed and discussed in detail here (Developer's Guide).

One feature is available to test and deploy: Articles Sample application (which can be downloaded  from Oracle edelivery site). Although following the steps given in guide should be enough, there are few errors and less info available for known issues. I am listing those so that you can make the changes and make it work:

1. SSO authentication failure (multi cast port not updated). Open the file: cas-cache.xml present at /WEB-INF/classes/cas-cache.xml and search for the term -"multicastGroupPort=@casCacheMultiCastGroupPort@" and change it to "multicastGroupPort=<SOME PORT NUMBER>". Re-deploy articles-1.0.war and run install.app

2. If you are not able to run install.app, then after deploying article-1.0.war file, register your app manually as mentioned here. There are few issues even after registering manually:

  • Not able to find app icon: To resolve this either you keep the icon within /cs/ folder of your application server directory and update your FW_Application or else update your FW_Application icon url to "../articles-1.0/images/articles.png"
  • Other issue is after each login on JSK, you have to run install.app and also there are multiple http redirects made leading to errors. To resolve this, rather than deploying the article-1.0.war file, unzip the folder under <APP_SERVER>/webapps/ folder and update your FW_Application accordingly. More details present here in oracle community. 
Although sample is present, it is little complex to understand it as it requires good knowledge on how controller works and creating app & assets programatically. But there is another simpler way to create and test WEM app. As a FatWire/Oracle Webcenter Sites consultant, often challenges are met with developing custom solutions which are useful for content contributors and administrators. For eg: Mass edit/save/update/delete/sharing assets, managing roles and ACLs, searching assets on attributes, etc. Such tools/solutions are often created as CSElement+SiteEntry where SiteEntry is called via browser to perform the task. If a project has so many custom requirements, I think it is better to have them separately in another WEM app which would be available to only permitted users. By doing so, custom admin tasks are separated from normal users and is secure as the solution is not exposed. I won't be telling you how to create these custom tools but rather about how to create a simple custom WEM app as followed:

Step 1: Create one typeless-template which should have the following code within the default code:
<div id="myapp" style="float:left;height:100%;width:100%" class="wemholder"></div>

This would be your layout element which would be included while creating FW_Application asset. Note: This id - myapp is important as it would be added to field: parent node while creating FW_View asset and should be unique.

Step 2: Create another typeless-template which will include your code to render the content. This content can come from anywhere like REST API, 3rd party api, etc. In our example, I will just include and proceed with Sample site URL present in JSK which shows the number of sites present and two sample sites urls to access sites: http://localhost:8080/cs/ContentServer?pagename=OpenMarket/Demos/index



This url would be added in the element while creating FW_View asset. 

Step 3: Download an icon (.gif or .png) from internet for your app and place it under some folder in <webapps>/cs/ folder

Step 4: Go to AdminSite, create new asset of Type: FW_View, fill in all the details like name, parent node (value would the id present in layout template i.e. myapp), view type: iframe and source url: sample site url. It should look like the following:


Step 5: After creating FW_View asset, add it to active list/bookmark it or it should be available in HISTORY tab if you did not navigate to other site or logged out. Create new FW_Application asset, include your FW_View asset and fill in all the details which should end like the following:


Step 6: Navigate to WEM Admin in AdminSite and register your app for avisports. Click on Apps from top menu and hover over you MyApp app, you will get 2 options: Edit and Manage App. Select Manage App, select site/s & role and then save it. I selected avisports and assigned all roles. Select site - avisports, an icon should be now visible for you to click on to open your WEM app. Overall you should see like below:

Similarly, any webcenter sites content or small functionality can be shown.

----------------------------------------------------
SUGGESTIONS/COMMENTS ARE INVITED
----------------------------------------------------