Please disable your adblock and script blockers to view this page

Search this blog

Showing posts with label 11g. Show all posts
Showing posts with label 11g. Show all posts

Saturday 8 April 2017

Uploading and downloading files from database (BLOB) in Oracle ADF (12.1.3)

Hello all

This post is about a very simple requirement -file handling (uploading and downloading various types of file) in ADF and it is needed very often to store file in absolute server path (actual path) and download from there and I have posted about that previously

Uploading and downloading files from absolute server path

Now this post is about uploading and saving file in database BLOB column and downloading from there
See step by step implementation -

Tuesday 3 February 2015

ADF Basics: Set multiple LOV's on attribute and conditionally switch using LOV Switcher

This post is about a very basic and common use case
Suppose we have to show different values in our List depending on some condition but all values must be stored in same attribute so for this type of requirement ADF BC framework provides concept of LOV Switcher
Framework allows us to define multiple LOV on same attribute, I hope you all know about defining LOV(List of Values) so move ahead and see how to use lov switcher

 See the implementation part-
  • Created a Fusion Web Application and a viewObject to show LOV on viewport (Used dual to create view object for this example , you can use use your own)





  • Created 2 more viewObject to apply LOV on first viewObject's attribute, One ViewObject is for Departments and other one is for Employees


  • Open dual viewObject select LovAppl attribute and goto ListOfValues tab and add both LOV
    For Department - DepartmentId is List Attribute and DepartmentName will be shown on UI


  • For Employees- EmployeeId is List Attribute and FirstName,LastName will be shown on UI



  • Now click on green plus icon of List Of Values Switcher and add a transient attribute , this will be further used to switch lov on base of some condition


  • So created LovSwitcher attribute , and remember this switcher attribute value should be one of the LOV Name that are applied on attribute.
    Here i am using a condition - if LovType attribute of Dual viewObject is 'D' the LovAppl should show Departments Lov and if it is 'E' then LovAppl should show Employees Lov
    For this i have written expression for lov switcher attribute
    LovType=='D' ? 'LOV_LovAppl' : LovType=='E' ? 'LOV_LovAppl1' : null


  • Now run Application Module and check it


Thanks , Happy Learning :)

Monday 5 January 2015

ADF Basics: Delete child records on delete of parent record, Overriding remove() in EntityObject class

This post is about one basic question of Master-Detail relation between business components
How to delete all child records on delete of parent record ?
So answer is quite simple , see the steps how to achieve this?

  • Create a Fusion Web Application and prepare model project using Departments and Employees table of HRSchema.
    you can see multiple associations and viewLinks are created automatically due to foreign key relation in database


  • Here Departments is parent table and Employees is child, so there is an association between both entity objects , open this association and goto Association Properties . Now you can see source and destination accessor name that are created in both entity objects




  • Next step is to create EntityObject java class. To do this open Departments entity object -- go to java section-- click on edit icon and check the box to create class and required methods
    See Accessors and Remove Method will be created in this class


  • Open DepartmentsEOImpl class and check there is a method that returns RowIterator of Employees (this is Accessor)

  •     /**
         * @return the associated entity oracle.jbo.RowIterator.
         */
        public RowIterator getEmployeesEO1() {
            return (RowIterator)getAttributeInternal(EMPLOYEESEO1);
        }
    

  • Now locate remove method in EOImpl, this method is called every time when delete operation for Departments is executed so add this code to remove(); method

  •     /**
         * Add entity remove logic in this method.
         */
        public void remove() {
            //Get all Employees of currenlty selected Department
            RowIterator employees = getEmployeesEO1();
            while (employees.hasNext()) {
                //Delete all Employees
                employees.next().remove();
            }
            //Delete Department itself after deleting all Employees associated with it
            super.remove();
        }
    


This is how we can make use EntityObject class and Association accessors, in the same way other operation can be performed as updating all child rows, sum of a column of child records etc
Thnaks , Happy Learning :)

Friday 14 November 2014

ADF Faces dvt:thematicMap to mark location using latitude and longitude

Hello all,
this post is about simple use of dvt:thematicMap component , this map is used for displaying some information of a particular geographic location such as population ,any trends or patterns
Map is called thematic because it doesn't include geographic details of location as rivers, ocean etc.
If you want to use geographic features then use <dvt:map>

Thematic map includes different basemap as world map and all continents map
for details see oracle docs - <dvt:thematicmap>
In this post i am just spotting locations using their latitude and longitude co-ordinates

  • So first step is create a fusion web application and drop a thematic map (world map) on page



  • then i have created a bean class to populate data in thematic map , this bean class contains properties (varaibles) for thematic map like Country Name,latitude and longitude



  • public class LocationDetail {
        private String location; // Name of Location
        private String countryNm; // Name of Country
        private String textDisp; // Additional Information to display
        private float lattitude; // Latitude of location
        private float longitude; // Longitude of Location
    
        public LocationDetail() {
            super();
        }
    
        public void setLocation(String location) {
            this.location = location;
        }
    
        public String getLocation() {
            return location;
        }
    
        public void setCountryNm(String countryNm) {
            this.countryNm = countryNm;
        }
    
        public String getCountryNm() {
            return countryNm;
        }
    
        public void setTextDisp(String textDisp) {
            this.textDisp = textDisp;
        }
    
        public String getTextDisp() {
            return textDisp;
        }
    
        public void setLattitude(float lattitude) {
            this.lattitude = lattitude;
        }
    
        public float getLattitude() {
            return lattitude;
        }
    
        public void setLongitude(float longitude) {
            this.longitude = longitude;
        }
    
        public float getLongitude() {
            return longitude;
        }
    }
    

  • created a managed bean and a List data structure to add location detail and added this List reference to thematic map component

  • <dvt:thematicMap basemap="world" id="tm1" summary="World Map" styleClass="AFStretchWidth"
                                         partialTriggers="::b1" inlineStyle="background-color:#e9ffdc;">
                            <dvt:areaLayer layer="continents" id="al2">
                                <dvt:pointDataLayer id="dl1" value="#{viewScope.MapBean.mapDetail}" var="row">
                                    <dvt:pointLocation id="pl1" type="pointXY" pointY="#{row.lattitude}"
                                                       pointX="#{row.longitude}">
                                        <dvt:marker id="m1" shortDesc="#{row.textDisp}"
                                                    fillColor="#ff0000" borderWidth="1.0" scaleX="2.0" scaleY="2.0"
                                                    labelDisplay="on" labelPosition="bottom" shape="triangleDown"
                                                    value="#{row.location}" labelStyle="color:maroon;font-size:10px;"/>
                                    </dvt:pointLocation>
                                </dvt:pointDataLayer>
                            </dvt:areaLayer>
                        </dvt:thematicMap>
    

  • then i have added a form on page to add new location by user, this form has 5 fields (Country Name, Location, Latitude, Longitude and Description) and a button to add this information to list

  • <af:panelBox text="Add New Location" id="pb1" showDisclosure="false">
                            <f:facet name="toolbar"/>
                            <af:panelFormLayout id="pfl1" rows="1" maxColumns="2">
                                <f:facet name="footer">
                                    <af:button text="Add Location" id="b1"
                                               actionListener="#{viewScope.MapBean.addLocationButton}"/>
                                </f:facet>
                                <af:inputText label="Country" id="it3"
                                              contentStyle="width:100px;font-weight:bold;color:navy;"
                                              binding="#{viewScope.MapBean.cntryNmBind}"/>
                                <af:inputText label="Location" id="it4"
                                              contentStyle="width:100px;font-weight:bold;color:navy;"
                                              binding="#{viewScope.MapBean.locationBind}"/>
                                <af:inputText label="Latitude" id="it1" contentStyle="width:100px;color:red;"
                                              binding="#{viewScope.MapBean.latitudeBind}"/>
                                <af:inputText label="Longitude" id="it2" contentStyle="width:100px;color:red;"
                                              binding="#{viewScope.MapBean.longitudeBind}"/>
                                <af:inputText label="Description" id="it5" contentStyle='width:200px;color:darkgreen;'
                                              binding="#{viewScope.MapBean.descriptionBind}"/>
                            </af:panelFormLayout>
                        </af:panelBox>
    


  • now see the managed bean code to add this information to list and to populate default locations

  • public class MapBean {
        //List to contain Location Detail
        private List<LocationDetail> mapDetail = new ArrayList<LocationDetail>();
        // Bindings of page component to access value
        private RichInputText cntryNmBind;
        private RichInputText latitudeBind;
        private RichInputText longitudeBind;
        private RichInputText locationBind;
        private RichInputText descriptionBind;
    
        public MapBean() {
            // Add Default location to map
            LocationDetail location = new LocationDetail();
            location.setCountryNm("India");
            location.setLocation("Mumbai");
            location.setTextDisp("Economic Capital of India");
            location.setLongitude((float) 72.8258);
            location.setLattitude((float) 18.9750);
            mapDetail.add(location);
    
            location = new LocationDetail();
            location.setCountryNm("India");
            location.setLocation("Kanpur");
            location.setTextDisp("Industrial City in North India");
    
            location.setLongitude((float) 80.20);
            location.setLattitude((float) 26.28);
            mapDetail.add(location);
    
            System.out.println("List is-" + mapDetail);
        }
    
        public void setMapDetail(List mapDetail) {
            this.mapDetail = mapDetail;
        }
    
        public List getMapDetail() {
            return mapDetail;
        }
    
    
        /**Method to add new Location
         * @param actionEvent
         */
        public void addLocationButton(ActionEvent actionEvent) {
            if (cntryNmBind.getValue() != null && latitudeBind.getValue() != null && longitudeBind.getValue() != null &&
                locationBind.getValue() != null && descriptionBind.getValue() != null) {
    
                LocationDetail location = new LocationDetail();
                location = new LocationDetail();
                location.setCountryNm(cntryNmBind.getValue().toString());
                location.setLocation(locationBind.getValue().toString());
                location.setTextDisp(descriptionBind.getValue().toString());
    
                location.setLongitude(Float.parseFloat((String) longitudeBind.getValue()));
                location.setLattitude(Float.parseFloat((String) latitudeBind.getValue()));
                mapDetail.add(location);
            }
        }
    
        public void setCntryNmBind(RichInputText cntryNmBind) {
            this.cntryNmBind = cntryNmBind;
        }
    
        public RichInputText getCntryNmBind() {
            return cntryNmBind;
        }
    
        public void setLatitudeBind(RichInputText latitudeBind) {
            this.latitudeBind = latitudeBind;
        }
    
        public RichInputText getLatitudeBind() {
            return latitudeBind;
        }
    
        public void setLongitudeBind(RichInputText longitudeBind) {
            this.longitudeBind = longitudeBind;
        }
    
        public RichInputText getLongitudeBind() {
            return longitudeBind;
        }
    
        public void setLocationBind(RichInputText locationBind) {
            this.locationBind = locationBind;
        }
    
        public RichInputText getLocationBind() {
            return locationBind;
        }
    
        public void setDescriptionBind(RichInputText descriptionBind) {
            this.descriptionBind = descriptionBind;
        }
    
        public RichInputText getDescriptionBind() {
            return descriptionBind;
        }
    

  • you can see in thematicMap map source - how bean variables are used to point latitude, longitude etc
  • Run this application, you will see default location are marked at first time



  • now add any other location using 'Add New Location' form 


  • See this video how locations are added to thematic map using their latitude and longitude

and finally after adding all location , map looks like this

 Sample ADF Application
Thanks , Happy Learning :)

Monday 22 September 2014

Invoke button action (ActionEvent) and value change listener using JavaScript- Oracle ADF

This is another post about using JavaScript in ADF Faces, So again nothing complicated just simple things but needed often
In this post i am covering two simple requirements , using Jdeveloper 11.1.2.4 (11g Release2)

1. How to call button action (ActionEvent) using JavaScript
2. How to call valueChangeListener of a component using JavaScript

 

Call button action using JavaScript-


So for this just drop a commandButton and an inputText on page and create a ActionListener in managed bean for button



Code in managed bean for ActionEvent-




    /**Action Listener for Button
     * @param actionEvent
     */
    public void buttonAction(ActionEvent actionEvent) {
        FacesMessage msg = new FacesMessage("Button Action called");
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, msg);
    }

Now requirement is to call this button action on double click event of mouse in inputText
To handle ActionEvent in JavaScript, framework provides a class AdfActionEvent , it has a method to queue ActionEvent from a component. So here i use same method to call ActionEvent

See JavaScript function-

function callButtonAction() {
                  //Method to get component using id (here button is top container)
                  var button = AdfPage.PAGE.findComponentByAbsoluteId('cb1');
                  //Method to queue ActionEvent from component
                  AdfActionEvent.queue(button, button.getPartialSubmit());
              }

and call it using af:clientListener under af:inputText-



Run page and check on double click of mouse in inputText-




Call ValueChangeListener using JavaScript-


This is also same as pervious one, created a valueChangeListener in managed bean for input text and requirement is to call this listener on mouse hover of button

Code in managed bean for ValueChangeListener-

    /**ValueChangeListener for inputText
     * @param valueChangeEvent
     */
    public void inputTextVCE(ValueChangeEvent valueChangeEvent) {
        FacesMessage msg = new FacesMessage("Value Change Lestener called");
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, msg);
    }

There is a class to handle valueChange event using JavaScript - AdfValueChangeEvent
So this class also has a queue method , the difference is this queue method takes 4 parameters and also requires a value change event on component
So first step is to change (set) value of field using JavaScript and then queue valueChangeEvent

See JavaScript function-


 function callValueChangeEvent(evt) {
                  //Method to get component using id (here inputText is top container)
                  var field = AdfPage.PAGE.findComponentByAbsoluteId('it1');
                  //Change(set) field's value
                  field.setValue('I am JavaScript text');
                  //Get New changed value
                  var newVal = field.getValue();
                  //Queue ValueChangeEvent (component,oldValue,newValue,autoSubmit)
                  AdfValueChangeEvent.queue(field, null, newVal, false);

              }

make sure that clientComponent and autoSubmit property of inputText set to true
call this javascript fucntion from button using af:clientListener


Run page and check it-
Thanks, Happy Learning


Sunday 7 September 2014

Show message (Invoke FacesMessage) using JavaScript in ADF Faces

Hello all
This post is about use of JavaScript in ADF Faces to show a simple message notification , it may be error/warning/information/critical error message
so this is simple, as we have to just invoke default FacesMessage using JavaScript

So for this i have used an af:inputText on page and use case is that this field should only take characters


How to validate characters (alphabet) only  using javascript ?





So for this i have taken a simple regular expression that check that entered value is alphabetic or not
see this JavaScript function that is added to page, here it1 is the id of inputText for that FacesMessage is invoked, i am using Jspx page so i use actual id of component, if you try this in region,dynamic region or inside pageTemplate then check and change the id of component .
It will be something like r1:0:it1 or pt1:0:it1, because that is nested page structure.
you can get this id using componentBinding.getClientId();


 <af:resource type="javascript">
              function validateStringOnKeyPress(event) {
                  //Regular Expression to validate String
                  var letters = /^[A-Za-z]+$/;
                  //Get value of input text
                  var charCode = event.getSource().getSubmittedValue();

                  if (charCode != '') {
                      if (charCode.match(letters)) {
                          // IF matches then no problem
                      }
                      else {
                          //Invoke FacesMessage
                          AdfPage.PAGE.addMessage('it1', new AdfFacesMessage(AdfFacesMessage.TYPE_ERROR, "Invalid Value", "Enter Characters Only"));
                          AdfPage.PAGE.showMessages('it1');
                          event.cancel();
                      }
                  }
              }
            </af:resource>


Added a clientListener to inputText that executes this JavaScript function on keyPress event





Run page and see how it works-
Here you see that 2 is not a character so it showing error message as FacesMessage is defined for TYPE_ERROR




So it's done but now problem is - when user input a wrong value a error message is displayed and after this validation alert if user keeps entering wrong values then every time a new FacesMessage is created and added to page, It appears on page like this (duplicate messages - really weird)


To remove additional messages , i have added one more line in JavaScript to clear previous validation message

JavaScript to clear validation message-


 // Clear all validation message 
              AdfPage.PAGE.clearAllMessages();

now JavaScript function is like this


function validateStringOnKeyPress(event) {
                  //Regular Expression to validate String
                  var letters = /^[A-Za-z]+$/;
                  //Get value of input text
                  var charCode = event.getSource().getSubmittedValue();
                  // Clear all validation message 
                  AdfPage.PAGE.clearAllMessages();
                  if (charCode != '') {
                      if (charCode.match(letters)) {
                          // IF matches then no problme
                      }
                      else {
                          //Invoke FacesMessage
                          AdfPage.PAGE.addMessage('it1', new AdfFacesMessage(AdfFacesMessage.TYPE_ERROR, "Invalid Value", "Enter Characters Only"));
                          AdfPage.PAGE.showMessages('it1');
                          event.cancel();
                      }
                  }
              }

and yes you can change type of message, use TYPE_ERROR, TYPE_INFO, TYPE_WARNING, TYPE_FATAL to change message type

see different output-
Warning Message (TYPE_WARNING)-

Informational Message (TYPE_INFO)-

Fatal Error Message (TYPE_FATAL)-


Thanks Happy Learning :)

Monday 25 August 2014

Using HashMap in EL expression to set component properties in Oracle ADF

Basic requirement while using EL on pages in ADF, we use bean variables, binding attributes, iterators in expression to check conditions , to set properties for components as Enable-Disable, Visible, inline style etc.
in the same way we can use collections (Array, HashMap) in expression, i know it is pretty simple but have seen many thread in OTN asking how to use HashMap in expression

So here i am taking a very simple example



I have 5 input text on page and i have to enable-disable some fields based on it's id value, there is two buttons on page


as you can see on click of first button , input field 1,3 and 5 should be disabled and on click of second button af:inputText 2 and 4 should be disabled
so for this purpose i have used a HashMap in managed bean


    private HashMap fieldVal = new HashMap();

    public void setFieldVal(HashMap fieldVal) {
        this.fieldVal = fieldVal;
    }

    public HashMap getFieldVal() {
        return fieldVal;
    }

values in HashMap are populated using id value of inputTexts on page as key, this id will be passed as parameter in HashMap in expression
see how expression used in disabled property of inputText-


in same way expression for all inputText is set


<af:panelFormLayout id="pfl1" partialTriggers="b1 b2">
                    <af:inputText label="Label 1" id="it1" disabled="#{EnableDisableBean.fieldVal['it1']}"/>
                    <af:inputText label="Label 2" id="it2"
                                  disabled="#{requestScope.EnableDisableBean.fieldVal['it2']}"/>
                    <af:inputText label="Label 3" id="it3"
                                  disabled="#{requestScope.EnableDisableBean.fieldVal['it3']}"/>
                    <af:inputText label="Label 4" id="it4"
                                  disabled="#{requestScope.EnableDisableBean.fieldVal['it4']}"/>
                    <af:inputText label="Label 5" id="it5" autoSubmit="true"
                                  disabled="#{requestScope.EnableDisableBean.fieldVal['it5']}"/>
                </af:panelFormLayout>

now see code on buttons, simply setting values against key


    /**Method to disable inputText (1,3,5) on basis of id value
     * @param actionEvent
     */
    public void disable135Action(ActionEvent actionEvent) {
        fieldVal.put("it1", true);
        fieldVal.put("it2", false);
        fieldVal.put("it3", true);
        fieldVal.put("it4", false);
        fieldVal.put("it5", true);

    }

    /**Method to disable inputText (2,4) on basis of id value
     * @param actionEvent
     */
    public void disable24Action(ActionEvent actionEvent) {
        fieldVal.put("it1", false);
        fieldVal.put("it2", true);
        fieldVal.put("it3", false);
        fieldVal.put("it4", true);
        fieldVal.put("it5", false);
    }

Run Application and see what is on page
On Click of First Button

On Click of Second Button

Thanks
Happy learning :)

Saturday 23 August 2014

Access BindingContainer (Page Bindings) of another page using DataBindings.cpx in Oracle ADF

Hello all
this post is about a requirement of getting page binding of another page that is not active currently
we use BindingContainer to access bindings of current page, region in managed bean

Oracle Docs says-
The BindingContainer contains the Control Bindings for a reusable unit of View technology. For example, each individual Page, Region, or Panel refers to a unique BindingContainer with a set of Control Bindings that refer to the Model elements used by that Page. The BindingContainer interface is implemented by the data binding framework provider. 

So to access operations, methods exposed in client, listBinding, IteratorBinding we need to get BindingContainer of current viewPort (a page or a page fragment)
this method is used to get BindingContainer -


import oracle.adf.model.BindingContext;
import oracle.binding.BindingContainer;

    /*****Generic Method to get BindingContainer of current page, fragment or region**/
    public BindingContainer getBindingsCont() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }

as previously mentioned that BindingContainer contains bindings of current page but sometimes we need to access BindingContainer of any other page in order to access it's operations , iterators



So how to do this ?

for this i have created a 2 page fragments inside a bounded taskFlow



firstPage is very simple , it has only one button and secodPage has Departments (HR Schema ) viewObject as form

First Page Second Page

then i added createInsert operation in secodPage binidng, so here is the pageDef of secondPage
as there is no bindings on firstPage so there is no pageDef file is generated for that



now what i want to do is to call createInsert operation of Departments viewObject from firstPage, but there is no binding of operation in firstPage so if i use
BindingContext.getCurrent().getCurrentBindingsEntry()
to get BindingContainer then it will throw NullPointerException on calling createInsert

Now i have to get BindingContainer of secondPage -
Go to DataBindings.cpx file and see usageId for second page



Copy page usageId from there


pass this usageId in this method to get BindingContainer of secondPage


    /**
     * @param data
     * @return
     */
    public Object resolvEl(String data) {
        FacesContext fc = FacesContext.getCurrentInstance();
        Application app = fc.getApplication();
        ExpressionFactory elFactory = app.getExpressionFactory();
        ELContext elContext = fc.getELContext();
        ValueExpression valueExp = elFactory.createValueExpression(elContext, data, Object.class);
        Object Message = valueExp.getValue(elContext);
        return Message;
    }
    
    /**Method to get BindingContainer of Another page ,pageUsageId is the usageId of page defined in DataBindings.cpx file
     * @param pageUsageId
     * @return
     */
    public BindingContainer getBindingsContOfOtherPage(String pageUsageId) {
        return (BindingContainer) resolvEl("#{data." + pageUsageId + "}");
    }

then call createInsert operation using this BindingContainer


 getBindingsContOfOtherPage("binidngs_view_secondPagePageDef").getOperationBinding("CreateInsert").execute();

Happy Learning Cheers :)