Saturday, November 29, 2014

Previously I had a post about dynamic ADF attribute binding creation and dynamic ADF form generation - Adaptive Form with Dynamic ADF Attribute Value Binding. Blog reader was asking how to generate dynamic ADF LOV binding using similar approach. This is possible and actually documented in Eugene Fedorenko post here - Dynamic LOV binding. I will use the same piece of code to extend my sample application with dynamic ADF LOV binding support.

Once you are generating dynamic components on the UI and getting VO attributes to render, you should not be surprised there will be more attribute entries returned than you can see defined in VO. Additional attributes are for View Accessors, and we don't need them while generating dynamic ADF UI. This can be controlled by checking attribute kind property for attribute definition. If attribute kind is not of rowset kind, we can display it:

There is another method in the sample app, it checks for attribute type. This helps to decide what kind of UI component to render - input text, input date, LOV, etc.:

Here is the essential part of the updated sample app - LOV binding creation method. LOV binding is constructed, similar as ADF attribute binding, by pointing to the iterator, LOV server binding name, attribute name and ID:

Dynamic ADF UI components are stamped through ADF UI iterator:

There is a special Facet to support ADF LOV UI component creation. UI component is created by pointing to the helper method, where ADF LOV binding is constructed:

LOV generated dynamically works well on runtime, user can open a list and select a value:

LOV validation also works, try to enter invalid value (not available in the list), user will be prompted to enter existing value instead:

Wednesday, November 26, 2014

I had a post about the solution to suppress ADF LOV Like operator and prevent LOV popup loading when user is typing existing value - Suppressing ADF LOV Like Operator Filtering. Thanks to a blog reader, there was one use case found, when Like operator was not suppressed properly. This is fixed now and I would like to post updated sample application here.

Blog reader reported an issue, when LOV value was changed to 10, again changed to 100 and again 10, then LOV popup was opened on the last change. This should not happen, as value 10 exists in the LOV. It seems like when LOV value is changed to the same as it was set before, ADF BC executes extra call for LOV filter through applyViewCriteria method. This is why this method is overridden as well as buildViewCriteriaClauses.

Both methods are overridden and check for STARTSWITH (Like) operator is implemented:

It works well now. Try to enter value 10, LOV will accept this value without opening LOV popup:

Enter value 100, this value will be accepted as it exists in the LOV list:

Again enter value 10, it will be accepted as it was previously (it will not be, without overriding applyViewCriteria method):

If I type any value, not available in the LOV list:

As expected LOV popup will be opened and user could select a valid value:

Wednesday, November 19, 2014

This is the next post in the series of ADF/BPM integration, check previous post available here - Dynamic ADF Buttons Solution for Oracle BPM Outcomes. Here I'm going to describe how you could authenticate with BPM from ADF through a proxy user, on top you could apply only business user name, password will not be required.

There is API method available - authenticateOnBehalf(context, userName), you must have a valid connection context created and with authenticateOnBehalf method you could set to use any valid user name, instead of proxy user. Here is the example for Workflow Context:

Similar example for BPM Context, same authenticateOnBehalf method:

As a proxy user I'm using weblogic. You could set to use any different user and consider it as a proxy user.

Tasks assigned for redsam1, connected through proxy user weblogic, are retrieved and displayed in the table:

This is how you could avoid using password for each business user and simply create initial connection through a proxy user. Download sample application - adfbpm11gr4.zip.

Thursday, November 13, 2014

BPM Human Task activity is configured with outcomes. Based on these outcomes, buttons in ADF UI are constructed allowing user to perform different actions with the task. Auto generated ADF Human Task form contains a set of predefined buttons and this set is controller with rendered flag. My sample application is using different approach, it implements custom tasks table and dynamic ADF UI for the human task input form - Dynamic ADF Form Solution for Oracle BPM Process. Once user selects a task, action buttons are generated dynamically - using a set of outcomes configured for the particular task.

Here you can download complete sample application - adfbpm11gr4.zip. This application implements a method based on BPM API, where a list of outcomes by the currently selected Task ID is fetched from BPM engine:

Each outcome is represented by ActionType. I'm constructing a list of outcomes to be used on ADF UI. There is ADF UI iterator components on the fragment, this component is generating dynamic buttons, based on the constructed set of outcomes. Outcome name is used to set button name and outcome itself is used as attribute value for the generic action listener method:

Generic action listener method is responsible to parse outcome name, initialise a payload if needed, and execute BPM API to submit the outcome for further task processing:

We can check how this works. There is a human task AssignEmployee with SUBMIT outcome, in the sample application:

Task action button is generated accordingly - there is only one Submit action button for the selected task:

The next human task ApproveEmployee is set with two outcomes - APPROVE and REJECT:

Based on the set of the outcomes, two buttons are present now - Approve and Reject:

BPM payload contains additional element called voInstanceName. This element is supposed to contain ADF VO instance name, this instance will be used later to render dynamic ADF UI for the currently selected task:

Sample application - adfbpm11gr4.zip, is based on two separate applications. One implements simple BPM process with payload including ADF VO instance name and another implements standalone dynamic ADF application with BPM API.

There are two human tasks in BPM process. Each of these human tasks accepts a payload element with ADF VO instance name. This allows to control ADF UI from BPM process, by providing ADF VO instance name to be used in ADF. The first human task is set to work with EmployeesView1 instance:

Second human task is set to work with different ADF VO instance - EmployeesROView1:

I'm reading voInstanceName payload variable value in ADF application, to construct dynamic ADF UI accordingly. Accessing currently selected task by ID and retrieving payload information for voInstanceName. Later this information will be used to construct dynamic ADF iterator:

Value from voInstanceName payload is used as a parameter for the ADF task flow rendering dynamic ADF UI. Task flow is configured to refresh each time, when parameter value is changed - new UI will be rendered for each new task selected:

ADF task flow checks if parameter for voInstanceName is not empty (it could be empty, if there are no tasks from BPM or payload value was not set). If there is no value, user will be redirected to the empty fragment:

Dynamic ADF UI is constructed in the bindings, instead of using static ADF iterator - we are initialising iterator from task flow parameter value passed through voInstanceName. This is how we can switch between different VO's from the ADF BC, depending on BPM task selected:

ADF UI is rendered with dynamic ADF form component. There are several ways to implement dynamic ADF UI, it can be all custom or using out of the box ADF UI components (depends on use case requirements). Here I'm using out of the box dynamic component, because UI is fairly simple:

This is how it looks like. Initially there are no tasks, no dynamic ADF UI - blank screen:

Start a new task in BPM, task is started through BPM API from standalone ADF application:

ADF UI form is rendered for the task. User can select a task and then select Employee, by navigating with Next/Previous buttons. As soon as Employee is selected (ID: 103), task can be submitted for further processing:

Login with different user - redsam2 and you are going to see new task in the inbox. Employee data is rendered from different VO instance and is readonly now. Employee ID was taking from the payload, this is how a row with ID: 103 is selected (the same as selected in the previous step):

Employee data in the second step is rendered from different read-only VO, including Job Title attribute:

There are two human task activities in the process, both are rendered with different dynamic ADF UI:

Monday, November 3, 2014

If you have migrated ADF application to ADF 11.1.1.7 version recently, you may see error in the log related to the internal MetadataResourceXmlImpl class usage. Runtime behaviour will not be affected, but there could be many redundant error messages in the log, like this one:

Error UNEXPECTED_CLIENT_OBJECT_TYPE found oracle.adf.controller.internal.metadata.xml.MetadataResourceXmlImpl, points to the ADF internal class usage, instead of public. You must look through the source code and you should find illegal internal imports for MetadataService and TaskFlowDefinition classes. Typically ADF developer would use such classes in the previous ADF versions to check if specific ADF TF exists:

In ADF 11.1.1.7 you can use public classes for MetadataService and TaskFlowDefinition, instead of private. To fix the error, you only need to change class import: