Wednesday, November 26, 2014

Suppressing ADF LOV Like Operator Filtering V2

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.

Additional method is overridden in LOV VO implementation class - applyViewCriteria(ViewCriteria, boolean). Besides previously overridden method buildViewCriteriaClauses(ViewCriteria), this method provides additional handling for LOV Like operator suppression. Download sample application - ADFTableApp_v2.zip.

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

BPM Authentication On Behalf Business User from ADF

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

Dynamic ADF Buttons Solution for Oracle BPM Outcomes

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:

Friday, November 7, 2014

Dynamic ADF Form Solution for Oracle BPM Process

I was working recently on integrating ADF 11.1.2.4 and BPM 11.1.1.7 environments. This worked pretty well, all configuration was done based on my previous blog post for similar topic, only previous ADF and BPM versions - BPM 11g R1 Worklist Integration (Hacking Experiment) Into Non-SOA ADF 11g R2 Domain. Goal of this post is to describe dynamic ADF form approach associated with BPM process human task.

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

MdsMetadataResourceProvider Error in ADF 11.1.1.7

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:


Here you can download sample application with correct API usage - ADFMetadataInternalApp.zip.

Tuesday, October 28, 2014

Handling Date Format and ADF Bindings

There are tips and tricks related to the date format handling and ADF bindings. When Oracle date type attribute is being used through ADF binding expression, it will be converted to String with default format (yyyy-MM-dd), no matter what original format was set. This is described in API for the Oracle date type - Date constructor with String. Below I'm going to explain how it works and how you could optimise ADF application to handle date type attributes from ADF bindings layer.

Sample application (download it here - DateFormatApp.zip) is based on one simple VO with calculated attributes, both oracle.jbo.domain.Date type:


ADF UI implementation is standard - there are ADF Input Date components with regular date converters:


There is a button on UI, it calls custom method implemented in AM and exposed through the bindings. This method accepts two parameters, both oracle.jbo.domain.Date type. I'm using regular binding expression and getting inputValue property (this returns formatted value of the date):


Try to invoke the method, you will get an error about invalid argument - binding expression with date attribute is not accepted. It is trying to use formatted value dd/MM/yyyy and set it for the custom method argument value, but Oracle date accepts only yyyy-MM-dd (I'm using Alta UI skin):


Error message is written in the log:


The workaround is to use attributeValue instead of inputValue in the binding expression. Property attributeValue returns original unformatted date type attribute value:


Do the same test again, type both dates and press Test Dates button - this would work now:


I'm checking out date values in the custom method. Originally it comes unformatted date value, taken from attributeValue property. If we would like to use date value in the certain format (e.g. send to PL/SQL in format dd/MM/yyyy, instead of default yyyy-MM-dd), we should apply DefaultDateFormatter to retrieve the formatted String value for the original date:


Here is the output from the custom method:

Thursday, October 23, 2014

ADF BC View Object SQL Query Customization with MDS

This post is based on my previous article about MDS Seeded Customization - MDS Seeded Customization Approach with Empty External Project. Today I will focus on explaining how to customise SQL query for read-only VO. This is not so obvious as it sounds. However, it is doable - I will explain how.

Sample application - MDSCustomizationsApp_v2.zip contains both main and customisation projects. Main project implements read-only VO for Jobs data, it doesn't include Job Title attribute:


This is how SQL query looks for such VO in the wizard:


We should take a look into the source code, SQL query is defined by SQLQuery tag. Tag doesn't have ID, this would disable tag customisation using JDEV MDS wizards:


No matter there is no ID set, we still could customise it - I will show you how. Here is the example of SQL query customisation stored in MDS customisation file. Firstly you should remove SQL query completely from VO and then add it again (this will create two entries in MDS customisation file). Once SQL query is written to the MDS customisation file, we can change it as we would like to - Job Title attribute is added to the SQL statement:


We need to add separately VO attribute for Job Title, this can be done through JDEV MDS customisation wizard. Make sure to set IsSelected=true property, otherwise attribute will not be set from the query:


You should drag and drop Job Title attribute from Data Control into the fragment, this will generate binding entry in the page definition file:


UI component for Job Title will be generated as ADF Faces output text:


You should notice on runtime customised SQL statement executed, this statement would include Job Title added through MDS customisation:


Job Title value is fetched and displayed on UI: