Monday, December 10, 2012

How to get the source codes of Build-In WebCenter Spaces Task Flows


The post is originally posted here.

Since WebCenter PS5, Oracle brings lots of standard task flows inside WebCenter Spaces. Some of them are already registered within the resource catalog and ready to use, most of them are also ready but you need to add them to the resource catalog first for business users to utilize. But from a developer standpoint, you may be interested in reviewing the source codes of the standard task flow shipped with Oracle WebCenter Spaces. Today I will show you how to locate the EAR or WAR file and take the advantages of build-in task flows.

After the Oracle WebCenter Spaces is installed, go to the following directory and you will find the relevant EAR and WAR files are already installed. In my case, it’s WebCenter PS5 but it’s applicable to other 11g releases.

$FMW_HOME/<WebCenter Instance Name>/webcenter/modules/oracle.webcenter.spaces_11.1.1


The one we are interested is the one at the bottom ‘oracle.webcenter.spaces.webapp.war’ file. You can ftp the file from the server to your local directory and extract it. You will find there are two subfolders in the file – “META-INF” and “WEB-INF”. If you are familiar with WebCenter/ADF development/deployment, those two folders should not be strange. The “META-INF” folder contains configuration files for applications, extensions, class loaders and services. The “WEB-INF” contains the static content that could be referenced and defined in some configuration files in META-INF folder for libraries pre-loading. So there is a folder ‘lib’ residing in WEB-INF and contains the JAR files that is pre-loaded when the server starts and they are the libraries that contains the build-in task flows. Here is the snapshot of the lib directory:




Again, it contains several JAR files that aggregate different set of resources in terms of their modules of functionalities and scope of use. We will look at the one at the bottom “spaces-web” JAR file. In this jar file, you will find all kinds of build-in task flows that are used internally in standard WebCenter Spaces resources. For example, in WebCenter Spaces, the default page template is a template called “Top Navigation”. In the template files, there are several regions being used are those task flows, which can be found here. Take the navigation region as an example, you could find the navigation task flow in this package ‘oracle.webcenter.webcenterapp.view.taskflows.navigation’. Here is the screenshot of the directory you can find about navigation task flows:




In the same ‘spaces-web’ jar file, you could find:
  • All the templates jspx file and their page definition files
  • Standard task flows that you can access from resource catalog
  • Java Beans that manage/support the transactions for the task flows and page fragments

If you want to learn a certain functionality that how Oracle WebCenter build or just find out the source codes that behind the scene, you can find all the relevant info by this means.


IPM/ODC: New Patches available


Patch for IPM:

  • WebCenter-Imaging       11.1.1.6.0             Patch 15947662: CUMULATIVE IPM/AXF PATCH 11.1.1.6.0 NUMBER 9 DATE 2012-12-03

Patch for ODC:

  • WebCenter-Capture      10.1.3.5.1             Patch 14538406: ODC PATCH 4 FOR 10.1.3.5.1

Enjoy!

Friday, November 30, 2012

Adding JavaScript to WebCenter/ ADF web application with Password Meter example



This blog describes steps to add JavaScript to WebCenter/ ADF web application, providing an example of Password Meter. It is common requirement in web applications to enforce user to create strong account password while registering on web site

1.   Create new WebCenter Portal – Framework Application, say MyWebApplicationWithJavaScript. Add new MyRegistrationForm.jspx file, in which JavaScript code is required to be added. Select View > Component Palette > Common Components and drag and drop ADF Faces Input Text into the .jspx file. Source code would contain lines as below   
<af:inputText label="Password" id="itPassword"/>
    Modify these as below
<af:inputText label="Password" id="itPassword">
</af:inputText>
2. Select View > Component Palette > Operations and drag and drop Client Listener above </af:inputText>
Figure 1
3.   In Insert Client Listener pop-up dialog, type method name of your JavaScript method in Method *: (in this example, chkpass), select type of event from Type *: (in this example, keyUp). This should change code to following
<af:inputText label="Password: " id="itMyValue">
<af:clientListener method="printMyValue" type="keyUp"/>
</af:inputText> 
 Note that secret="true" has not been added to af:inputText. Hence typed text would be visible as plain text to make it convenient for you to observe
4.   Add div tag as below, after password
<div id="divPasswordStrength">
<af:clientAttribute name="caPasswordStrength"/>
 </div>
5.   Add af:resource tag to .jspx file just above </af:document> tag. Add JavaScript code by either typing JavaScript function directly within af:resource tag
 <af:resource type="javascript”>
function chkPass(evt) {
//Add your code here
}
</af:resource>
 Or provide path to your .js file and .js file name, containing your JavaScript code, as value to source property of af:resource
<af:resource type="javascript" source="/PATH_TO_YOUR_.JS_FILE/YOUR_.JS_FILE_NAME">
</af:resource>

Below is code for MyRegistrationForm.jspx and function chkPass
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document id="d1" title="My Registration Form">
      <af:form id="f1">
        <af:inputText label="Password: " id="itPassword" maximumLength="10">
          <af:clientListener method="chkPass" type="keyUp"/>
        </af:inputText>
        <div id="divPasswordStrength">
          <af:clientAttribute name="caPasswordStrength"/>
        </div>
      </af:form>
      <af:resource type="javascript">
        function chkPass(evt) {
            var objItPassword = evt.getCurrentTarget();
            var strPassword = objItPassword.getValue();
            var intScore = 0;
            if (strPassword.match(/[a-z]/)) {
                intScore++;
            }
            if (strPassword.match(/[A-Z]/)) {
                intScore++;
            }
            if (strPassword.match(/\d+/)) {
                intScore++;
            }
            if (strPassword.match(/.[!,@,#,$,%,^,*,?,_,~,-,(,)]/)) {
                intScore++;
            }
            if (strPassword.length > 7) {
                intScore++;
            }
            var strStrengthArray = new Array();          
            strStrengthArray[0] = "Blank Password";
            strStrengthArray[1] = "Very Weak";
            strStrengthArray[2] = "Weak";
            strStrengthArray[3] = "Good";
            strStrengthArray[4] = "Strong";
            strStrengthArray[5] = "Very Strong";
            var strStrength = strStrengthArray[intScore];
            var objDiv = document.getElementById('divPasswordStrength');
            objDiv.innerHTML = "";
            if (intScore == 0) {
                objDiv.style.color = "#ffffff";
            }
            else if (intScore == 1) {
                objDiv.style.color = "#ff0000";
            }
            else if (intScore == 2) {
                objDiv.style.color = "#ff5f5f";
            }
            else if (intScore == 3) {
                objDiv.style.color = "#56e500";
            }
            else if (intScore == 4) {
                objDiv.style.color = "#4dcd00";
            }
            else if (intScore == 5) {
                objDiv.style.color = "#399800";
            }
            if (intScore > 0) {
                objDiv.innerHTML = "Score: " + (intScore * 20) + "%";
                objDiv.innerHTML += " | Strength: " + strStrength;
            }
            else {
                objDiv.innerHTML = "";
            }
        }
      </af:resource>
    </af:document>
  </f:view>
</jsp:root>
6. To test application, download it by clicking on 'Download Application' below, unzip it, right click MyRegistrationForm.jspx in Application Navigator and click Run. Type characters in upper/ lower cases, numbers, special characters and press enter to observe password strength. Output is as shown in Figure 2
 Figure 2



How to persist changes for a specific component in MDS?


Question: How to persist changes for a specific component in MDS?

Answer: Suppose you have a WebCenter portal framework application that uses Panel Box component. Now if you wish to persist its state i.e. Expand/Collapse in MDS.  E.g. If user logs in into the portal application and collapses one panel box, then anytime he logs back into the application, the panel box should appear collapsed. The steps for achieving the aforementioned functionality are given below.

STEPS:
  1. To persist changes for a specific component in MDS the adf-config.xml file needs to be edited to add the component and the attributes to store changes for. For this, open the adf-config.xml file that is located in the Application Resources | Descriptors | ADF META-INF node of the Oracle JDeveloper Application Navigator.
  2.   Go to View option.
  3.   Select “http://xmlns.oracle.com/adf/faces/rich” option under Tag Library URI in Tag Configuration.
  4.   Click on + (add) button to add component under Tags.
  5.    Select panelBox component from the list.
  6.    Save the application
  7.   Re-deploy the application.

Monday, November 19, 2012

Adding CAPTCHA to WebCenter/ ADF web application

CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) is type of challenge-response test used in computing as attempt to ensure that response is generated by human being. This is requirement for several web sites, especially on registration forms

Sample CAPTCHA is shown below
Figure 1

1. Download Simplecaptcha-1.2.1.jar. This is available for download for free on Internet. This is also available under MyWebApplicationWithCaptcha\Portal\public_html\WEB-INF\lib in application provided for download

2. Create new WebCenter Portal - Framework Application at C:\JDeveloper\mywork

3.  Create lib folder as follows
C:\JDeveloper\mywork\MyWebApplicationWithCaptcha\Portal\public_html\WEB-INF\lib

4. Paste Simplecaptcha-1.2.1.jar under lib folder

5. In JDeveloper, select View → Application Navigator, add Simplecaptcha-1.2.1.jar by right clicking Portal, Project Properties… → Libraries and Classpath → Add JAR/ Directory… Browse to
C:\JDeveloper\mywork\MyWebApplicationWithCaptcha\Portal\public_html\WEB-INF\lib

6. Add following to web.xml of application between <web-app></web-app>

<servlet>
  <servlet-name>CaptchaServlet</servlet-name>
  <servlet-class>nl.captcha.servlet.SimpleCaptchaServlet</servlet-class>
  <init-param>
    <param-name>width</param-name>
    <param-value>250</param-value>
  </init-param>
  <init-param>
    <param-name>height</param-name>
    <param-value>75</param-value>
  </init-param>
</servlet>


<servlet-mapping>
  <servlet-name>CaptchaServlet</servlet-name>
  <url-pattern>/captchaservlet</url-pattern>
</servlet-mapping> 


7. Add following code in MyRegistrationForm.jspx file that needs to have CAPTCHA

<?xml version='1.0' encoding='windows-1252'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=windows-1252"/>
  <f:view>
    <af:document id="d1" title="My Registration Form">
      <af:form id="f1">
        <af:panelFormLayout id="pfl1">
          <af:panelGroupLayout id="pgl" layout="vertical">
            <af:image source="/captchaservlet" id="i1" clientComponent="true"
                      inlineStyle="width:251px; height:76.0px;"/>
            <af:commandButton text="Refresh CAPTCHA" id="cb2" immediate="true">
              <af:clientListener method="refreshCaptcha" type="action"/>
            </af:commandButton>
          </af:panelGroupLayout>
          <af:panelGroupLayout id="pgl1" layout="horizontal" halign="left">
            <af:inputText id="it1" label="Enter text as seen in above image: "
                          value="#{requestScope.bestGuess}"/>
            <af:commandButton text="Go" id="cb1"
                              actionListener="#{MyRegistrationFormBean.verifyAnswer}"></af:commandButton>
          </af:panelGroupLayout>
          <af:message id="m1" messageType="info" for="it1"/>
        </af:panelFormLayout>
      </af:form>
      <af:resource type="javascript">
        function refreshCaptcha(evt) {
            try {
                var component = evt.getSource();
                var i1 = component.findComponent("i1");
                i1.setSource(i1.getSource() + "?force=" + new Date().getMilliseconds());
                evt.cancel();
                return false;
            }
            catch (err) {
                alert(err);
            }
            return false;
        }
      </af:resource>
    </af:document>
  </f:view>
</jsp:root>



8. Open pages.xml. Drag drop MyRegistrationForm.jspx under Root. Select Delegate Security radio button. Ensure anonymous-role has View permission check box checked

9. Add a package mypackage under Portal and MyRegistrationFormBean in 
request scope as follows. Open MyCapthcaPage.jspx in Design mode. Double click Go button. Enter values as shown below
Figure 2
Click New...

Figure 3
Click OK

Figure 4
Click OK


10. Implementation of MyRegistrationFormClass.java class is as follows


package myPackage;

import java.io.UnsupportedEncodingException;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import javax.servlet.http.HttpServletRequest;

import nl.captcha.Captcha;

import oracle.adf.view.rich.context.AdfFacesContext;

public class MyRegistrationFormClass {
    public MyRegistrationFormClass() {
    }

    public void verifyAnswer(ActionEvent actionEvent) {
        FacesContext fctx = FacesContext.getCurrentInstance();
        ExternalContext ectx = fctx.getExternalContext();
        HttpServletRequest request = (HttpServletRequest)ectx.getRequest();
        Captcha captcha = (Captcha)ectx.getSessionMap().get(Captcha.NAME);
        try {
            request.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            System.out.println("UTF not supported!");
        }
        String myAnswer = (String)ectx.getRequestMap().get("bestGuess");
        if (myAnswer != null && captcha.isCorrect(myAnswer)) {
            getMessage("Congratulations! You are human");
        } else {
            getMessage("Sorry! You could be a computer!");
            UIComponent panelLabelAndMessage =
                ((UIComponent)actionEvent.getSource()).getParent().getParent();
            UIComponent panelFormlayout = panelLabelAndMessage.getParent();
            AdfFacesContext.getCurrentInstance().addPartialTarget(panelFormlayout);
        }
    }

    private void getMessage(String myMessage) {
        FacesContext fctx = FacesContext.getCurrentInstance();
        fctx.addMessage("it1",
                        new FacesMessage(FacesMessage.SEVERITY_INFO, null,
                                         myMessage));
    }
}


11. To test application, download it by clicking on 'Download Application' below, unzip it, right click MyRegistrationForm.jspx in Application Navigator and click Run
Download application

Thursday, November 15, 2012

Starting UCM 10g on boot


While this is a bit late, numerous Oracle customers are still installing and running instances of UCM 10g. These instructions refer to the automating of the startup of the UCM 10g service on system boot.

Once the UCM 10g instances are installed, the following process will add these to the init.d  startup process. These instructions are written using Oracle Linux Server release 5.7.

Starting UCM 10g involves starting the IDC Admin Server and the IDC Server. In my examples here, UCM was installed to the “/u01/app/ucm/server” directory.

  1. Log into Linux as root
  2. Copy the idcadmin_ctrl and the idcserver_ctrl files to the .etc/init.d directory. I like to shorten the names to idcadmin and idcserver respectively.

    [root@dev ~] cp /u01/app/ucm/server/etc/idcserver_ctrl /etc/init.d/idcserver
    [root@dev ~] cp /u01/app/ucm/server/admin/etc/idcadmin_ctrl /etc/init.d/idcadmin

  3. Verify that the two files are executable
    [root@dev init.d]# cd /etc/init.d
    [root@dev init.d]# ls -l idc*
    -rwxr-xr-x 1 root root 11201 Nov 12 10:56 idcadmin
    -rwxr-xr-x 1 root root 11204 Nov 12 10:56 idcserver

  4. Edit the idcadmin file and replace the first lines

    #!/bin/sh
    #idc Note: Lines beginning with #idc will be removed from this script
    #idc automatically during the build process.
    #idc

    With
    #!/bin/bash
    #
    #
    # chkconfig:   2345 85 15
    # description: This is a program that is responsible for taking care of
    # starting and stoping the UCM Admin Server.
    #
    # processname: idcadmin
    # Red Hat or SuSE config: /etc/sysconfig/idcadmin
    # Debian or Ubuntu config: /etc/default/idcadmin
    #

    The chkconfig:   2345 85 15 line tells chkconfig to set the run levels at 2345 (same as Oracle database)and it also puts the start at priority 85 and the stop at priority 15 (database is 80 and 05)

  5. Edit the idcserver file and replace the first lines

    #!/bin/sh
    #idc Note: Lines beginning with #idc will be removed from this script
    #idc automatically during the build process.
    #idc

    With
    #!/bin/bash
    #
    #
    # chkconfig:   2345 85 15
    # description: This is a program that is responsible for taking care of
    # starting and stoping the UCM Server.
    #
    # processname: idcserver
    # Red Hat or SuSE config: /etc/sysconfig/idcserver
    # Debian or Ubuntu config: /etc/default/idcserver
    #

    The chkconfig:   2345 85 15 line tells chkconfig to set the run levels at 2345 (same as Oracle database)and it also puts the start at priority 85 and the stop at priority 15 (database is 80 and 05)

  6. Add these to the service list with the following:

    [root@dev init.d]# chkconfig --add idcadmin
    [root@dev init.d]# chkconfig --add idcserver

  7. Verify they were added using the following:
    [root@dev init.d]# chkconfig --list|grep idc
    idcadmin        0:off   1:off   2:on    3:on    4:on    5:on    6:off
    idcserver       0:off   1:off   2:on    3:on    4:on    5:on    6:off

  8. Test the services
    [root@dev init.d]# service idcadmin query
    Success checking Admin Server status. Status:  Stopped
    [root@dev init.d]# service idcserver query
    Success checking Content Server  Content Server status. Status:  Stopped

  9. And finally, restart the linux instance and confirm that the IDC Admin and IDC Server start