Friday, August 2, 2013

WebCenter Portal on Mobile Devices

New article on WebCenter Portal delivery to Mobile devices is now published on the A-Team Chronicles.
This article talks about how you can optimize the design and implementation of a portal so that the markup and page weight is lean enough to deploy efficiently on a mobile platforms. The article includes an example application that when deployed generates portal pages that are less than 230Kb in weight.

Full link below :

Monday, June 25, 2012

Parametrizing WebCenter spaces customization

I'm using webcenter spaces, and I'm on PS5.

I need to customize some Webcenter task-flows, but I don't want the customization to take effect globally. I am using spaces, so I would like to localize customization to a space, or to an individual instance of a task-flow. For example, I have some MDS customization in the document task-flows, like in the wiki, I want to hide a bunch of features and controls/command buttons for all users except moderators.

I'll use the wiki as an example for this post. The wiki uses the folderViewer BTF (taskflow call) and the folderViewer BTF uses the DocumentViewer BTF (in the case of wiki). So a lot of these customizations are on the DocumentViewer taskflow's JSF fragments.
If I customize the right JSF fragments, everything can be shown/hidden based on the requirement. So far so good. Now the real problem is that these customizations are global, meaning for this webcenter spaces instance  or any WCS instance that uses this MDS DB, these customizations apply.

However, it would be nice to be able to parametrize (to an extent, and mostly at a very coarse grained level) some of the customizations so that I can customize these taskflows on a per Space level or per instance level. With Yannick's suggestion to add taskflow paramerets by customizing the taskflows themselves, I can do this at a per taskflow instance level , which is excellent !

Here is what I did :

Taking the example of the Wiki taskflow, here is the structure of the taskflow (you can see this by looking at the wiki taskflow from your library, in customization developer role)

Wiki Taskflow --calls--> FolderViewer Taskflow --calls--> DocumentViewer Taskflow

I want the customizations to be applied by default (just because that is the most common scenario for me), but want to give the page/space owners the ability to disable the customizations and expose the vanilla/out-of-the-box features of the taskflow too(a not-so-common thing in my implementation). To do this, when the person placing a wiki page on thier space, they should be able to set a parameter to disable all our internal customizations. This parameter obviously needs to be defined on the wiki tasklfow.

  • Step 1
    • Define new parmeter on the wiki taskflow.
    • Name the parameter something sensible, say 'disableCustomizations', make the type Boolean and set the value to #{pageFlowScope.disableCustomizations}. Setting the value is not mandatory if you dont mind the value being in pageFlowScope, which is the default scope it will be put in to at runtime, but I just prefer to be explicit.
    • Though the user sets the parameter on the wiki, the actual customizations are done on the DocumentViewer Taskflow's JSF fragments. So we need a way to propagate this parameter to the actual place/taskflow where it will be used.
    • Now one thing to note is that this  parameter value #{pageFlowScope.disableCustomizations} will not be available to the taskflow being called, DocumentViewer in our case. This is simple beacause taskflow calls and regions containing taskflows, when executed get thier own pageFlowScope that is different from the caller's pageFlowScope. I really dont want to keep a paremeter in the session scope, so I decided to add a parameter to  FolderViewer taskflow and from there propagate the value again to the actual DocumentViewer by adding a parameter to that as well.
  • Step 2
    • Add a paremeter to the FolderViewer Taskflow. Pass the user's input parameter to the FolderViewer, by customizing the taskflow call.
  • Step 3
    • Repeat step 2, but for propagating the value from FolderViewer to DocumentViewer.
    • Add a paramater to the DocumentViewer taskflow. Pass the parameter value recieved by FolderViewer to the DocumentViewer by customizing the taskflow call.
  • Step 4
    • Customize the DocumentViewer jsffs by incorporating the parameter value. Set the rendered attribute on the controls and components that I want to be able to toggle based on the parameter value.

Now deploy the customization and you should see a new parameter on the task-flow, and setting the parameter can toggle the components we have customized. The best thing is the new parameter can be set on per-instance of a taskflow, so I can have two Wiki taskflows on the same page, both looking different !

To recap, the idea here is to create your customization to be dependent on a parameter, which itself can be created through customization. Since customizations are global, the parameter is globally available across the webcenter instance, but since the actual, end user customization is dependent on the parameter, the customizations are applied only when the parameter is set. This enables us to finely control when the customizations are applied and when they are not.

A bunch of thanks to Yannick, for pointing me in the right direction from the OTN forums!

Wednesday, May 30, 2012

oracle.jbo.InvalidOperException: JBO-25221

This is a rather simple one, but it took me an hour to finally realize what was going on.

I got this error when trying to execute a custom method on my AM from a backing bean.
To execute the method, I got the OperationBinding from the binding container and called execute on it.
When testing I got this error.

oracle.jbo.InvalidOperException: JBO-25221

The error ,message basically explains that the method could not be found or is not supported. That should have been a good indicator, but I "knew" the method existed. What happened was that I had created the binding first, then changed the method signature on the AM and the client interface, but forgot to re-create the binding. So the parameters(in my case) that the binding had no longer was available on the AM's client interface.

Another thing to note here is the use of generics.