Tuesday, December 27, 2016

UTL_SMTP: Random Exclamations

Recently I noticed an issue with random exclamations points(!) in the HTML email notification, generated using UTL_SMTP package in PLSQL.

These random exclamations points were not supposed to be part of the message, but strangely appears in the message body. After analyzing for some time, I found out the cause. Here is my analysis.


Cause:
This issue appears only with HTML email notification exceeding 1000 characters(includes the CR and LF) per line. As per RFC#2822 Section 2.1.1, no line can be longer than 998 characters without a line break.


Fix:
Solution is simple. Concatenate each line with CHR(10) or line breaks, so that each line will not exceed 1000 characters mark.

Saturday, December 24, 2016

SQL Developer: DBA

Recently, I came across DBA Navigator feature in SQL Developer, that really helps DBA or Developers to administer Oracle Database right from your desktop.

How to access DBA Navigator:
Open SQL Developer --> Go to View --> DBA


What are all features, it enables to users:
  • View database instance overall status using Instance Viewer(IO, wait events, storage, log switches, and processes)
  • Access ADDM/AWR/ASH reports
  • Security(Users/Roles) Administration
  • Storage(Datafiles/Tablespaces) Administration
  • Many more....

Sunday, December 18, 2016

JDK Upgrade: JavaMail Exception

Recently I upgraded one of SOA Suite 11g environments to use latest JDK(7u121) and I received below error from UMS driver, when I restarted the complete SOA domain.

Error:
<Nov 25, 2016 2:26:53> <Error> <oracle.sdp.messaging.driver.email> <SDP-26123> <Could not initialize Email Store for user ABC@XYZ.COM >

<Nov 25, 2016 2:26:53> <Error> <oracle.sdp.messaging.driver.email> <SDP-25700> <An unexpected exception was caught.
javax.mail.MessagingException: * BYE JavaMail Exception: java.net.SocketTimeoutException: Read timed out;
  nested exception is:
        com.sun.mail.iap.ConnectionException: * BYE JavaMail Exception: java.net.SocketTimeoutException: Read timed out
        at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:569)
        at javax.mail.Service.connect(Service.java:288)
        at javax.mail.Service.connect(Service.java:169)

Cause:
As a part of latest JDK release, plain text authentication is no longer supported.

Fix:
Disable Plain-text Authentication in Email Driver Configuration

i.e. Check ImapAuthPlainDisable checkbox as shown below.


BPM: XPathFunctionException

Recently I faced below XPathFunctionException error, when I tried to build and execute SQL query in BPM process Script activity.

Error:
<Dec 12, 2016 6:47:14> <Error> <oracle.fabric.common.xml.xpath> <BEA-000000> <XPath function failed with error:oracle.xml.sql.OracleXMLSQLException: Character ')' is not allowed in an XML tag name.
oracle.fabric.common.xml.xpath.XPathFunctionException: oracle.xml.sql.OracleXMLSQLException: Character ')' is not allowed in an XML tag name.

<Dec 12, 2016 6:47:14> <Error> <oracle.soa.bpel.engine.xml> <BEA-000000> <
javax.xml.xpath.XPathExpressionException: internal xpath error


Fix:
Add alias to SQL query return value.

For Ex:

Incorrect: 
SELECT GET_STATUS('1234') FROM DUAL

Correct: added alias
SELECT GET_STATUS('1234') STATUS FROM DUAL


BPM: XPath ClassCastException

Recently I faced below Class Casting error, when I tried to invoke a BPEL service from BPM process.

Error 1:
<Dec 11, 2016 8:37:49> <Error> <oracle.fabric.common.xml.xpath> <BEA-000000> <XPath function failed with error:java.lang.ClassCastException: oracle.xml.parser.v2.XMLElement cannot be cast to java.lang.String
oracle.fabric.common.xml.xpath.XPathFunctionException: java.lang.ClassCastException: oracle.xml.parser.v2.XMLElement cannot be cast to java.lang.String


Error 2:
ORABPEL-11211

DOM Parsing Exception in translator.
DOM parsing exception in inbound XSD translator while parsing InputStream.
Please make sure that the xml data is valid.

at oracle.tip.adapter.jms.inbound.JmsConsumer.translateFromNative(JmsConsumer.java:591)
        at oracle.tip.adapter.jms.inbound.JmsConsumer.sendInboundMessage(JmsConsumer.java:407)
        at oracle.tip.adapter.jms.inbound.JmsConsumer.send(JmsConsumer.java:1185)
        at oracle.tip.adapter.jms.inbound.JmsConsumer.run(JmsConsumer.java:1065)
Caused by: oracle.xml.parser.v2.XMLParseException; lineNumber: 2; columnNumber: 82; Namespace prefix 'xsi' used but not declared.
        at oracle.xml.parser.v2.XMLError.flushErrors1(XMLError.java:323)
        at oracle.xml.parser.v2.NonValidatingParser.parseDocument(NonValidatingParser.java:409)
        at oracle.xml.parser.v2.XMLParser.parse(XMLParser.java:232)


Cause:
By default, BPM process variable refers to oracle.xml.parser.v2.XMLElement type and you need to convert it to String, before pass on to BPEL service.

Fix:
Surround input from BPM to BPEL process with string() function.

Thursday, June 30, 2016

WLS : SSL Certificate with Wildcard CN

Recently, I am supposed to integrate a SSL enabled web service. In order to that, first I imported the SSL certificate into WLS keystore and then I deployed the web service. When I tried to invoke an operation on the web service,  I faced an error that 'Hostname x.x.x.x is not verified'.

Then I verified and found that, SSL certificate is having wildcard in it's CN.

In this case, setting Hostname Verification to None will resolve issue. But it's not recommended in Production environments.

So enable Hostname verification as mentioned below to support SSL certificates with wildcard in the certificate CN.

1. Go to the WebLogic admin console -> Environment -> Servers -> <Admin/Managed Server> -> Configuration -> SSL
2. Click on "Advanced" icon to expand
3. Change "Hostname Verification" from "BEA Hostname Verifier" to "Custom Hostname Verifier"
4. Set "Custom Hostname Verifier" to weblogic.security.utils.SSLWLSWildcardHostnameVerifier
5. Click "Save" and restart Admin/Managed Server.

Sunday, May 22, 2016

WLS : FATAL Alert:BAD_CERTIFICATE

SOA 11.1.1.7.0

Last week, I faced below error when I tried to deploy a composite pointed to another remote web service WSDL URL from SOA Server.

Error:
<May 17, 2016 4:14:40 AM CDT> <Error> <oracle.integration.platform> <SOA-20003> <Unable to register service.
oracle.fabric.common.FabricException: Error in getting XML input stream: https://abc.xyz.com/Customer/ProxyServices/getCustomer?WSDL: FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificate was received.
    at oracle.fabric.common.metadata.MetadataManagerImpl.getInputStreamFromAbsoluteURL(MetadataManagerImpl.java:288)
    at oracle.integration.platform.common.MDSMetadataManagerImpl.getInputStreamFromAbsoluteURL(MDSMetadataManagerImpl.java:624)

Caused By: javax.net.ssl.SSLKeyException: FATAL Alert:BAD_CERTIFICATE - A corrupt or unuseable certificate was received.
        at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireException(Unknown Source)
        at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireAlertSent(Unknown Source)

Cause:
The root cause of  the problem was that, the remote web service URL was signed with the SHA-256 hash algorithm and WebLogic Server default settings does not support stronger algorithms like SHA-256.

Fix:
To remedy this, Java secure sockets extension (JSSE) must be enabled in Oracle Weblogic and JDK version needs to be upgraded to latest to avoid any runtime issues.

Enable JSSE:

Login to Weblogic Admin console -> server_name -> SSL -> Advanced ->. Check the checkbox Use JSSE. -> Reboot.

Note: Check "Hostname Verfication" drop down values as well if you have any other issues.



Sunday, April 10, 2016

WLS : Cannot Convert Identity Certificate

Recently we had an issue with expired Weblogic custom identity certificate and we used below commands to recreate the same.

Created New Identity Certificate:
keytool -genkey -alias client -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -validity 365 -keypass ******* -keystore identity.jks -storepass *******

Exported Certificate:
keytool -export -alias client -file root.cer -keystore identity.jks -storepass *******

Imported Certificate as Trusted:
keytool -import -alias client -trustcacerts -file root.cer -keystore trust.jks -storepass *******

Listed Keystores:
keytool -list -v -keystore identity.jks -storepass *******
keytool -list -v -keystore trust.jks -storepass *******

Later we faced one more error when we tried to start Admin Server and Node Manager.

Error: Cannot convert identity certificate

Cause: By default, WebLogic 11g doesn’t support the certificates with stronger signature algorithms like SHA256withRSA.

Fix: Enable JSSE support

1. Add below Java properties to setDomainEnv.sh file to enable JSSE across domain.

EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES}
-Dweblogic.ssl.JSSEEnabled=true -Dweblogic.security.SSL.enableJSSE=true"

Note:  '-Dweblogic.ssl.JSSEEnabled=true' is only valid for Weblogic 10.3.4 to 10.3.6

Follow below steps to enable JSSE for specific Managed Server:
Login weblogic console -> Click Servers -> Select the managed server -> lock&edit -> Configuration tab -> SSL subtab -> expand Advanced -> check “Use JSSE SSL” -> click Save button -> click 'Activate Changes' button -> Restart the managed server

2. Node Manager: Include below option in NodeManager.properties to support JSSE

JAVA_OPTIONS="-Dweblogic.security.SSL.enableJSSE=true"
export JAVA_OPTIONS

Saturday, March 5, 2016

OSB : Simple File Write Service - SOA Suite 12.2.1

Applicable to SOA Suite 12.2.1 Quickstart for developers

In this post, I will cover simple file write OSB web service creation using OSB 12.2.1 console.

Log in to OSB console http://localhost:port/sbconsole
Navigate to All Projects on left menu > Click on default > Click on 'Create' button to Create a session



Create Business Service:
Click on New Icon > Select Resource > Services > Business Service





Select Technology as file and click OK



In Create Business Service window, give Resource Name as 'WriteFile' and select protocol as file (if not). Click on Next arrow mark.



Leave default in next screen and go next



Add Endpoint URIs. In this case, added 'D:/temp' as output directory. Click Create button on last screen to create business service.



Create Proxy Service:
Click on New Icon > Select Resource > Services > Proxy Service > Technology > http. Click OK.



In Create Proxy Service window, give Resource Name as 'Caller' and select protocol as http (if not). Click on Next arrow mark.



Leave default in next screen and go next. Click Create button on last screen to create proxy service.





Expand default Projects folder > click on 'Caller-Pipeline' > click on 'Open Message Flow' icon



Add Route > Edit Route > Add an Action > Communication > Routing







Choose the 'WriteFile' business service and Submit.



Click on 'Activate' button to save all changes.



Testing:
Click on 'Caller' proxy service > click on 'Launch Test Console'



Test the proxy service with some random input



Go to 'D:/temp' directory, a file will be created with random name as shown below. Open the file with Notepad to view the content that passed as input.



That's it..!

Sunday, February 14, 2016

ADF : VO Query Dynamic WHERE Clause

Recently, I faced a scenario where I need to dynamically change the View Object's query WHERE clause. I followed below steps to address it.

Steps:
  • Override the buildWhereClause(StringBuffer stringBuffer, int i) VO method
  • Call super.buildWhereClause() to allow the framework processing. This call will return a Boolean indicator of whether a WHERE clause was appended to the query, indicated by the Boolean appended local variable.
  • The StringBuffer parameter that is passed to the method is the complete query SQL statement. Do your changes directly onto it. When done, make sure that you return appropriately a true/false boolean to to the framework to indicate whether a WHERE clause was appended to the query or not.

Example: Add/append additional WHERE condition when logged in user is not an ADMIN.

@Override
protected boolean buildWhereClause(StringBuffer stringBuffer, int i) {
        // TODO Implement this method      
      boolean hasWhereClause = super.buildWhereClause(stringBuffer, i);
      boolean isAdmin = ADFContext.getCurrent().getSecurityContext().isUserInRole("ADMIN_ROLE");

      if (hasWhereClause) {
          if (!isAdmin) {
              stringBuffer.append(" AND (USER_EMAIL =  ' " + ADFContext.getCurrent().getSecurityContext().getUserName() + "')" );
           }
        } else {
          if (!isAdmin) {
              stringBuffer.append(" WHERE (USER_EMAIL =  ' " + ADFContext.getCurrent().getSecurityContext().getUserName() + "')" );
              hasWhereClause = true;
            }
        }
        return hasWhereClause;
    }

SOA : WSM-00138: The path to the certificate is invalid

Recently, I integrated a secured web service with Oracle SOA and faced following error when I tried to test the web service call. I used OWSM policy  'oracle/wss10_message_protection_client_policy' to sign the request message.

Error:
<Feb 03, 2016 10:30:56 AM CST>  <Error> <oracle.webservices.service> <OWS-04086> <javax.xml.rpc.soap.SOAPFaultException: oracle.fabric.common.FabricInvocationException: Unable to invoke endpoint URI "https://abc.xyz.com/WebService" successfully due to: oracle.fabric.common.PolicyEnforcementException: WSM-00276 : Validation failed for the identity published in the WSDL endpoint "https://abc.xyz.com/WebService".

Caused By: oracle.wsm.security.SecurityException: WSM-00138 : The path to the certificate is invalid.
 Validation failed for the certificate "Subject DN:- CN=dummy_key, OU=abc, O=XYZ, C=US, Serial Number:- 1430987244, Issuer DN:- CN=dummy_key, OU=abc, O=XYZ, C=US"
 Certificates in cert path used for validation are:-
"Subject DN:- CN=dummy_key, OU=abc, O=XYZ, C=US, Issuer DN:- CN=dummy_key, OU=abc, O=XYZ, C=US"
        at oracle.integration.platform.blocks.soap.WebServiceEntryBindingComponent.generateSoapFaultException(WebServiceEntryBindingComponent.java:1279)

Fix:
Imported additional(intermediate/identity) certificates(X509) associated with secured web service into SOA's Keystore as trusted certificates and rebooted server(s).

Notes:
I enabled WSSE debug flags in Weblogic Server setDomainEnv.sh to find out exact cause. Don't forget to disable the flags, otherwise you will confront excessive logging issue.

EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dweblogic.wsee.verbose=* -Dssl.debug=true"
export EXTRA_JAVA_PROPERTIES

DB: ORA-01688: unable to extend table

Recently, I encountered following error in Oracle Database 12c log files.

Error:
ORA-02002: error while writing to audit trail
ORA-55917: Table flush I/O failed for log ID: 1 bucket ID: 0
ORA-01688: unable to extend table AUDSYS.CLI_SWP$8ab1e924$1$1 partition HIGH_PART by 1024 in tablespace SYSAUX partition by in tablespace

Then I logged into Database 12c as SYSDBA and ran following queries to verify tablespace quota.

Query 1:
========
SELECT df.tablespace_name "Tablespace",
       totalusedspace "Used MB",
       (df.totalspace - tu.totalusedspace) "Free MB",
       df.totalspace "Total MB",
        round(100 * ( (df.totalspace - tu.totalusedspace)/ df.totalspace))"Pct. Free"
FROM   (SELECT tablespace_name,round(sum(bytes) / 1048576) TotalSpace FROM dba_data_files GROUP BY tablespace_name) df,
       (SELECT round(sum(bytes)/(1024*1024)) totalusedspace, tablespace_name FROM dba_segments GROUP BY tablespace_name) tu
WHERE  df.tablespace_name = tu.tablespace_name;

Tablespace                      Used MB    Free MB   Total MB  Pct. Free
------------------------------ ----------     ---------- ---------- ----------
SYSAUX                               5075         45       5120          1
USERS                               21082       3677      24759         15
SYSTEM                                728         12        740          2

Query 2:
========
SQL> SELECT * FROM dba_tablespace_usage_metrics;

TABLESPACE_NAME    USED_SPACE TABLESPACE_SIZE USED_PERCENT
------------------------------ ---------- --------------- ------------
SYSAUX                             649784          655360   99.1491699
SYSTEM                              93312          655360   14.2382813
USERS                             2699032        14028248   19.2399792

Just to rewind, a tablespace is where the physical Oracle meets the logical Oracle and a tablespace is a bit like a file system for your database. It is a logical entity (this means the tablespace only exists within the Oracle database itself, not outside of it) that provides storage space so that users can create things like tables and indexes. And one datafile can only be assigned to one tablespace.

And I fixed this issue by adding data file to SYSAUX tablespace using below command.

> ALTER TABLESPACE SYSAUX ADD DATAFILE '/xyz/oradata/data01/sysaux01.dbf' SIZE 200M AUTOEXTEND ON NEXT 20M MAXSIZE 5120M;

Note that I used 200M to indicate that I wanted to create the tablespace 200 Megabytes in size and the tablespace will auto extend in increments of 20 Megabytes until it reaches a maximum size of 5120 Megabytes. It's recommended to use auto extend on all tablespaces for Production databases.

Note, if you want to resize data file, use alter database command.

> ALTER DATABASE DATAFILE '/xyz/oradata/data01/sysaux01.dbf' resize 500M

Sunday, January 3, 2016

DB: Logical Reordering of Columns

Applicable to 12c

Following post will help you to logically(not physical) reorder the columns in a table with the help of invisible columns feature in 12c.

Let's say, we have a table TAB1 having 2 columns COL1, COL2.

CREATE TABLE TAB1
  ( COL1 NUMBER,
    COL2 NUMBER);

Now suppose that, we need to add new column COL3 and it should appear in middle of the table.. We could achieve this column reordering without using invisible columns as follows.
  • Rename the table TAB1 to something, For Ex: TAB2
  • Add new column COL3 to table TAB2, which would appear at the end of the column list.
  • Create a view or an editioning view named TAB1 that explicitly selects the columns in the right order
  • Revoke the grants on TAB2 and issue those grants on the view TAB1
  • Update the scripts(indexes, triggers, constraints) to refer renamed table TAB2
This may help us to make the column seem to appear in the middle of the table, but require lot of efforts. But we can achieve the the logical reordering with minimal efforts using invisible columns feature in 12c as follows.
  1. First hide the column COL2 and Add column COL3. At this point, column COL3 will appear to be right after column COL1.

  2. ALTER TABLE TAB1 MODIFY COL2 INVISIBLE;
    ALTER TABLE TAB1 ADD COL3 NUMBER;

  3. Next unhide column COL2 and it will appear after column COL3 logically.

  4. ALTER TABLE TAB1 MODIFY COL2 VISIBLE;

  5. Describe the table TAB1

  6. DESC TAB1

     Name       Type
     —————   ——————
     COL1        NUMBER
     COL3        NUMBER
     COL2        NUMBER

But physically these columns will be stored as COL1, COL2, COL3 on disk.

DB: Virtual and Invisible Columns

Following post will help you to understand the usage of couple of new features introduced in Oracle database.

Virtual Column (Introduced in 11g R1):

Virtual columns are expressions that are based on one or more existing columns in the table. A virtual column is only stored as metadata. It does not consume physical space, but it can be indexed. The virtual column also contains optimizer statistics and histograms.

When queried, virtual columns appear to be normal table columns, but their values are derived rather than being stored on disc. The syntax for defining a virtual column is listed below.

Syntax: column_name [datatype] [GENERATED ALWAYS] AS (expression) [VIRTUAL]

If the datatype is omitted, it is determined based on the result of the expression. The GENERATED ALWAYS and VIRTUAL keywords are provided for clarity only.

Benefits:
  • Automatic re-computation of derived columns for ad-hoc query tools
  • Reduction in redundant disk space for columns that must be derived from other columns
  • Using virtual columns in tables also eliminates the need to use views to display derived column values.
  • Using a virtual column also simplifies the use of derived columns. Transparently derived values do not require the application to calculate and insert an additional value. This also prevents the need to use a trigger on the table to provide an alternate implementation of this functionality.

Limitations:
  • Virtual columns may not reference other virtual column values:
  • Virtual columns only work within the specified table, and you cannot reference columns within other tables.
  • Virtual columns can be referenced in the WHERE clause of updates and deletes, but they cannot be manipulated by DML.
Ex:
CREATE TABLE EMP (
  id            NUMBER,
  name      VARCHAR2(100),
  salary      NUMBER(9,2),
  commission  NUMBER GENERATED ALWAYS AS (ROUND(salary/100,2)) VIRTUAL,
  CONSTRAINT emp_pk PRIMARY KEY (id)
);

INSERT INTO EMP (id, name, salary)  VALUES (1, 'LKAKARLA', 100);

SELECT * FROM EMP;

Invisible Column (Introduced in 12c R1):

This new feature in 12c allows to make invisible columns for generic queries, operations. When a column is defined as invisible, the column won’t appear in generic queries, unless the column is explicitly referred to in the SQL statement or condition, or DESCRIBED in the table definition. You must explicitly refer to the invisible column name with the INSERT statement to insert the database into invisible columns.

Syntax: 
Invisible Column: column_name [datatype] [INVISIBLE]
Invisable Virtual Column: column_name [datatype] [INVISIBLE] [GENERATED ALWAYS] AS (expression) [VIRTUAL]

Benefits:
  • Hide important data - columns from being displayed in the generic queries
  • Invisible columns can be useful during application migrations. Making new columns invisible means they won't be seen by any existing applications, but can still be referenced by any new applications, making the online migration of applications much simpler.
  • Virtual columns can be made invisible.
  • Ability to logically reorder the columns in a table (refer link)

Limitations:
  • Temporary tables, external tables and cluster tables won’t support invisible columns.
  • Following operations don’t see invisible columns
    • SELECT * FROM statements in SQL
    • The DESCRIBE statement when used in either SQL*PLUS or via Oracle Call Interface (OCI) (SET COLINVISIBLE ON in SQL*PLUS to see invisible columns)
    • %ROWTYPE attribute declarations in PL/SQL
Ex:
CREATE TABLE EMP (
  id            NUMBER,
  name      VARCHAR2(100),
  salary      NUMBER(9,2),
  dob         DATE INVISIBLE,
  commission  NUMBER GENERATED ALWAYS AS (ROUND(salary/100,2)) VIRTUAL,
  bonus       NUMBER INVISIBLE GENERATED ALWAYS AS (ROUND(salary/200,2)) VIRTUAL,
  CONSTRAINT emp_pk PRIMARY KEY (id)
);

INSERT INTO EMP (id, name, salary, dob)  VALUES (1, 'LKAKARLA', 100, SYSDATE);

DESC EMP;

SET COLINVISIBLE ON;

SELECT * FROM EMP;

SELECT ID, NAME, SALARY, DOB, COMMISSION, BONUS FROM EMP ;

ADF: JSTL with ADF Faces Rich Client Components

Following post will help you to understand the usage of JSTL along with ADF Faces.

The JavaServer Pages Standard Tag Library (JSTL) is a collection of useful JSP tags which encapsulates core functionality common to many web application functionalities.

Here I listed commonly used JSTL expressions:

Function
Description
fn:contains()
Tests if an input string contains the specified substring.
fn:containsIgnoreCase()
Tests if an input string contains the specified substring in a case insensitive way.
fn:endsWith()
Tests if an input string ends with the specified suffix.
fn:escapeXml()
Escapes characters that could be interpreted as XML markup.
fn:indexOf()
Returns the index withing a string of the first occurrence of a specified substring.
fn:length()
Returns the number of items in a collection, or the number of characters in a string.
fn:replace()
Returns a string resulting from replacing in an input string all occurrences with a given string.
fn:startsWith()
Tests if an input string starts with the specified prefix.
fn:substring()
Returns a subset of a string.
fn:substringAfter()
Returns a subset of a string following a specific substring.
fn:substringBefore()
Returns a subset of a string before a specific substring.
fn:toLowerCase()
Converts all of the characters of a string to lower case.
fn:toUpperCase()
Converts all of the characters of a string to upper case.
fn:trim()
Removes white spaces from both ends of a string.


















You need to import JSTL namespace (xmlns:fn="http://java.sun.com/jsp/jstl/functions") into your page/fragment to refer JSTL tags.

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:fn="http://java.sun.com/jsp/jstl/functions">

JSTL Sample Examples: 
1. Get Records count in an Array List:
<af:outputText value="#{fn:length(pageFlowScope.empBean.employeeList)}" id="ot1"/>
2. Match content of String:          
<af:outputText value="#{fn:contains(bindings.deptName.inputValue,'SALES') ? 'SALES' :  'OTHER'}" id="ot1"/>

For more details, refer link