9 abr 2013

WebCenter Spaces, navigation from one space to another space specifiying the destination path

Recently on a project we have the requirement of jumping from a Space to another one, but not the landing page.

This is the hierarchy and the desired navigation.






By default you can access to SpaceA with this URL: http://server/webcenter/spaces/spaceA

To access to second space the URL is http://server/webcenter/spaces/spaceB

Inside of SpacesB if you try to move to a "detail page" you can use http://server/webcenter/faces/news/detail because the navigation of the Space is the "default navigation" stored in memory.

Now imagine you're on SpaceA "home page", if you try to move to "detail page" of SpaceB you will get an error of 404 page not found.





This is produced because your current navigation is the default navigation defined in SpaceA.

To bypass this problem, we need to read the "default navigation" of SpaceB and create the correct link to the page.

First, we need the path of the "default navigation" of SpaceB, to get this value, we have to log as space administrator and go to the tab called "Resources".

Go to: http://server/webcenter/spaces/spaceB/admin

Select the correct resource and click "Edit Properties".


You will see a popup similar to this one, copy the value of the "Metadata File" clicking on "more" icon.





Now we have all needed information. It's time to create a "<af:goLink>" from one space to another.

Check this code:
<af:golink destination="#{navigationContext.navigationModel['/oracle/webcenter/siteresources/scopedMD/s8195d183_d2b1_4c90_b0fa_b541d2031f79/navigation/gsrbe2d4c14_2b20_4e1b_94aa_cc1930641d4e/default-navigation.xml'].node['news/detail'].goLinkPrettyUrl}" id="gl1">
</af:golink>


This is the syntax of the Expression Language (EL) used:

 #{navigationContext.navigationModel['<path to xml>'].node['<hierarchy>'].goLinkPrettyUrl}

This <af:goLink> will produce a HTML output like this:

http://server/webcenter/faces/news/detail?wc.contextURL=/spaces/spaceA&&wcnav.model=%2Foracle%2Fwebcenter%2Fsiteresources%2FscopedMD%2Fs8195d183_d2b1_4c90_b0fa_b541d2031f79%2Fnavigation%2Fgsrbe2d4c14_2b20_4e1b_94aa_cc1930641d4e%2Fdefault-navigation

 Souces:
  • WebCenter Developer's guide (link)

19 feb 2013

Using CMIS query with boolean metadata

Often we create boolean type metadata on WebCenter Content. This type of metadata in fact is an integer type metadata, but uses a system internal view called "YesNoView".

Check screenshots above to see the default configuration of this kind of metadata.



If we check the standard "Check-in" page, the metadata is represented with a "combo-box" input.





You can use this metatada to perform searchs over UCM and retrive the contents that are checked as "hidden" (in this example).


Since WebCenter PS3 was released, you can show content on WebCenter Portal/Spaces with "Content-Presenter (CP)" taskflow. This component shows contents stored at content server (UCM).

CP allows the user to define a query that searchs on content-server the items that matches your query. This is done over CMIS standard instead UCM query syntax.

Now, we try to add a content-presenter on a page, and query filtering with the new metadata (Hidden content). This is the CP wizard screenshot.


Remember to check that the new metadata is in "Filters" section. And save/close the wizard...

The system will show some error stacktrace, this is a summary

Caused by: oracle.webcenter.content.integration.RepositoryException: 19-feb-2013 17:00:46 oracle.webcenter.content.integration.spi.ucm.search.SearchService search
GRAVE: Se ha producido un error al buscar el repositorio ucm. Se ha recibido el código de estado -1 al llamar al servicio GET_SEARCH_RESULTS, como usuario weblogic y registro de hora 19/02/13 17:00. La búsqueda es Search[repositoryId=ucm, max to return=5, useFullTextSearch=true, useCache=true, sort="toProperty('dDocTitle') ASC", fullText="
 Metadata criteria((cm_contentType equals IDC:GlobalProfile)AND(xHiddenContent [any] equals true))
 isOr=false"] y la asignación de parámetros es {ResultCount=5, FolderPathInSearchResults=1, SortField=dDocTitle, IdcService=GET_SEARCH_RESULTS, SortOrder=ASC, vcrAppendObjectClassInfo=1, StartRow=1, QueryText=(xHiddenContent  `true`), vcrContentType=IDC:GlobalProfile}.


If you have installed WebCenter Spaces, we can try the Web-interface to test the CMIS queries. In my case I tried the following URLs:
  • http://owc:8888/rest/api/cmis/query/q/ucm?q=SELECT * FROM ora:t:IDC:GlobalProfile WHERE ora:p:xTuiHiddenContent = TRUE
  • http://owc:8888/rest/api/cmis/query/q/ucm?q=SELECT * FROM ora:t:IDC:GlobalProfile WHERE ora:p:xTuiHiddenContent = 1

And the following errors were launched

oracle.webcenter.content.integration.cmis.query.ParseException: Feb 19, 2013 5:19:27 PM oracle.webcenter.content.integration.cmis.query.VcrExpressionSearchDelegate fixLiteral
SEVERE: Comparing boolean property [xHiddenContent] to non-Boolean literal [1]


oracle.webcenter.content.integration.RepositoryException: Feb 19, 2013 5:19:33 PM oracle.webcenter.content.integration.spi.ucm.search.SearchService search
SEVERE: An error occurred when searching repository ucm.  When calling service GET_SEARCH_RESULTS, as user anonymous, at timestamp 2/19/13 5:19 PM, received status code -1.   The search was Search[repositoryId=ucm, max to return=26, useFullTextSearch=false, useCache=true, expr="(toProperty('xHiddenContent') == true && toProperty('cm_contentType') == 'IDC:GlobalProfile')"] and the parameter map was {ResultCount=26, FolderPathInSearchResults=1, SortField=dInDate, IdcService=GET_SEARCH_RESULTS, SortOrder=Desc, vcrAppendObjectClassInfo=1, StartRow=1, QueryText=(xHiddenContent  `1`), vcrContentType=IDC:GlobalProfile}.

To solve this, there is a workaround that we can do, without affecting the content already stored at UCM.

First create a table in UCM (using ConfigurationManager Applet), this table should have a structure similar to this one:



After that, we create a view that uses that table, similar to this one:



Next you should add the values for true/false.


And finally, attach the new view created to the metadata, replacing the system "YesNoView" with the "YesNoCustomView" just created.


Now, restart WebCenter Spaces and try with this URL:

  • http://owc:8888/rest/api/cmis/query/q/ucm?q=SELECT * FROM ora:t:IDC:GlobalProfile WHERE ora:p:xHiddenContent = 1
Now the query is correctly performed over CMIS standard. And if you try CP Wizard now also works without problems.

I hope this information helps on your project.

Related Information 



12 feb 2013

java.net.socketpermission on WebCenter Content (UCM) Applets

After the one of the last updates of my local JRE I couln't connect to the UCM Applets of the client throught the proxy connection.

This error appears:


To solve this issue, go to your "java.policy" file, mine is under this path:

C:\Program Files (x86)\Java\jre7\lib\security\java.policy

Modify your file and add this line at the end of the file:


permission java.net.SocketPermission "*", "connect,accept,resolve"; 

After that modification, close all your browsers and retry to open the Applet.



NullPointerException in VCR_GET_CONTENT_TYPE service

Recently I was debugging an error in WebCenter Portal, that didn't allow the user to search over a content-server instance with a Content-Presenter TaskFlow.

In this case, we had 2 instances of UCM connected to WebCenter Portal application, the first one works without problems, but when we attached the second one, and you try to query over it, the page is refreshed and the content-presenter wizard is closed.



The Portal log shows this error:

Caused By: oracle.stellent.ridc.protocol.ServiceException: Could not load information about VCR content type. Unable to execute service method 'vcrGetContentTypeInfo'. The error was caused by an internally generated issue. The error has been logged.
 at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:135)
 at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:107)



And looking at UCM log this error is shown:

services/3 02.07 15:22:14.039 IdcServer-89 !csUserEventMessage,sysadmin,CIS!$ intradoc.common.ServiceException: !csVcrCouldNotLoadContentType!csUnableToExecMethod,vcrGetContentTypeInfo
 services/3 02.07 15:22:14.039 IdcServer-89 *ScriptStack VCR_GET_CONTENT_TYPE
 services/3 02.07 15:22:14.039 IdcServer-89 3:vcrGetContentTypeInfo,**no captured values**
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceRequestImplementor.buildServiceException(ServiceRequestImplementor.java:2115)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.buildServiceException(Service.java:2260)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.createServiceExceptionEx(Service.java:2254)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.createServiceException(Service.java:2249)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceHandler.executeAction(ServiceHandler.java:102)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.doCodeEx(Service.java:533)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.doCode(Service.java:505)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceRequestImplementor.doAction(ServiceRequestImplementor.java:1643)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.doAction(Service.java:477)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceRequestImplementor.doActions(ServiceRequestImplementor.java:1458)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.doActions(Service.java:472)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceRequestImplementor.executeActions(ServiceRequestImplementor.java:1391)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.executeActions(Service.java:458)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceRequestImplementor.doRequest(ServiceRequestImplementor.java:737)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.Service.doRequest(Service.java:1890)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceManager.processCommand(ServiceManager.java:435)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.IdcServerThread.processRequest(IdcServerThread.java:265)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.IdcServerThread.run(IdcServerThread.java:160)
 services/3 02.07 15:22:14.039 IdcServer-89         at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:528)
 services/3 02.07 15:22:14.039 IdcServer-89         at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
 services/3 02.07 15:22:14.039 IdcServer-89         at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
 services/3 02.07 15:22:14.039 IdcServer-89 Caused by: java.lang.NullPointerException
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.vcr.VcrServiceHandler.addPropertyChoicesForFieldAndView(VcrServiceHandler.java:514)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.vcr.VcrServiceHandler.vcrGetContentTypeInfo(VcrServiceHandler.java:464)
 services/3 02.07 15:22:14.039 IdcServer-89         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 services/3 02.07 15:22:14.039 IdcServer-89         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 services/3 02.07 15:22:14.039 IdcServer-89         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 services/3 02.07 15:22:14.039 IdcServer-89         at java.lang.reflect.Method.invoke(Method.java:597)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.common.IdcMethodHolder.invokeMethod(IdcMethodHolder.java:86)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.common.ClassHelperUtils.executeMethodReportStatus(ClassHelperUtils.java:324)
 services/3 02.07 15:22:14.039 IdcServer-89         at intradoc.server.ServiceHandler.executeAction(ServiceHandler.java:79)
 services/3 02.07 15:22:14.039 IdcServer-89         ... 16 more



After seeing that the problem resides at UCM service execution we see that the status-code returned is -32. (Any status-code lower than 0 means service execution error).

Looking at the dDocTypes all appears correctly, but after accessing to the "Check-in" form, some errors can give us an idea of the problem. When I access to check-in form, some alerts are showed to the user indicating that some of the metadata "views" seems corrupted.




To find out wich metadata is the one that uses that view, I've opened Firebug and look for that view on JS files.


The metadata called "xIsEditable" is using YesNoList view, its recommended to perform more search and see how many metadata fields are using that view.

The problem in this case was that the view was empty and didn't have any value, this causes the NPE (NullPointerException) in the execution of the service VCR_GET_CONTENT_TYPE.

After adding values to the view, and going back to check-in page, no more "alert" of view errors were shown.

Now the UCM is ready to be used again with content-presenter, and the problem solved.

23 nov 2012

Showing first tab always in a ADF panelTabbed

Oracle ADF panelTabbed component has the capability of remember the last Tab that the user keeps opened.

When the user get back to the page or taskflow that contains the af:panelTabbed, the last tab opened will be shown instead of the first tab.

If you want to show always first tab as "opened", there is a couple of parameters at the af:showDetailItem that will help us.

This  is a sample code that will make the trick:

<af:panelGroupLayout id="pgl1" layout="vertical">
  <af:panelTabbed id="ptab1" position="above">
    <af:showDetailItem text="First" id="sdi1" persist="disclosed" disclosed="true"/>
    <af:showDetailItem text="Second" id="sdi2" persist="disclosed" disclosed="false"/>
    <af:showDetailItem text="Third" id="sdi3" persist="disclosed" disclosed="false"/>
  </af:panelTabbed>
</af:panelGroupLayout>  


 Check ADF Tag Library

Big thanks to my co worker María for finding the solution :-)

Download sample project

26 oct 2012

Validate check-in form fields with Javascript

At one of my current projects we faced the problem that the dDocName field was filled with no common characters by the user.

For example they insert spaces and letters (like áéíóú). This kind of contentID was breaking the indexer process of UCM.

Most of you will tell me to use the AUTO_NUMBER property of content server, but on some type of content, the user have to insert a specified dDocName for our SSXA Web project.

To prevent contentID like "BIOGRAFÍA CATALÁN", we developed a custom component that performs a JS validation before check-in process.

For the validation I've created a REGEX expresion that allows only letters, numbers and underscore.

This is the code inserted in the custom-component. As you see, this will "include" all system validations with the <$include super.custom_schema_validation_script_post$> sentence.
After that, starts our custom validation, we only have to return "false" if we want to cancel the check-in process.

<@dynamichtml custom_schema_validation_script_post@>
<$include super.custom_schema_validation_script_post$>
<$if ((dpAction like "CheckinSel" or dpAction like "CheckinNew" or dpAction like "Update"))$>
if (document.Checkin != null && document.Checkin.dDocName != null)
{
var name = document.Checkin.dDocName.value;
if(name != null && name != '' && name.length > 0)
{
 var rgx_docname = /^[A-Za-z0-9_]{1,30}$/;
 
 if (rgx_docname.test(name))
 {
  vstatus = "Ok";
 }
 else
 {
  vstatus = "Error";
  alert("Error: You cannot use non-ASCII characters for ContentID");
  return false;
 }
}
}
<$endif$>   
<@end@>

Download here the custom-component for your customization and use.

25 sept 2012

Using WebCenter REST API from Java

Most WebCenter services are available over REST access. In this example app we will try to connect to our development Spaces instance and get the list of spaces for the user.

The REST API supports two kind of different authentication, depending where you use the Java code. If you are creating a taskflow to be deployed on same domain of the spaces node, you should use "OIT" auth, this kind of auth does not need the user password on each request to the server.

Instead, if your code is outside of the weblogic domain, you must send (user + password) on each request.

This sample app have a boolean flag to enable "development-mode" that means connection from outside of weblogic domain (for example my local JDeveloper).

Keep in mind that on each request you should have the URL access to your REST API, to generate that URL you need before the userToken.

//Get the client connnection
RESTUtils rest = new RESTUtils();
rest.setDevelopmentMode(true);

//Get weblogic user token
String userToken = rest.getUserToken();

//Creation of endpoint URL
//Sample URL: http://owc:8888/rest/api/spaces?utoken=FMgUQjBKZ96NGgwGdlZrX-WJACJ4_w**
URL endpoint = new URL(RESOURCE_INDEX + UTOKEN + userToken);

//Establishing connection
HttpURLConnection connection = rest.getConnection(endpoint);

This is the sample output of the app after executing the class WCSpaces.java

5-sep-2012 10:34:33 webcenter.rest.RESTUtils getUserToken
INFO: Obtaining user token
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getConnection
INFO: We are connecting in development mode
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getConnection
INFO: Auth sent:Basic d2VibG9naWM6T3JhY2xlMTFn
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getConnection
INFO: Finished development connection to http://owc:8888/rest/api/resourceIndex
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getUserToken
INFO: Obtained token:FMgUQjBKZ96NGgwGdlZrX-WJACJ4_w**
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getConnection
INFO: We are connecting in development mode
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getConnection
INFO: Auth sent:Basic d2VibG9naWM6T3JhY2xlMTFn
25-sep-2012 10:34:33 webcenter.rest.RESTUtils getConnection
INFO: Finished development connection to http://owc:8888/rest/api/spaces?utoken=FMgUQjBKZ96NGgwGdlZrX-WJACJ4_w**
25-sep-2012 10:34:33 webcenter.rest.WCSpaces getSpaces
INFO: Space displayName:blog
25-sep-2012 10:34:33 webcenter.rest.WCSpaces getSpaces
INFO: Space displayName:test
Process exited with exit code 0.



As you see, both "displayName" of the spaces are obtained.

Here is the sample app for download.

And finally the Oracle Documentation about REST