Follow by Email

Wednesday, 24 December 2014

Update page component in between of event processing in ADF Faces using JavaScript

This post is not about any specific topic of framework, recently i was working in an application, requirement was like this
There is a button on page that uploads a large file to server and it takes some time . So as soon as user press this button it's text should be changed to 'Processing..' and after upload is complete it should be 'Done'




In this post i am sharing same - How to update page component while an event is processing ?
First i have tried it using java means in same button action listener but in this case button text was changed only after event processing is complete
So for this purpose i have used some javascript function, this is quite simple (see the implementation)

  • Drop a button on page and create a ActionListener , it will change button text to 'Done' after event processing (used Thread.sleep() for some long processing)

  •     private RichButton buttonBind;
    
        /**Method to process Action Event
         * @param actionEvent
         */
        public void processValueAction(ActionEvent actionEvent) {
            // Sleep for some time (Event Processing time)
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //After processing set button text to 'Done'
            buttonBind.setText("Done");
            AdfFacesContext.getCurrentInstance().addPartialTarget(buttonBind);
        }
    
        public void setButtonBind(RichButton buttonBind) {
            this.buttonBind = buttonBind;
        }
    
        public RichButton getButtonBind() {
            return buttonBind;
        }
    

  • Now question is how to change button text to 'Processing..' immediately after clicking button. So for this purpose i am using javascript

  • function changeButtonText(event) {
                      var comp = event.getSource();
                      comp.setText('Processing..');
                  }
    

  • Calling this javascript function using af:clientListener in button like this (See XML source of page)

  •  <af:document title="UpdatePageComponent.jspx" id="d1">
                <af:resource type="javascript">
                  function changeButtonText(event) {
                      var comp = event.getSource();
                      comp.setText('Processing..');
                  }
                </af:resource>
                <af:form id="f1">
                    <af:spacer width="10" height="10" id="s1"/>
                    <af:panelGroupLayout id="pgl1" layout="horizontal" halign="center">
                        <af:panelBox id="pb1" showDisclosure="false">
                            <f:facet name="toolbar"/>
                            <af:button text="Click to process" id="b1"
                                       actionListener="#{viewScope.UpdatePageComponent.processValueAction}"
                                       clientComponent="true" binding="#{viewScope.UpdatePageComponent.buttonBind}"
                                       inlineStyle="width:250px;text-align:center;padding:5px;font-weight:bold;">
                                <af:clientListener method="changeButtonText" type="action"/>
                            </af:button>
                        </af:panelBox>
                    </af:panelGroupLayout>
                </af:form>
            </af:document>
    

  • As soon as button is clicked this javascript function will be invoked and set new text in button and after event processing button text is again set by managed bean actionListener.


  • After Clicking button (Event is processing)-

    Processing complete-

Thanks, Happy Learning :)

Monday, 22 December 2014

Uploading and showing image file from absolute server path -Orace ADF

This is another post about file handling in ADF. Previous post was about uploading and downloading any type of file from absolute server path
See-
Uploading and downloading files from absolute server path in Oracle ADF (12.1.3)

This post is specifically about handling image files, uploading an image file to server path and immediately show it on page using af:image component
So here i am using Jdev 12C (12.1.3) , see step by step implementation
  • Create a fusion web application and a page in viewController



  • Now drop af:inputFile (to browse and select file), af:image (to show uploaded image) and a button to upload file


  • Bind af:inputFile value to managed bean variable, this variable is further used to read or write or process  file



  •     //To Store Value of selected file
        private UploadedFile imageFile;
    
        public void setImageFile(UploadedFile imageFile) {
            this.imageFile = imageFile;
        }
    
        public UploadedFile getImageFile() {
            return imageFile;
        }
    


  • Now see Managed Bean method to upload image file to absolute server path
  • Bean Method to Upload File-


        //To Store path of uploaded Image file
        String imagePath = null;
    
        public void setImagePath(String imagePath) {
            this.imagePath = imagePath;
        }
    
        public String getImagePath() {
            return imagePath;
        }
    
        /**Method to upload image file to absolute server path*/
        private String uploadImage(UploadedFile file) {
    
            UploadedFile myfile = file;
    
            if (myfile == null) {
    
            } else {
                if (myfile.getContentType().equalsIgnoreCase("image/jpeg") ||
                    myfile.getContentType().equalsIgnoreCase("image/png") ||
                    myfile.getContentType().equalsIgnoreCase("image/bmp") ||
                    myfile.getContentType().equalsIgnoreCase("image/gif")) {
    
                    //Path of folder on drive
                    String path = "D://ADF//";
                    String type = "PNG";
                    String TypeVal = ".png";
                    if (myfile.getContentType().equalsIgnoreCase("image/jpeg")) {
                        type = "JPEG";
                        TypeVal = ".jpeg";
                    } else if (myfile.getContentType().equalsIgnoreCase("image/png")) {
                        type = "PNG";
                        TypeVal = ".png";
                    } else if (myfile.getContentType().equalsIgnoreCase("image/bmp")) {
                        type = "PNG";
                        TypeVal = ".png";
                    } else if (myfile.getContentType().equalsIgnoreCase("image/gif")) {
                        type = "GIF";
                        TypeVal = ".gif";
                    }
    
                    InputStream inputStream = null;
                    try {
                        //Generate a unique name for uploaded image with date time
                        DateFormat dateFormat = new SimpleDateFormat("yyMMdd_HHmmss");
                        Date date = new Date();
                        String dtTime = dateFormat.format(date);
                        dtTime = dtTime.replace(" ", "_");
    
                        String name = "IMG" + "_" + dtTime;
                        System.out.println("File name is-" + name);
                        inputStream = myfile.getInputStream();
                        BufferedImage input = ImageIO.read(inputStream);
    
                        //Writing file to path
                        File outputFile = new File(path + name + TypeVal);
                        ImageIO.write(input, type, outputFile);
                        imagePath = outputFile.getAbsolutePath();
    
    
                    } catch (Exception ex) {
                        // handle exception
                        ex.printStackTrace();
                    } finally {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                        }
                    }
                } else {
                    imagePath = "NO";
                }
            }
            setImageFile(null);
            return imagePath;
        }
    


    ActionListener of Upload Button-


        /**Action Listener to Upload image File
         * @param actionEvent
         */
        public void uploadImageFileAction(ActionEvent actionEvent) {
            File directory = new File("D://ADF//");
            //get all the files from a directory
            File[] fList = directory.listFiles();
            for (File file : fList) {
                //Delete all previously uploaded files
                if (!"NoImage.png".equalsIgnoreCase(file.getName())) {
                    file.delete();
                }
    
            }
            //Upload Currently Selected File
            String flag = uploadImage(imageFile);
    
            if ("NO".equalsIgnoreCase(flag)) {
                FacesMessage msg =
                    new FacesMessage("This is not an Image file, Please upload supported file type (.jpg,.png etc)");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                FacesContext.getCurrentInstance().addMessage(null, msg);
            }
        }
    

  • set usesUpload to true for af:form component on page to support file upload


  • Now upload part is complete , next is to show uploaded image on page. So to do this create a servlet (this will process image file into bytes and then show using af:image component)



  • See Servlet code and how it is mapped with af:image component

  • import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ViewImageServlet extends HttpServlet {
        private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
    
        public void init(ServletConfig config) throws ServletException {
            super.init(config);
        }
    
        /**
         * @param request
         * @param response
         * @throws ServletException
         * @throws IOException
         */
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String path = (request.getParameter("path"));
    
    
            OutputStream os = response.getOutputStream();
            //If path is null or file is not an image
            if (path.equalsIgnoreCase("No")) {
                path = "D:\\ADF\\NoImage.png";
            }
            if (request.getParameter("path") == "") {
                path = "D:\\ADF\\NoImage.png";
            }
            InputStream inputStream = null;
    
            try {
                File outputFile = new File(path);
                inputStream = new FileInputStream(outputFile);
                BufferedInputStream in = new BufferedInputStream(inputStream);
                int b;
                byte[] buffer = new byte[10240];
                while ((b = in.read(buffer, 0, 10240)) != -1) {
                    os.write(buffer, 0, b);
                }
    
    
            } catch (Exception e) {
    
                System.out.println(e);
            } finally {
                if (os != null) {
                    os.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
    
            }
    
        }
    }
    


  • Now run this application and check this (All uploaded files will be stored in D://ADF path)
Select an image and click upload (Image is immediately reflected on page)


Check in D://ADF folder, image file is uploaded there with a new name


Again upload another image-


Check that previous file is deleted from folder and current one is there-


Happy Learning :)

Monday, 8 December 2014

Show animated Image Caption using jQuery in ADF Faces

This is another post about using jQuery in ADF Faces, see previous posts on jQuery

Using JQuery in Oracle ADF 
Image zoom (power zoomer) effect using Jquery in ADF Faces

This post talks about - how to add mouse hover caption to images? Caption means a brief explanation of picture/image. Normally 'alt' attribute of HTML page is used as Image Caption
But in ADF Faces af:image doesn't has 'alt' property , there is a property called 'shortdesc' and this property is used as 'alt' attribute for image when jsf page is loaded at client browser
you can check this in html source of your page in browser (inspect element)




<af:image shortDesc="Black Horse running or flying" id="FirstImage"
                                  inlineStyle="height:300px;width:500px;"
                                  source="#{resource['images:Best-Wild-Animal-Photos-of-2012-307-black-horse-running.jpg']}"/>


JSF page is converted to html for client side presentation, see in HTML source 'shortdesc' is used as 'alt' property


jQuery is used for client side scripting of HTML so jQuery script makes use of this 'alt' attribute to show animated caption for image
There are lots of jQuery and JavaScript available for showing different types of captions , here i am using jQuery Capty - A Caption Plugin (Download jQuery script and respective css file from link)

Now follow steps to use this jQuery plugin with ADF Faces
  • Create Fusion Web Application and a page in viewController, added jQuery script and css in viewController project (Jdev 12.1.3)


  • Add jQuery library and script file reference to page, also add css file reference to page

  •  //jQuery library reference
                <af:resource type="javascript" source="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></af:resource>
                //jQuery file reference that will be used to show caption
                <af:resource type="javascript" source="js/jquery.capty.js"/>
                <af:resource type="javascript" source="js/jquery.capty.min.js"/>
                //CSS file to style Caption
                <af:resource type="css" source="css/jquery.capty.css"/>
    

  • Next step is to execute jQuery function on pageload to show caption

  • //Function to show default sliding caption
    
    $('#ImageId').capty();
    
    //Change default fucntion to change animation type , speed and height of caption
    
    $('#ImageId').capty({
    animation: 'fade',
    speed:     1000
    }) 
    

  • So here i am using both function for two different images (for first image animation type is slide (default) and for second it is fade), add clientListener to document tag and set it's type to 'load' (to execute jQuery function on pageload)

  •  <af:clientListener method="jQuery(document).ready(function($){ $('#FirstImage').capty(); $('#SecondImage').capty({animation: 'fade',   speed:     1000}) })" type="load"/>
    

  • Run application and see magic of jQuery

  • Image Caption (animation:slide)-

    Image Caption (animation:fade)-

  • you can change style (color,font etc) of caption box by modifying css sheet and size can be increased or decreased from jQuery function. for example i have changed color, font and size of caption box. see this

  • @CHARSET "UTF-8";
    
    div.capty-caption {
     background-color: red;
     color: #FFF;
     font: bold 11px cursive;
     padding-left: 10px;
     padding-top: 7px;
     text-shadow: 1px 1px 0 #222;
    }
    
    div.capty-caption a {
     color: #318DAD;
     font: bold 11px verdana;
     text-decoration: none;
     text-shadow: none;
    }
    

    jQuery function to increase size-

    jQuery(document).ready(function($){ $('#FirstImage').capty(); $('#SecondImage').capty({animation: 'fade',   speed:1000,height:50}) })
    

    See output-
Thanks, Happy Learning :)
Download Sample ADF Application

Tuesday, 2 December 2014

Image zoom (power zoomer) effect using Jquery in ADF Faces

Jquery is most popular javascript library ,it is used to provide better ui design, animations and client side events
This is another post about using jquery in ADF Faces, see previous post
Using JQuery in Oracle ADF

In this post i am using a jquery script to zoom (enlarge) image on hover , you have seen this in many e-commerce websites as they provide power zoom feature to enlarge product image for better customer experience



I have taken this jquery script from Dynamic Drive, see the documentation
To implement this in ADF Application follow these steps
  • Create a Fusion Web Application and a page in viewController project (Jdev 12.1.3)


  • Downloaded jquery script file from above link -ddpowerzoomer.js, add this jquery file to viewController project


  • Now add jquery library reference in page in order to use jquery functions

  • <af:resource type="javascript" source="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></af:resource>
                <af:resource type="javascript" source="js/ddpowerzoomer.js"/>
    

  • Next step is to add an image to page , so added an af:image to page and set path of image to display


  • Now i have to execute jquery function that will add power zoom feature to this image (See jquery code that will be executed on pageload)

  • jQuery(document).ready(function($){
     $('#i1').addpowerzoom({
      defaultpower: 2,  powerrange: [2,5],  largeimage: null,  magnifiersize: [75,75]  }) 
    })
    

    here i1 is the id of image, default zoom power and magnifier size is configured here
  • So to execute this jquery function on pageload , added a clientListenr to pagelike this

  • <af:clientListener type="load"
                                   method="jQuery(document).ready(function($){   $('#i1').addpowerzoom({  defaultpower: 2,  powerrange: [2,5],  largeimage: null,  magnifiersize: [75,75]  }) })"/>
    

  • Now run this application and check it, magnifier is on deer :)


  • Now i am increasing size and power of magnifier - Power is 3 and size is 200x200
Thanks, Happy Learning :)
Download Sample ADF Application

Monday, 24 November 2014

Populate af:table programmatically from managead bean using POJO

This post is about a common question
How can we populate an af:table programmatically ?

It means that data in af:table is not populated through model layer (Using ViewObject) using binding layer. lets say I have some values in our managed bean and have to show records in tabular format on page

So what we have to do -
  • First you should know the number and data type of columns in table, suppose i have to populate a table for person details (name, mobile number and salary). to get and set value of columns i have created a java bean class , it has 3 variable for 3 columns



  • // Java Class to set and get value for table column
    public class PersonBean {
    
        public PersonBean(String name, String moNo, Integer salary) {
            this.Name = name;
            this.mobNo = moNo;
            this.salary = salary;
        }
        private String Name;
        private String mobNo;
        private Integer salary;
    
        public void setName(String Name) {
            this.Name = Name;
        }
    
        public String getName() {
            return Name;
        }
    
        public void setMobNo(String mobNo) {
            this.mobNo = mobNo;
        }
    
        public String getMobNo() {
            return mobNo;
        }
    
        public void setSalary(Integer salary) {
            this.salary = salary;
        }
    
        public Integer getSalary() {
            return salary;
        }
    }
    

  • Next step is to create a managed bean for referencing af:table , this managed bean makes use of person java bean class to add data in same format for all table rows. A List data structure is used to pass all values in af:table. See code of managed bean 

  • //ArrayList to poplate data in af:table
        List<PersonBean> personList = new ArrayList();
    
        //To Populate default row in table (Code in Constructor)
    
        public ProgTableBean() {
            personList.add(new PersonBean("Ashish Awasthi", "xxxxxxxxxx", 50000));
        }
    
        public void setPersonList(List<PersonBean> personList) {
            this.personList = personList;
        }
    
        public List<PersonBean> getPersonList() {
            return personList;
        }
    

  • Now just drop an af:table on page and set it's properties like value, column header and text values in columns

  •  As i have to show only 3 columns so deleted extra ones

     Set properties -
     value- from where table collection is populated
     columns values- take the var reference of table and refer variable name in List (here 'row' is table var and second is variable name in person bean class)


     See the XML source of af:table-

    <af:table var="row" rowBandingInterval="1" id="t1" value="#{viewScope.ProgTableBean.personList}"
                              partialTriggers="::b1">
                        <af:column sortable="false" headerText="Name" id="c1" width="150">
                            <af:outputText value="#{row.name}" id="ot1"/>
                        </af:column>
                        <af:column sortable="false" headerText="Mobile Number" id="c2">
                            <af:outputText value="#{row.mobNo}" id="ot2"/>
                        </af:column>
                        <af:column sortable="false" headerText="Salary" id="c3" align="right">
                            <af:outputText value="#{row.salary}" id="ot3"/>
                        </af:column>
                    </af:table>
    

  • Now run this application and see there will be one row in table as code is added in constructor of managed to populate one row


  • I have added a form and button in page to add new records in table , see the form source code

  • <af:panelFormLayout id="pfl1">
                        <f:facet name="footer"/>
                        <af:inputText label="Name :" id="it1" binding="#{viewScope.ProgTableBean.nameBind}"/>
                        <af:inputText label="Mobile Number :" id="it2" binding="#{viewScope.ProgTableBean.mobNumBind}"/>
                        <af:inputText label="Salary :" id="it3" binding="#{viewScope.ProgTableBean.salaryBind}">
                            <af:convertNumber/>
                        </af:inputText>
                        <af:button text="Add Record" id="b1" actionListener="#{viewScope.ProgTableBean.addNewRcord}"/>
                    </af:panelFormLayout> 
     

    Code in managed bean for button action-

        /**Method to add new record in table
         * @param actionEvent
         */
        public void addNewRcord(ActionEvent actionEvent) {
            //Get all values using compoenet binding as mobNumBind
            if (mobNumBind.getValue() != null && nameBind.getValue() != null &&
                salaryBind.getValue() !=
                null) {
                // Add new Record in List
                personList.add(new PersonBean(nameBind.getValue().toString(), mobNumBind.getValue().toString(),
                                              Integer.parseInt(salaryBind.getValue().toString())));
            }
        }
    

  • now run and check application- 


 More posts on POJO Based table -

Get selected row (single/multiple) from POJO based table in ADF
Apply sorting to POJO based af:table programmatically , Using custom sort listener in ADF

Thanks , Happy Learning :)
Download-Sample ADF Application

Wednesday, 19 November 2014

Populate Dynamic table and form using af:dynamicComponent and dynamic viewObject - Oracle ADF

This post is about a common development requirement- Can we increase or decrease number of fields , type of fields (columns in case of table), data in fields at run time?

Suppose i have to show data of Departments and Employees table on page using only one af:table component. It means columns should be generated dynamically at run time depending on any defined condition
So for this requirement i am using dynamic viewObject in model layer and af:dynamicComponent in view layer
See previous post about creating dynamic viewObject-
Creating Dynamic View Object at Runtime programmatically - Oracle ADF

See step by step implementation-
  • Create Fusion Web Application and follow the link posted above to create dynamic viewObject, in short create a viewObject using dual and a method in AMImpl to create dynamic viewObject from sql query


  •     /**Method to create viewObject using SQL query
         * @param query
    
    
    
    
    
    
    
         */
        public void createNewViewObject(String query) {
            ViewObject dynVo = this.getdynamic1();
            dynVo.remove();
            this.createViewObjectFromQueryStmt("dynamic1", query);
            this.getdynamic1().executeQuery();
        }
    

  • Created a page and added an inputText to enter SQL query and a button to process that query and create dynamic viewObject at run time


  • See Managed Bean code to process query, value of inputText is passed using component binding

  •     private RichInputText sqlQueryBind;
    
        public DynamicTableBean() {
        }
    
        /*****Generic Method to call operation binding**/
        public BindingContainer getBindingsCont() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    
        /**
         * Generic Method to execute operation Binding
         * */
        public OperationBinding executeOperation(String operation) {
            OperationBinding createParam = getBindingsCont().getOperationBinding(operation);
            return createParam;
    
        }
    
        /**Method to create viewObject
         * @param actionEvent
         */
        public void createViewObjectAction(ActionEvent actionEvent) {
            if (sqlQueryBind.getValue() != null) {
                OperationBinding ob = executeOperation("createNewViewObject");
                ob.getParamsMap().put("query", sqlQueryBind.getValue().toString());
                ob.execute();
            }
        }
    
        public void setSqlQueryBind(RichInputText sqlQueryBind) {
            this.sqlQueryBind = sqlQueryBind;
        }
    
        public RichInputText getSqlQueryBind() {
            return sqlQueryBind;
        }
    

  • Now dropped this dual viewObject on page as dynamic form and dynamic table from Data Control (this snap is about creating form)



  • Next is to change pageDef entry for this dynamic component , open pageDef and goto treeBinding. there is an entry for nodeDefinition, there will be separate treeBinding for form and table both (you should change both)

  •  <tree IterBinding="dynamic1Iterator" id="dynamic1">
                <nodeDefinition DefName="dynamictableapp.model.view.dynamicVO" Name="dynamic10"/>
            </tree>
    

    Change this entry like this-

     <tree IterBinding="dynamic1Iterator" id="dynamic1">
                <nodeDefinition Name="dynamic10"/>
            </tree>
    

  • Now run this application and enter SQL query in box and press process button


 Thanks, Happy Learning :)
Download -Sample ADF Application