Saturday, July 4, 2015

Oracle Process Cloud Service - Consuming ADF BC REST Service in Web Form

With the introduction of Oracle Process Cloud Service (https://cloud.oracle.com/process) there is an option to run your business process in the cloud. You can implement very similar things as it is possible with BPM 12c in JDeveloper, but only in the cloud. There is no option to implement human task UI with ADF, it must be done with Web Forms (light UI forms implementation framework). This is disadvantage, as it will require to externalise complex business logic and access data collections through REST calls, instead of processing it locally in ADF extension. However, this is how it is implemented currently in the BPM cloud version.

This is how it looks - Web Form editor in Process Cloud Service:


You have an option to select specific types from component palette. There are such types as money, email, phone, text. Components are provided with built in validation, checks for valid email address, etc. User who implements a form, needs to drag and drop components one by one (generally it works OK, but sometimes may get stuck and page refresh will be required). Properties section is available to enter details for the selected component.

Cool part about it - we can define business logic rules. For example, to show/hide customer field based on trip type, etc. One of the rules below, shows how REST service can be called inline and REST response is applied for drop-down field. This is pretty simple to fetch data from external REST service and use it for the Web Form component. Just invoke REST service and assign collection to the component supporting array of data:


If REST call requires to pass parameters through URL, this is also possible, see example below - list of cities, based on the selected country in the Web Form:


Web Form works pretty well in Preview mode, it even calls REST services and shows real data. Validation messages for built-in checks are displayed pretty nicely. Here I'm selecting a country from the list populated by REST service:


Based on the selection in the Country drop-down, filtered list for Cities becomes available (another REST call):


Good news - most of the Oracle Process Cloud interface itself is implemented with ADF. Here you can see a section listing all Web Forms available for the current process:


I have implemented REST service for Countries and Cities lists in ADF BC. There are two custom methods in AM implementation, to fetch the data and transform it to the list format:


REST resources are defined through annotations and are configured to produce JSON data, this will allow Oracle Process Cloud to parse such data automatically:


If you are going to check how REST service is implemented in ADF BC, you can run a query in Postman to retrieve a list of all countries from HR schema:


Another query to retrieve a list of cities, by country:


Download sample application, with ADF BC REST service - RestADFBCApp.zip.

Wednesday, June 24, 2015

Intercepting Table Filter Query and Manipulating VO SQL Statement

I’m going to describe one non declarative use case. Imagine, if there is a table with filter functionality, you may want to intercept filter items and apply the same for another VO. This another VO should be based on the same DB table, so it could apply criteria items against the table.

Sample application - AdvancedViewCriteriaApp.zip, implements a fragment with table component and a chart. Table component can be filtered, criteria is intercepted and applied for the chart, this one is rendered from different VO with GROUP BY query. Chart stays in synch and displays data according to the criteria filtered in the table:


In the log, I’m printing out intercepted criteria from the table filter:


Chart is rendered from the SQL query below:


Table filter criteria is being intercepted by overridden method buildViewCriteriaClauses. Criteria clause is constructed here, we just need select FilterViewCriteria, the one originating from table filter. We could apply this criteria straight ahead to the VO responsible to bring chart data. However, this would not work - ADF BC would wrap original chart SQL query with SELECT * FROM (…) QRSLT WHERE (table filter criteria). This would not work, because table filter criteria is not present in the original chart SQL statement. To make it work, I’m updating original SQL query for chart data, by updating WHERE clause part:


In the last step, we need to pass bind variable values - the ones user is searching for in table filter. This can be done from another overridden method - bindParametersForCollection. We have access to the applied bind variables in this method. Again, you should check for FilterViewCriteria and extract applied bind variables values. Chart VO will be updated with bind variable definitions created on the fly and assigned with values to search for:


I hope this trick will save some of your time, if you are going to implement something similar - to intercept table filter query and apply it to the another VO, based on same DB table.

Thursday, June 18, 2015

Select One Choice with Select Items Tag

If you need to implement select one choice based on alternative data sources (not based on ADF BC) - you shouldn't use af:forEach inside af:selectOneChoice component. Don't get confused with af:forEach tag, this tag is supposed to generate multiple components and not to iterate over a collection of objects and render HTML for each item. There could be cases, when choice list data will come duplicated, with af:forEach tag applied. I would suggest to construct array of SelectItem objects and return it to the f:selectItems tag to be rendered.

This is how proper af:selectOneChoice definition should look like. Array of items is being rendered in the choice list through f:selectItems tag:


Value property for f:selectItems can be entered manually or through the wizard, when creating af:selectOneChoice - this should point to the custom method, where array of SelectItem objects is constructed:


Custom method could read data from any source and construct array of SelectItem objects. This is the input for f:selectItems tag, it knows how to render a list of choice list items out of it:


This is how it looks on runtime - choice list is working fine, no need to use af:forEach:


Download sample application - CustomSelectListApp.zip.

Thursday, June 11, 2015

How To Record ADF Client Side Request Performance Time

I had a blog post, where I have described how to monitor client side request performance time with Ajax tag (works in ADF 12c) - Monitoring PPR Request Time on ADF UI Client Side. There is effective way to propagate recorded statistics back to the server for history logging using WebSockets - WebSocket Integration with ADF for PPR Request Monitoring. This requires WebSockets integration into project, if project doesn't allow this - there is another way. We could leverage Ajax call to the Java servlet and pass logged statistics data through parameter. I will describe how this can be achieved.

Sample application - ADFAltaApp_v6.zip, implements standard servlet. In the doGet method, I'm accessing parameter and parsing received statistics data. From here we could log data to the DB, so it could be analysed further. Data processing should be executed in the separate thread, not to block servlet execution and return response back to the client. Java in ADF 12c supports asynchronous servlets, however this is not the case with ADF 11g versions (unless you change JVM to 1.7). Parameter processing in the servlet:


On the client side, JavaScript code contains a method to acquire Ajax XmlHttpRequest object. Through this object we can invoke servlet, directly from JavaScript:


In the monitor function (invoked automatically on start and end events for the request) - we are invoking servlet and passing request performance data to log. I'm executing synchronous call, this is done on purpose - asynchronous calls in JavaScript can be lost, if user executes requests fast, portion of the data will be skipped. Synchronous call is made at the end of the request and usually is pretty fast (make sure to log data in the separate servlet thread, not to block execution):


This is how it works. Press Save button - you will see information about request processing time embedded in the top of the page (this is calculated and updated in JavaScript function from above):


Servlet on the server side prints received data to be logged - button ID, request processing time, user info:


Try to invoke another request - navigate back to the previous fragment. Time will be logged and displayed in the top part of the page, same is communicated to the servlet for logging:


Time is being logged on the server side:


I hope described idea will be useful for your own project, where you could measure ADF UI client performance (from button click, until action is done). Ajax tag to catch request start and stop events works only in ADF 12c, but you could do similar thing in ADF 11g with custom JavaScript listeners.

Thursday, June 4, 2015

How to Apply New Label Text in MDS Customisation

It may look simple, but really is not obvious how to apply new label text for the ADF BC attribute or UI component through MDS customisation. It is simple, if such label text already exists in the core bundle. If you need to create new label text in the customisation and use it - this becomes a bit tricky. Well, as usual - I'm going to explain how you could solve such task. You should read more about MDS customisation setup in ADF - MDS Seeded Customization Approach with Empty External Project.

Core application - mds_label_cust.zip, contains one label for First Name VO attribute:


The requirement is to customise core application and add label for the Last Name VO attribute, without changing anything in the core. For this purpose, we need to create different JDEV application - extension, configured with shared library deployment profile. Here you could simply create new properties file. We are going to use this application to deliver additional components for the core. Keep in mind - core application must be configured to use this library. Add label for Last Name VO attribute, in the properties file located in the extension:


Time for the main trick. We could use label directly from any resource bundle in the ADF application. This is accomplished through such expression - reference for the resource bundle and label key:


This code should be part of customisation project, on runtime it will find referenced resource bundle and label key in the resource bundle from extension (see above).

This is how it looks on runtime - label text is taken from resource bundle in extension and applied by customisation:


It sounds more tricky, than it is - just try it.

Friday, May 29, 2015

Load More Scroll Policy for ADF 12c Table and Range Paging

There is a new scroll policy for the table component in ADF 12c. This new policy is called - load more. I think it gives good potential, it allows to reduce access load on heavy tables. In ADF 11g we are implementing similar approach with RowCountThreshold = -1 setting, this is preventing full scroll at once (How To Disable SELECT COUNT Execution for ADF Table Rendering). Load more is better, it integrates with VO Range Paging and allows to configure maximum number of rows present on the client.

New scroll policy is configurable directly on the ADF UI table component, as a property:


Load more works based on configured Range Size for the iterator in the bindings. In my example, I have set it to be 15, this means there will batches of new rows added in the groups of 15 elements:


One of the key things - new scroll policy works with VO Range Paging, this allows to fetch less rows from DB and improve ADF BC runtime performance:


There is no need to set Range Size, it will be calculated automatically, based on the current set of rows rendered in the table on runtime.

This is how it looks like on UI. User scrolls in the range and is given option to Show More rows. Total number of rows is also visible:


What is good about Load more scroll policy, it doesn't keep all fetched rows. If user want to come back to the first set of rows, he will be given Show More rows option in the top of range - to display previous set of rows:


Below you can see SQL query executed to fetch rows in the current range. This query is based on Range Paging feature and contains range variables:


If I would navigate back in the range and display previous 15 rows:


New SQL query is executed with Range Paging, with different range variables:


What is good about it - SQL query range paging variables are calculated automatically, there is no need to implement any custom logic to keep them in synch.

One extra feature to be described - blockNavigationOnError (also available in ADF 11g). This could be useful feature, if you want to prevent selecting rows in the table, when there is validation error in the current row:


Row selection is blocked, until validation error will be fixed:


Download sample application - ADFTableLoadApp.zip.

Thursday, May 28, 2015

Responsive UI Support in ADF 12.1.3

Responsive UI is a big deal nowadays, when enterprise applications should run on different platforms and devices. Often customers prefer to render simpler functionality screens for mobile devices and give full data entry access only when accessing through regular Web browser on the computer. ADF provides support for this, you can implement responsive UI designs relatively easy, check informative blog post from Shay Shmeltzer - ADF Faces Responsive Design - 12.1.3 Update.

I would suggest to think about responsive UI design from the start, it very much depends on functionality your application offers. It is good idea to start from the template and define facets for various layouts. But this is not only about layouts, you may prefer to render editable forms on large screens and on mobile devices to show only charts for quick overview. I'm going to demonstrate, how you could switch between different regions in ADF UI, depending on current resolution. Download sample application here - ADFResponsiveUIApp.zip.

This is how it works, I'm using iPad simulator, but same would be true for the regular browser display on smaller screen resolutions. Web page displays region with editable columns in horizontal view and same page displays different region with read-only list in vertical view:


Similar to Shay's sample, there is a template implemented with two facets (each for different layout):


Facet visibility is managed through assigned style class, controlled by CSS media query. It checks if screen width is less than 950px and sets narrow layout to be displayed:


Main page is created based on the template. Here I'm inserting both regions into corresponding facets - wide and narrow:


This is editable table in wide view:


This is read-only list in narrow view: