Override inputListOfValues component model and Continuous Query Notification sample in ADF

Requirement:

Standard ADF inputListOfValues component should behave like this:
    • When pressed "Search", action should stop and wait untill any change happen in DB table being searched
    • When change happen in DB table, search should resume among updated data. If no change happen it should resume after 10 seconds timeout
    • In addition - search input field validation should happen on "Search" press. If there is no at least one field filled with at least 3 symbols - error should be shown.
Well, this requirement may look sensless, but this is just a PoC of functionality, of what and how is possible to implement. Maybe a peace or a whole of this sample can be adapted to your case.

Solution:
  • Create a separate class which extends ListOfValuesModel, put custom logic there for validation and processing query
  • Use Continuous Query Notification (CQN) or in earlier Java releases called Database Change Notification (DCN) for delivering event from DB to application
  • Use Java latches (CountDownLatc) for suspending and resuming search after either an event from DB or timeout occurs.
This PoC will use Oracle DB and HR schema for sample data. Will put LOV on departmentId attribute of EMPLOYEES table. Will suspend searching in DEPARTMENTS table untill any change there happens.
  • Lets start from creating custom class for inputListOfValues model:


  • Configure LOV for departmentId in EmployeesView. Set UI hint for list type "Input Text With List of Values". Create main.jspx file and drag'n'drop EmpoyeesView data control into it, render as regular ADF table. Check whether inputListOfValues component is rendered for departmentId attribute:

  • Create a managed bean mainBean.java for main.jspx and put there getter of inputListOfValues model. Reassign model in main.jspx.
  • Get back to custom model class ListOfValuesModelEx. Put necessary validation and change subscribtion logic into method performQuery. Special attention to CountDownLatch utility here - it is used to suspend query execution and wait either till it is notified from the CQN listener or timeout occurs. The key points are emphasized in red:
For more detailed sample description of Continuous Query Notification (CQN/DCN) usage, please have a glimpse to my previous post: WebSocket together with DB Change Notification in ADF for immediate data refresh in browser (complete sample).

Thats it,  please download sample application to find more details and test it!

JDeveloper version 12.1.0.0

WebSocket together with DB Change Notification in ADF for immediate data refresh in browser (complete sample).

Requirement
  • We have DB table contents displayed in ADF GUI
  • After changes in that DB table (by anyone else in the background) we want to immediately display in our currenlty open browser session
Solution

To achieve our goal we need somehow to know when changes in DB happen. Once we know when, need to notify browser session in order it could be refreshed. This time we'll exploit two Java offerings:
  • JDBC Database Change Notifications (DCN) - to subscribe and receive notifications when changes happen in DB
  • WebSocket - protocol other that HTTP which works in request/response manner. Basically its full-duplex communication channel over a single TCP connection. That means we can have bidirectional continuous communication between server application and browser.
Lets do simple PoC with EMPLOYEES table from HR schema. Just display its contents and immediately refresh if changes happen in this table.
Make sure you have access to any Oracle DB (recommended >= 11.1 - more DCN features available) HR schema.
  • Create basic ADF Fusion Web Application. Create bussiness component for EMPLOYEES table and generate simple .jspx file with its contents displayed on the screen (ADF table component is fine):

  • That was the very basic so far. Now will create WebSocket project which will serve as listener for DB changes and the one which send notifications to browser. In the same recently created application, create new project of type "WebSocket":

    • Create java class which will implement WebSocket service. Annotate it as a server endpoint:

    • Click on code assistant icon and select "Configure Project for Web Socket":

Recent action has been generated web content folder with necessary belongings. 
    • Implement main service methods. Lets choose annotation driven implementation and add following methods with according annotations:
Note that method processMessageFromClient will not be used by fact in this sample, because it is not necessary to fullfill our requirement. But we just add a stub of it to be able to utilize it later if necessary. We have full WebSocket service structure defined already. It can be deployed although will not process anything benefiting our needs.
  • Now lets move to ViewController project and do necessary steps to be able to  establish and close connection between browser session and WebSocket service. Also implement refreshing of data in the browser.
    • As there are no dedicated ADF components for connection establishing and maintaining it, will leverage basic javascript to implement that. Add WebSocket.js file to ViewController project:

Notice WebSocket service URL marked with green rectangle. You need to check if its the same in your enviroment. Target URL is displayed right after running service in integrated server:

    • Create two buttons in the GUI which do connection and disconnection accordingly. Either of them will be client listener based and call javascript functions. Add javascript resources to page:


    • Add another button id="b1" (visible in screenshot above) to refresh table content when event from WebSocket service is received. You can make it either visible or invisible. It doesn't matter, because its action is queued using javascript means (function refreshJs() ) anyway. Add server listener which invokes bean method to refresh EmployeesView by re-executing its iterator:


At this moment were done with basic WebSocket connectivity implementation. We can run either ViewController and WebSocket project and try to enable and disable WebSocket connection. Check how it works:

  • Lets move back to WebSocket project implementation. There we still need logic which takes care of data change notifications from database.
    • Ensure that DB user HR has change notification privilege: 
grant change notification to hr;
    • Add DB notification subscription controller and listener classes. Add WebLogic remote client library to project:


    • Configure data source for HR connection in WebLogic and use it in DBChangeNotification.java for accessing DB:


    • Configure DB Change registration in DBChangeNotification.java class. Two main things worth to pay attention to: 
      • There are set two registration properties: DCN_NOTIFY_ROWIDS (tells that we are interested in changed rowids and want to get them in the payload) and DCN_QUERY_CHANGE_NOTIFICATION (tells that our registration is of higher granularity and is select statement based rather than DB object based).
      • In this sample statement "select salary from employees where employee_id=100" is used,  by which we ask DB to notify only when salary of employee whose employee_id="100" changes. DCN_QUERY_CHANGE_NOTIFICATION property is needed if we want filtering against some criteria and focus on certain columns take effect. If this property would be missing - even with such quite fine granularity query DB would notify about any change in EMPLOYEES table. 

    • Add Service.SendMessageToClient call in DB change listener (DBChangeNotificationListener.java):


  • Add javascript logic inside onMessage function to queue refresh action to ADF application from browser:

  • We're done, now can test the behavior:
    • Run application and WebSocket service
    • Enable WebSocket connection by clicking button in the GUI
    • Change salary of employee_id="100" using SQLDeveloper or other SQL execution means. 
    • Change should be immediately visible in the browser. 
In the Integrated server and browser logs can see notification cycle logged:

 

Note: for cleaning DB registrations can use app described in my other post How to select all JDBC Database Change Notification Registrations and clean them?

Demo application can be downloaded here



JDeveloper version 12.1.3.0.0

How to select all JDBC Database Change Notification Registrations and clean them?

Question:
How do I select all database change notifications registered via JDBC driver by my DB user?

Answer:
select * from user_change_notification_regs


Question:
How do I clean all of my DB change notifications?

Answer:
Database change notifications registered via JDBC driver can be deregistered only the same way - using JDBC driver. Therefore you need to execute this code:

This code can be downloaded here.

Comment:
More info about JDBC database change notifications can find in Database JDBC Developer's Guide

How to add ADF source code in JDeveloper 12c ?

Problem

I want to have ADF source code available in my project.

Solution
  • Open service request ticket at My Oracle Support and ask to provide you a source code for ADF. Oracle staff will provide you a security code and a link to download a zip file.
  •  Open JDeveloper, select Tools -> Manage Libraries... 
    • Click Libraries tab
    • Select folder User
    • Click New
    • Select Source Path on the right pane then click Add Entry... 
    • Point to zip file received from Oracle

  • Add defined library to particular project
    • Right click on project folder and select Properties
    • Select Libraries and Classpath on the left pane
    • Click Add Library on the right pane
    • Point to previously defined ADF source code library which should be available in User folder
  • You should be able to access ADF source classes now!
JDeveloper version 12.1.3.0.0




I get JBO-25200: Application module is not connected to a database exception. What can be the reason?

Problem

Time to time "JBO-25200: Application module is not connected to a database" exception is raised while browsing ADF application

Solution

Tune ADF application module by disabling "Support Dynamic JDBC Credentials".


However this solution may not work in your case, depends on the root cause.

Comment

If I understand this option correctly, it is needed only when application users must access DB using their personal credentials, but not one used for app in general. From my experience the latter approach is used usually (single DB user is created for app to access data). Thus this option is not necessary to be selected, especially when it involves additional lifecycles. And they make us problems like described above :)

Documantation about this application module option tell us:
Enables additional pooling lifecycle events to allow developer-written code to change the database credentials (username/password) each time a new user session begins to use the application module. This feature is enabled by default (true), however this setting is a necessary but not sufficient condition to implement the feature. The complete implementation requires additional developer-written code.

ADF version 12.1.3.0.0

How to iterate through all view object rows irrespective of specified range size and without impact to current rowset?

Problem

Imagine we have iterator binding EmployeesViewIterator with specified range size 25. But we want to iterate through ALL employees available, not just 25 of current range.

Solution

Create new row set iterator from EmployeesView view object. It will contain ALL rows irrespective of specified range size. Iterate it !

DCIteratorBinding it = (DCIteratorBinding)BindingContext.getCurrent().getCurrentBindingsEntry().get("EmployeesViewIterator");

RowSetIterator rsi = it.getViewObject().createRowSetIterator(null);
   while (rsi.hasNext()) {
     Row row = rsi.next());

     //...
   }
rsi.closeRowSetIterator();

ADF ViewObject query selects values into wrong attributes?

Problem
   In the view object result set value of particular attribute has wrong value. It belongs to another attribute of the same view object, usually to previous one in the sequence.

Solution
   Each view object attribute has property "Selected in query". It must be selected if attribute is fetched using SQL query. If it is not selected and is available in query, value is fetched into next attribute (wrong one) which has property "Selected in query" as true;


Ubuntu vpn connects successfully and shortly thereafter fails - network traffic stops - either VPN and local network

I've started to use Ubuntu for my job needs and experienced first pretty annoying challenge with VPN connection.
I'm using openvpn client with network manager. After successfull connect to VPN server I can use local and remote networks with no problem. After a while - like 1 -10 minutes , sometimes a bit longer up to couple hours or sometimes immediately - all network interfaces stop functioning - either no VPN and no local network.
   I 've googled a lot and found a confirmed network-manager package bug with very similar behaviour described - Bug #991666 . But the bug is unresolved so far.
   Nevertheless I was trying to find the reason and workaround for this issue. And found a problem in routing table.

  • My routing table before connection to VPN (local network works OK):

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG    0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     1      0        0 eth0
  •    My routing table after connection to VPN (all network traffic stops working after a short time):
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.1   0.0.0.0         UG    0      0        0 eth0
10.242.2.1      10.242.2.21     255.255.255.255 UGH   0      0        0 tun0
10.242.2.21     0.0.0.0         255.255.255.255 UH    0      0        0 tun0
78.47.224.80    10.242.2.21     255.255.255.248 UG    0      0        0 tun0
80.249.167.64   10.242.2.21     255.255.255.192 UG    0      0        0 tun0
82.195.75.160   10.242.2.21     255.255.255.224 UG    0      0        0 tun0
82.195.78.142   192.168.100.1   255.255.255.255 UGH   0      0        0 eth0
172.16.10.0     10.242.2.21     255.255.254.0   UG    0      0        0 tun0
192.168.1.0     10.242.2.21     255.255.255.0   UG    0      0        0 tun0
192.168.100.0   10.242.2.21     255.255.255.0   UG    0      0        0 tun0

192.168.100.0   0.0.0.0         255.255.255.0   U     1      0        0 eth0

10.242.2.21 - my VPN gateway
192.168.100.0 - my local network

As you see two strange static routes are pushed by server (marked in red). The green one (192.168.100.0) - my network points to default destination. One of the red ones (192.168.100.0) points to the VPN gateway. I'm really not a network guy and it is not my strength, but it looks for me suspicious. Probably some kind of collision happens when OS does not know where to forward packets when routing table shows two directions. As far as I know Metric should help to make this decision, but maybe it is not interpreted correctly, whatever... What I did - just asked network admin to remove those two extra static routes and thereafter everything started to function properly... Those routes were not needed and used for any puposes anyway - some legacy stuff...
If there is possibility that you experience similar reason, some test can be made by manually locally removing particular routing records, or by connecting some intermediate router.

So thats my story with happy-end  after long fustrating hours of investigation. Good luck!

Ubuntu 14.04

ADF how to stretch table vertically and horizontally?

How to stretch ADF table vertically to fill maximum available vertical space in browser?

Answer:
  • Put table into af:panelStretchLayout component center facet.
  • Put dimensionsFrom="parent" attribute into af:panelStretchLayout (parent of af:panelStretchLayout component must stretch its children)

How to stretch ADF table horizontally to fill maximum available horizontal space in browser?

Answer:
  • Put table into af:panelStretchLayout component center facet.
  • Add styleClass="AFStretchWidth" attribute to af:panelStretchLayout
 
Example:
 
<af:panelStretchLayout id="psl1"  styleClass="AFStretchWidth" dimensionsFrom="parent">
    <f:facet name="center">
        <af:table value="#{bindings.EmployeesView11.collectionModel}"
                      var="row" rows="#{bindings.EmployeesView11.rangeSize}"
                      emptyText="empty"
                      fetchSize="#{bindings.EmployeesView11.rangeSize}"
                      rowBandingInterval="0" id="t1">
              

<af:column sortProperty="#{bindings.EmployeesView11.hints.FirstName.name}"
                         sortable="false"
                         headerText="#{bindings.EmployeesView11.hints.FirstName.label}"
                         id="c2">

.....
.....
.....
 </table>
</f:facet>
</af:panelStretchLayout>

Sample can be downloaded here
If stretching issues in ADF 12.2.1 this post might help: ADF application layout messed up after migration to 12.2.1 ... What might be the reason ?

Version 12.1.3.0

ADF java.lang.ClassCastException: ...ViewRowImpl cannot be cast to ...ViewRow ?

For example:
java.lang.ClassCastException: model.DepartmentsViewRowImpl cannot be cast to model.common.DepartmentsViewRow

JDeveloper, when generating View Object Row client interface sometimes goes wrong with class definition. Such error can be displayed when implementation of class is not defined. In particular error sample -  "implements DepartmentsViewRow" is missing in DepartmentsViewRowImpl class:

public class DepartmentsViewRowImpl extends ViewRowImpl implements DepartmentsViewRow {
...
}