Sunday, October 27, 2013

WebCenter Portal HA and Performance Tuning Checklist

Performance is a broad topic which is never out of date. I'd like to itemize a checklist with specific topics, links and references. Some topic may be more generic and some may be more specific. But this list mainly focuses on WebCenter Portal applications and its relevant products.

This is not intended to be a complete list and there will never be.

WebCenter Performance Tuning Guide

HA for WebCenter Portal and ADF application

Configure JOC for WebCenter Portal services

Configure Coherence Caching for Content Presenting

WebCenter Performance Study (Including Enable Client Caching and Compression)

Tuning JVM

Weblogic Capacity Planning

Middleware Performance Tuning Roadmap

Oracle HTTP Server Performance Tuning

MDS Performance Tuning

Using Cluster and HA Features


Some Useful A-Team Blog Posts:

High availability considerations for WebCenter Portal and ADF 
Improving ADF Page Rendering Time : Progressively Loading Taskflows
Configure Coherence for Oracle WebCenter Portal Framework Content Presenter Task Flow 

Non-programmatic Authentication Using Login Form in JSF (For WebCenter & ADF)

My previous post described a scenario that the OAM DCC programmatic authentication is not supported yet, and here I am presenting a nice alternative to do the DCC authentication non-programmatically.

You may have a read on Frank's book "Oracle Fusion Developer Guide" and there is a section in the ADF security talking about "Creating a login form in JSF" programmatically. This approach works for JEE contained security but would not work well with your WebCenter Portal or ADF app integrated with OAM authentication. I am introducing an approach that does not require any programmatic authentication and can be used safely with any type of authentications (contained security or OAM authentication).

Note: You can create HTML form in JSF but there are many limitations, such as only one form component can be allowed in a page. Due to this, it's impossible to support a complicated login page in JSF. It induced extra pitfalls and challenges on the skinning as well.

If you create a WebCenter Portal application in Jdeveloper, you will have a loginProxy.jspx page already created in your application. This loginProxy.jspx is our solution here. This pre-built page is coded in HTML form and I experienced in some cases it is not well supported for WebCenter portal applications, although it does seem ok with a pure ADF application (this page is not shipped with an ADF fusion application, so you have to create it for ADF app). I would recommend to re-code this page using ADF Faces component.

The process flow is simple:

1. Create an actual login page in JSF (.jspx) page. In this JSF page, it contains the input text for user name, password and a button for submit/login. All these components are coded with ADF faces components. In the value fields, specify a parameter in request scope so they can be passed onto the loginProxy page.



2. Re-code the loginProxy.jspx page using <f:verbatim> which will wrap the form post with the username/password parameters passed from login page. Depending on the authentication type, you may have different form post actions. This page uses the JavaScript to auto submit the form.

For JEE contained security:
 <?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 title="login" id="d1">
    <af:clientListener method="formSubmit" type="load"/>
    <af:resource type="javascript">
     function formSubmit(evt) {
       var form = document.getElementById("loginData");
       form.submit();
     }
    </af:resource>
    <f:verbatim>
     <form id="loginData" name="loginData" method="POST" action="j_security_check">
      <input id="userid" type="hidden" name="j_username" value="${requestScope.userid}"/>
      <input id="password" type="hidden" name="j_password" value="${requestScope.password}"/>
     </form>
    </f:verbatim>
   </af:document>
  </f:view>
 </jsp:root>

For OAM authentication:
 <?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 title="login" id="d1">  
    <af:clientListener method="formSubmit" type="load"/>  
    <af:resource type="javascript">  
     function formSubmit(evt) {  
       var form = document.getElementById("loginData");  
       form.submit();  
     }  
    </af:resource>  
    <f:verbatim>  
     <form id="loginData" name="loginData" method="POST" action="/oam/server/auth_cred_submit">  
      <input id="userid" type="hidden" name="userid" value="${requestScope.userid}"/>  
      <input id="password" type="hidden" name="password" value="${requestScope.password}"/>  
     </form>  
    </f:verbatim>  
   </af:document>  
  </f:view>  
 </jsp:root>  

3. Last step is to create a navigation rule from login page to loginProxy page. The navigation rule is specified in the "login" button on the login page.


This approach avoids the programmatic authentication and works great for having a custom login page developed in WebCenter Portal integrated with OAM authentication. It works for both ECC and DCC authentication. As of now, the programmatic authentication on OAM DCC is not supported, so this approach fits right in the gap.

Tuesday, October 15, 2013

Difference on Getting Error Code from OAM ECC and DCC

In case of OAM authentication failures, the OAM server will send the error codes back to the client. It's up to the client to decide what actual error message needs to be displayed on different types of authentication failures. For the list of the standard error codes, you can refer to here. To getting the error code on the client side, they are different based on whether it's ECC or DCC authentication. I have not found this difference documented in anywhere yet. So I am putting it in this blog post.

DCC (Detached Credential Collector) is introduced in OAM 11gR2. ECC is embedded credential collector. My previous post has described its concept and advantages, so I will not repeat it here.

For ECC, the link above also shows a code snippet to get the error code parameter "p_error_code". The error code is returned back as one of the request parameters on the browser URL. So it can be accessed by calling request.getParameter("p_error_code").

 <%@page import="mytest.error.ExampleErrorMsg"%>  
  //initializing the messageBundle first  
  String defaultResourceBundle = "mytest.error.ExampleErrorMsg";  
  java.util.Locale myLocale = request.getLocale();  
  ResourceBundle msgBundle=  
  ResourceBundle.getBundle(defaultResourceBundle,myLocale);  
 String errCode = request.getParameter("p_error_code");  
 String secondaryErrMessage = request.getParameter("p_sec_error_msg");  
  <%  
     if(errCode != null && errCode.length() > 0) {  
      try {  
        simpleMessage = msgBundle.getString(errCode);  
      } catch(Exception e) {  
        //get the default authn failed message  
        simpleMessage = msgBundle.getString("OAM-8");  
      }  
  %>  
  <div class="message-row">   
    <p class="loginFailed"> <%=simpleMessage%> </p>   
  </div>  


For DCC, it's not returned on the request parameter but on the request header. Actually there is no request parameter returned at all for DCC, as the returned url is "http://host:port/oam/server/auth_cred_submit" with no actual parameters, in case of authentication failure. To get the error code from the request header, simply by:

 String errCode = request.getHeader("p_error_code");  

Sunday, October 13, 2013

Does OAM DCC Support Programmatic Authentication? - Maybe not yet!

Credential Collection is the process of collecting the end user's credentials through a login page. When OAM Webgate intercepts a requests and detects the user is not authenticated yet, it would redirect the user to the login page. In OAM, when the login page is hosted on the OAM server, it's called Embedded Credential Collector (ECC).

Another form - Detached Credential Collector (DCC) - is introduced in OAM 11gR2. As the name explains, DCC can be decoupled from the OAM server, which provides the flexibility of deploying the login page in either trusted internal network or DMZ. It uses a specific WebGate to collect he user credential and communicate to the OAM using secure Oracle Access Protocol (OAP). It offers a solution that isolates the OAM serve from any unauthenticated network connection, such as public access.

It is my interest to discuss on whether DCC supports programmatic authentication. Usually the login page for OAM authentication would be form based JSP page with the following snippet:

  <form id="loginData" name="loginData" method="POST" action="/oam/server/auth_cred_submit">  
      <table cellspacing="2" cellpadding="3" border="1">  
       <tr>  
        <th>Username:</th>  
        <td>  
         <input id="userid" type="text" name="userid" autocomplete="off"/>  
        </td>  
       </tr>  
       <tr>  
        <th>Password:</th>  
        <td>  
         <input id="password" type="password" name="password" autocomplete="off"/>  
        </td>  
       </tr>  
      </table>  
      <p>  
       <input type="submit" name="submit" value="Login"/>  
      </p>  
      <!--<input type="hidden" name="request_id" value="${param.request_id}" id="reqid1"/>-->  
      <!--<input type="hidden" name="OAM_REQ" value="${param.OAM_REQ}" id="oamreq1"/>-->  
     </form>   
Note the important thing in the snippet is the HTML form component with "POST" method and "/oam/server/auth_cred_submit" action. The user id input id and password input id have to match the settings on OAM server. You might notice the "request_id" and "OAM_REQ" parameter is commented out and they are not required by the DCC (but they are required by ECC authentication though).

Oracle documentation did talk about the programmatic authentication here - "Programmatic authentication using HTTP client APIs is supported for both OSSO 10g and 11g OAM Server". This is true for ECC authentication, but not for DCC. I will explain why.

In case of DCC, the user sends a request to access an OAM protected resource. The webgate will detect that and redirect to the login page with a DCCCtxCookie. The cookie looks like this:

Cookie: DCCCtxCookie_host:port=encdata%3DK1%2Fz6ZK1yVCemO56M9Zs9DfIY%2Fui4r%2BQaoWbA8rxRf%2FgJ68egTxUyOC4G%2F2Ufj8gQwEgL36wlEEevfNm5ETfaw4PwDVMVj3MRkHfvZSmBCPsFC6T4z9tS98ehpAxZjhx8cJN2ELvMycCrgqQFNEd23WbRzRq4YCLt9edz%2Ba1gekDhjIMKLYMZrNrlmv1krsIV4PYnQWydY5pmfpYfh%2BYPyumYWMt%2Bm6syK9nmruSM%2BOSKu39PxBV6TL1S3wWpWgXLFmpS6Jq5Xt6cBGWaMbCaVnfcQQdN%2BSIfFLz0kA8u8Fxq9Z4dB9MGQoWzE165KDHRKsVPgMN81M%2F84ju3Cximw%3D%3D;

This cookie is sitting on the path "/oam/server/auth_cred_submit" but not on the domain "/" like JSESSIONID. This makes the cookies not accessible from Http Client API. Without this DCCCtxCookie, submitting the login page with action "/oam/server/auth_cred_submit" would result in 404 - page not found.

Different from ECC, the cookies generated for ECC authentication are sitting on the domain path so it can be accessed from the Http Client API.

Due to this cookie path challenge, I am making a conclusion that the DCC is not supporting programmatic authentication yet. I hope others can correct me and show me an alternative or workaround for this matter.

Assuming DCCCtxCookie is present, OAM will authenticate the credentials on submitting the login form. If the credential passed the authentication, a cookie "OAMAuthnCookie" will be set and available on the response header.

Set-Cookie: OAMAuthnCookie_host:port=qLhahoJixOlOMO%2F9mCzrd80IPFoaswuOA%2F59re%2Bo%2FREiXuKMFfzicypCssemSZLLBwaGIZawYc6TnymVPUppQQKolyt015hJuas5xYIbK3rCT4SgI%2BMYdlsPpeyy1IFvpFEHWVbLJ%2Fkd94SYoiBwUWlNo7dEa7jVltmz8k8h2sJ4id%2FriGn2JCtxgUfPNGsF8FrIvO3xIkXCqo7c4LMPlZJrgxz5vW1Dt9FARC1eQ%2BzhNK4p9XYpogcuKEfGSwSEyzrQdiVPU82zx108uVKhNvlUvBPwwqhY38Dkpnecaouv6Gzo5XqEnac%2Bz8GB84UmVen6UXca8knu9lNzC2iRLi0356JSR27%2Fft4ESr%2Fpnlk%3D; 

Note to Jmeter test with the DCC cookie

The following info is provided by Flavia from the comments below: 

It's true that Jmeter cannot see the DCCCtxCookie_host:port by default, but if you set
CookieManager.check.cookies=false
In jmeetr.properties or user.properties, Jmeter can see the cookie. You need to restart Jmeter.

Another import thing that I found is set the "Follow Redirects" in the HTTP Request. I did for all my pages (specially "/oam/server/auth_cred_submit")

Monday, October 7, 2013

FileNotFoundException after Recent Deployment on WebLogic Server

You might experience the FileNotFoundException (OracleJSP error:java.io.FileNotFoundException) error on rending your JEE app after a recent deployment on WebLogic server. You could also see errors in the log stating "unable to dispatch JSP page".

First thing to try is, clear your browser's cache and request the page again. If this is not helping, then the issue is from the server side.

When web application is activated and deployed, the new web application is exploded to a tmp directory under $DOMAIN_HOME, eg. $DOMAIN_HOME/servers/AdminServer/tmp/_WL_user...

These directories are used in subsequent server starts so the applications do not have to be deployed again. In this case, some of the files and directories are missing in the tmp directory, resulting in errors observed. It is unknown what caused the files/directories to be missing in this case.

To get rid of the error, simply need to either restart the manager server or force the re-deployment like below:

1. Shutdown AdminServer
2. Remove or rename $DOMAIN_HOME/servers/Adminserver/tmp directory.
3. Start Adminserver, this will cause all the applications to be deployed again.

There are others talks about the related weblogic behaviors:
http://stackoverflow.com/questions/12301976/temporary-directories-in-weblogic-10
http://stackoverflow.com/questions/6815330/weblogic-not-clearing-cache