Thursday, June 28, 2012

BPM 11g HTML Email Notification

As on the date of writing this entry, the latest BPM release is 11.1.1.6 (also called the PS5). If you have ever wondered or had issues in sending 'HTML' email notifications from BPM 11g using the 'Notification' activity, here is a workaround to get the HTML email notifications working.

In your BPM process drag and drop the 'Notification' activity from the activity pane and configure the settings. This will create a 'BPM-Notification Service' web service adapter with a set of operations (for different communication channels) under the 'External References' swim lane of the Composite editor. If you closely notice, there is no way to explicitly specify the 'Content Type' using the default 'Notification' activity and hence all emails are by default are 'text/plain' types.

To overcome this issue, drag and drop a service task and refer to the 'BPM-Notification Service' web service and under 'Data Associations' expand the 'Content' section of the notification service and map the 'ContentType' element to 'text/html' along with other configuration details such as 'fromAccount', 'to' etc..

Essentially what we are trying to achieve here is that to explicitly specify the email 'contentType' by leveraging the service task 'Data Association' capability.

Now, all your message content with HTML tags for formatting such as <BR> will take effect and the email messages would be HTML formatted.

Wednesday, June 27, 2012

BPM 11g - Validating Boolean DO in User Task Skip Condition

This may sound like a small thing but honestly speaking I had to try out multiple methods to get this working through XPath expression builder. Hence I thought of making note of this on my blog so it may help a needful soul :)

<Employee>
   <EmployeeName>John Smith</EmployeeName>
   <IsMarried>true</IsMarried>
   <IsContract>true</IsContract>
</Employee>

Use-Case: All employees who are 'Contract' should be reviewed by 'Group A' and 'Permanent' employees must go through an additional level of review by 'Group B'.

Solution: The most logical way to build/represent this use-case in BPM 11g would be to create a user task with two sequential approval/review stages where the first stage participants would be 'Group A' and the sequential stage would be attended by 'Group B'. Now, by leveraging the 'Skip Condition' capability we can build a condition on 'Stage 2' to validate whether the boolean data object (in this case 'IsContract' element) is false. This means that if the <IsContract> element is true it skips the second stage of review else it goes through the second level of review.



Let's say the boolean data objects are modelled as 'Check Boxes' in ADF - where it returns 'true' when checked or 'false' when not checked by the user

Now, the problem is how to evaluate the boolean data object in Skip condition. Here is one way to evaluate boolean data objects;

xp20:matches(string(/task:task/task:payload/Employee/IsContract), '\s*(?i:true|1)\s*')='true'

What we are doing here is that converting the boolean data type into String and matching the result against the string 'true' or 'false'. Apparently we have to do this because, the direct boolean validation [/task:task/task:payload/Employee/IsContract = true] doesn't work in Skip condition.

Hope this helps.


Thursday, June 14, 2012

Oracle Business Rules: "Fact not found in the rule engine working memory" error

At run-time when you encounter the following error from a Business Rule component, more often than not, the reason/cause could be that there is no 'otherwise' branch defined in the business rule causing the business rules engine to throw this not-so-straight-forward error message.

Non Recoverable Business Fault :

Fact not found in the rule engine working memory, rule session execution failed. The rule session 130287 failed because an instance of the fact Response could not be found in the working memory of the rule session. This is most likely a rule modeling error. The decision service interaction expects the fact instance to exist in the working memory of the rule session. Check the rule actions in rule designer and make sure that a fact of the expected type is being asserted. If the error persists, contact Oracle Support Services.

Okay - Anyways the solution is to model the Business Rule for ALL probabilities!

It could be as easy as this - Just add the 'otherwise' rule to take a default action for cases where none of the rules match.

Thursday, June 7, 2012

ADF 11g Table Row Selection

By default, when the 'Row Selection' property of the ADF af:table component is set to 'Single', the first row rendered in the table at run-time is 'Selected'. This is all fine and works as expected. The issue occurs in a scenario where the end-user wants to choose exactly the same row that ADF renders as 'Selected' especially when there is a back end logic to fetch and process the selected row values. This is because the 'selection listener' on the table is invoked only when a row state changes from 'unselected' to 'selected' - hence the behaviour.

In order to overcome this situation and ensure that 'NO' rows are 'rendered' selected by default, clear the 'SelectedRowKeys' property under the 'Advanced' section. This will ensure that at runtime ADF renders the table with no rows selected.

On the other hand, if you override the 'Selection Listener' with a custom listener (to process selected row values) you might want to use the following code snippet in your backing bean to make the current row selected;

        ADFUtil.invokeEL("#{bindings.CI_CA_HDR_PNG.collectionModel.makeCurrent}",
                                 new Class[] { SelectionEvent.class },
                                 new Object[] { selectionEvent });

where #{bindings.CI_CA_HDR_PNG.collectionModel.makeCurrent} is nothing but the default 'Selection Listener' value.

Tuesday, June 5, 2012

JDeveloper 11g Cannot Establish App Server Connection

Very often I see people bump into this error and thought I should make some notes here which might help someone in need.

First of all, I would like to make some inferences from the JDeveloper documentation;

"By default, JDeveloper uses the proxy settings from the default browser on the same machine, adding localhost and 127.0.0.1 to the list of proxy exceptions. If you have problems making connections from JDeveloper, for example, connecting to an application server or a SOAP server that is on the same machine as JDeveloper, you may need to change the proxy server settings you use."

Pre-Requisite:
While trying to establish a connection to the App server from JDeveloper, ensure that the following settings are correct;

1. Weblogic Hostname : resolves to the actual IP address of the server
2. Port: 7001 (default admin server port) or as per your admin port configuration during install. Remember you should only use the admin server port of your WebLogic server here even if you have an architecture where you front end the app server with a HTTP server like OHS
3. Domain: Use the domain name that was created during the WLS configuration

Check 1: Check whether the proxy settings are disabled in JDeveloper. Go to Tools -> Preferences -> Web Browser & Proxy section and ensure that no HTTP proxy server is setup. If already configured, uncheck the check box and click OK

Check 2: Test whether the port 7001 on the WLS host is accessible from the machine where JDeveloper is installed. You can test this with a simple telnet command;

telnet hostname 7001

If this test doesn't succeed then there can be two possible reasons;

1. There can be a network firewall or firewall enabled on the server which blocks this admin port from being accessed from a client machine. If this is the case, then ask your network administrator to open the port. This can be done by adding the port to the ip6tables on the linux server or similar.

2. Do a netstat on the linux server where WebLogic is installed to find out whether the port is open and is available (LISTEN mode). Ensure that your admin server is running when you run this command

eg., netstat -apn | grep 7001

This will show up the ip addresses from which the host can accept requests. Some common causes that I have identified is that the /etc/hosts file contains the ip - hostname mapping as follows;

127.0.0.1          hostname1

When the WebLogic server starts up, it will start all services properly but a closer look at the netstat command reveals that the host accepts connections only from within the server (127.0.0.1). This means that the port is virtually blocked for any requests coming from outside the machine/host itself. To resolve this issue, change the /etc/hosts file entry as follows;

<ip address of host >       hostname1

Now, stop all services and restart the services. This enables all WebLogic ports and accessible from outside the server.