Thursday, August 4, 2016

Calculating Table Footer totals in ADF

Problem: To display total of numeric columns in ADF table footer . Sometimes requirement is to display total of a numeric columns , for ex. Total of the salaries of all employees in a search.

Solution: Their are several ways this can be achieved , one of the ways is described in this blog How To add Table Footer Totals. This blog mentions to write the iteration code inside the getter of the footer transient attribute in viewRowImpl class  , but if we have several attributes in table where we want to display the total in footer , above approach might be costly as iteration will be done per attribute. To avoid this we can use following approach.

1) Create a view object for your requirement and don't forget to generate Java classes .




2) Add a new transient attribute to your view object for storing "TotalSalary" . Create one new transient attribute for each field whose footer total needs to be displayed.


3) Define a variable for calculating the total in VOImpl class of the BigDecimal type. In case you have multiple attributes whose total needs to be displayed in footer , you need to declared variable for each attribute here. 


4) Override executeQuery() method of ViewObjectImpl . Call super.executeQuery() , and then
    call a method to calculate the totals and set it into the salaryTotal variable .  Now  we need to
    create a secondary row set iterator, iterate through it and calculate the total of the salary attribute,       don't forget to close the iterator :) . Here we can calculate total of multiple attributes in one go and       set them to the variables defined for them in VOImpl class.



5) Now go to viewRowImpl class and access the getter of variable defined in viewImpl class
from the getter of the footer total attribute. Please refer to below snapshot.


6) For UI, create a query panel with table for your view object ( do not create a column for transient attribute) .  Now inside the salary column , add footer facet with a binding of the transient attribute which was created for the footer total. You will need to add binding for the footer total  attribute to the page definition file.




7) Now run the application , and you should see the footer total for the salary column.
You can add same for multiple columns if your use case requires to do the same.





Please download the application from here . Cheers :) .



Wednesday, August 3, 2016

Cascade LOV based on Multiselect LOV inside view criteria

Problem: Creating a cascade LOV based on single select drop down in af:query component (based on view criteria) works fine but ADF does not have out of the box support to create a LOV based on multi-select LOV i.e. values of the dependent LOV are not filtered based on the list selected in the parent LOV and it is even more difficult to make it work in af:query component i.e. using view criteria.

Solution: Vanilla creation of cascade LOV requires to create a bind variable in the dependent LOV view object which will accept the attribute value (bound to master LOV) from the main view object to filter the list. Main view object here refers to the VO which will have view criteria and LOVs defined. Master attribute's autoSubmit property(in the main view object) should be set to true so that the dependent LOV is filtered each time the value is changed in parent LOV. If we try the same thing by marking master LOV as multiselect , this arrangement won't work because the viewCriteriaItem for the master attribute will always return first value from the list i.e. value returned by expression

viewCriteriaItem.getValues().get(0).getValue().

but what we want is a comma separated string of the list of values selected in parent LOV which can then be fed to the query of the child LOV view object in the “IN clause”. This should fix our problem.

In our use case here we want the employees LOV to be filtered based on the multi-select Department LOV. For each department selected , employee drop down should be refreshed with employees in that department and we want this to happen inside af:query component created using view criteria.

Here is a view object for the departments LOV. 

Employees LOV view object defined with a bind variable which will get the list of departments 
selected in department LOV. This bind variable needs to be marked as required  and will be supplied to in_list_char  function which takes comma separated string and returns a list which can be supplited to "IN" clause in the query. in_list_char function has been taken from one of Jobinesh's blog . 


Now we will create a view object for Job History which will be used to view the job history and
will have lov's for departments and employees.


Define a LOV on DepartmentID using the DepartmentsLOV.


Set the autoSubmit property of DepartmentID to TRUE


Create a transient attribute in the view object for DeptIdList and set its autosumbit property to true .


Now define a LOV for EmployeeId using EmployeesLOV

In view object accessor for EmployeesLov , pass the DeptIdList for the bind variable vDeptId.


Create a view criteria in JobHistory view object.


Now from UI , drag & drop named criteria from data controls to create Query Panel with Table. Override the queryOperationListener in af:query component and bind it to a backing bean method.
Now inside backing bean method we need to check when ever the values for deparmtent id LOV is changed , we need to get all the departmentId values that were selected/de-selected by the user and set them into the transient attribute (DeptIdList) as a comma separated string. To get currently selected values in DepartmentsLOV we need to get the view criteria row and iterate through viewCriteria.getValues() which returns an arraylist of ViewCriteriaItemValue


ViewCriteria selectedVc = vo.getViewCriteriaManager().getViewCriteria("JobHistoryVOCriteria");
ViewCriteriaRow vcRow = (ViewCriteriaRow)selectedVc.getRows().get(0);
StringBuilder sb = new StringBuilder();
if ("DepartmentId".equals(attrName)) {
 ViewCriteriaItem vcItem = vcRow.getCriteriaItem("DepartmentId");
 ArrayList itemValList = vcItem.getValues();
   for (ViewCriteriaItemValue itemValue : itemValList) {
         if (!sb.toString().isEmpty()) {
                 sb.append(",");
         }
System.err.println("Deartment id --> " + itemValue.getValue());
                    sb.append(itemValue.getValue());
                }
    }
System.err.println("DeptIdList --> " + sb.toString());
ViewCriteriaItem jobItem = vcRow.ensureCriteriaItem("DeptIdList");
jobItem.setOperator("=");
jobItem.getValues().get(0).setValue(sb.toString());


Please download the attached application to try out for yourself . Cheers :) .Click here to download application


Monday, July 2, 2012

Printing a commandLink 'text' present in ADF Table

Hi Friends , sometimes we have a use case where we need a command link in the ADF table column. This scenario is required in cases where the column containing the command link represents the identifying key for the table and we want the user to click on that link and perform some action like going to details page for that record or opening the details in a pop up. This is a simple use case and easy to implement.  So our jsff will look something like this.











Problem:  A problem arises when we want to use print functionality on this table.
Here if we implement default print functionality provided by ADF i.e adding af:showPrintablePageBehavior element inside a command button, it omits the the command link and we get a blank field on the print page when user tries to print the contents of this page. But we wanted to display the 'text' value of commandLink.  This happens because by default ADF print functionality has been designed to omit the commandLinks and buttons present on an ADF page and provide the user with a better printable format of the page in consideration.        
   

Solution: Now to resolve this problem user can add an output text inside the same column of the ADF table(which contains a commandLink) and to the rendered property of the output text add the following expression.
 rendered="#{adfFacesContext.outputMode eq 'printable'}";

Your table jsff code should look like the following.






  


Ta-Da...so here it is , simple and easy solution. Now when user clicks the print button, he gets this output text which is rendered only if outputMode of the current adfFacesContext is 'printable'.
Thanks. Hope it works for you . Cheers.

Serialization (Persistence) in Java

           Hi Friends, everyone who is acquainted with JAVA even distantly knows that Java platform allows us to create objects which can be reused in memory, but these objects can be reused as long as your java application or JVM is running i.e. alive. Once the execution of the program finishes or JVM ends its execution the objects also perish to exist. Think of a scenario where you need to save(persist) the current state of the instantiated object(with all its variables and attributes assigned some value) and reuse it at a later stage even beyond the lifetime of JVM. This is what all this article talks about. This can be done with the powerful  Serialization API provided by Java itself. We can flatten the objects using serialization and then re-expand them at a later stage.

           Using object serialization an object's state is saved into form of bytes on the physical memory like hard disk and it can be inflated into a live object  at a later stage from those bytes. The emphasis in this article will be on understanding the classes and methods provided by the Java serialization API. Persisting objects is one of the tougher challenges which can easily be met by making use of serialization . Major problem is solved by understanding the Serialization API clearly which is rather misunderstood and misinterpreted while using in different scenarios.

Lets start with the most basic and simple case.


Persisting An Object
               
            To persist or serialize a java object, the class of that object must implement the marker interface java.io.Serializable , which indicates the underlying API that this object can be serialized to the disk in form of bytes and reused at a later point of time.




SerializableClass
               As you have seen above , making a class as serializable is pretty simple. You just need to extend the Serializable interface. Doing this allows the JVM to identify this class as serializable.
All subtypes of a serializable class are themselves serializable.

                   Now we have made a class serializable but it needs to be persisted. It can be done by using      java.io.ObjectOuputStream class. 

ObjectOutputStream 
                    An ObjectOutputStream class writes primitive data types and graphs of Java objects to an OutputStream. The objects can be read (reconstituted) using an ObjectInputStream. If the stream is a network socket stream, we could easily transfer a flattened object across a network wire and have it be rebuilt on the other side. The method writeObject() is used to write an object to the stream.

FlattenedObject



    


                                                      
            The real work of serializing or persisting the object is done in the highlighted line. The serialized file i.e. "serialize.object" will be saved in the project folder of your java app if the path is not mentioned for the file.




Inflating the serialized Object


InflatedObject


                 The real work of reconstructing the serialized object into live instance is done by the highlighted line. The serialized object i.e. "serialize.object" is taken up and type casted to the original object type. Method readObject() can read the raw bytes which were previously saved during the serialization of the object. The class file for the raw object being deserialized must be available to the JVM for the restoration of the object , because during serialization only object's state is saved  to the file and not the class file and its methods.