Please disable your adblock and script blockers to view this page

Search this blog

Wednesday 13 August 2014

Use View Link Accessor to call aggregate functions, set attribute value , set bind variables value (Oracle ADF)


Hello All

This post is about various usage of view link accessor  , when we create viewLink between two viewObjects , destination accessor is created by default in master viewObject, there is check box to create source accessor also at same time

We can use this view link accessor for calculating attribute's sum, setting value of attributes etc



here Departments is master viewObject and Employees is it's detail, after creating viewLink you can see in viewObject xml source there accessor is present

In Departments ViewObject- 




<ViewLinkAccessor
    Name="Employees"
    ViewLink="sample.model.view.link.DeptTOEmpVL"
    Type="oracle.jbo.RowIterator"
    IsUpdateable="false"/>

In EmployeesViewObject- 
 

<ViewLinkAccessor
    Name="Departments"
    ViewLink="sample.model.view.link.DeptTOEmpVL"
    Type="oracle.jbo.Row"
    Reversed="true"
    IsUpdateable="false"/>

So what is the use of these view link accessors ?
Master accessor in detail viewObject returns current Row of master viewObject, when you generate RowImpl class for detail viewObject , it also has a method for this accessor


    /**
     * Gets the associated <code>Row</code> using master-detail link Departments.
     */
    public Row getDepartments() {
        return (Row) getAttributeInternal(DEPARTMENTS);
    }

    /**
     * Sets the master-detail link Departments between this object and <code>value</code>.
     */
    public void setDepartments(Row value) {
        setAttributeInternal(DEPARTMENTS, value);
    }

Detail accessor in master viewObject returns a row set of all row of details viewObject that are currently referenced by master record

    /**
     * Gets the associated <code>RowIterator</code> using master-detail link Employees.
     */
    public RowIterator getEmployees() {
        return (RowIterator) getAttributeInternal(EMPLOYEES);
    }

Now see what we can do with viewLink Accessor

1. Get master attribute value in detail viewObject

suppose i have to get a attribute's value from Master viewObject (Departments) in a attribute of detail viewObject (Employee)
in this example i am getting managerId from Departments ViewObject so for this just write in expression of Employee's ManagerId field
viewLinkAccesorName.AttributeName


now run BC4J tester and check - create new record in Employee and see managerId from Departments is auto populated

 on creating new record-


2. Call aggregate function to calculate sum of an attribute of detail viewObject

suppose now i have to calculate total salary of a Department (sum of Employees salary of that department)
for this purpose just call sum function to calculate sum of all rows of detail RowSet 
take a transient attribute in Departments ViewObject and write in it's expression
viewLinkAccesorName.sum("AttributeName")


 Run ApplicationModule and see-


3. Set bind variable value as per master viewObject's attribute (pass value from master viewObject)

This  is tricky part as we can not set bind variable value through expression as it doesn't recognize view link accessor name.
created a viewCriteria and bind variable for managerId in Employee viewObject




applied this criteria to Employees viewObject instance in Application Module (Just Shuttle criteria to selected side)


now to set bind variable's value we have to override prepareRowSetForQuery method in Employees VOImpl class

this method gets the value of managerId from currentRow of master ViewObject (Departments)and sets in bind variable of Employees viewObject


    @Override
    public void prepareRowSetForQuery(ViewRowSetImpl viewRowSetImpl) {
        RowSetIterator[] masterRows = viewRowSetImpl.getMasterRowSetIterators();
        if (masterRows != null && masterRows.length > 0 && masterRows[0].getCurrentRow() != null &&
            masterRows[0].getCurrentRow().getAttribute("ManagerId") != null) {
            Integer managerId = (Integer) masterRows[0].getCurrentRow().getAttribute("ManagerId");
            viewRowSetImpl.ensureVariableManager().setVariableValue("BindManagerId", managerId);
            System.out.println("ManagerID in bind Var-" + managerId);

        }
        super.prepareRowSetForQuery(viewRowSetImpl);
    }

now run AM and check it-

Happy Learning :)

Monday 4 August 2014

Uploading and downloading files from absolute server path 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

see step by step implementation -
  • I have created a simple table in HR schema to store uploaded file name ,path and content type
  • See sql script for this table-

     CREATE TABLE "FILE_UPD_DWN" 
       ( "FILE_NAME" VARCHAR2(50 BYTE), 
     "PATH" VARCHAR2(100 BYTE), 
     "CONTENT_TYPE" VARCHAR2(500 BYTE)
       )
    

  • Then prepare model using this table and drop on page as af:table, and an af:inputFile to select and upload file is used in page


  • Then create a ValueChangeListener on inputFile component to upload file to an actual path on server, and after upload a row is inserted in table to keep record of uploaded files

  • Bean Method to Upload File-


        /**Method to upload file to actual path on Server*/
        private String uploadFile(UploadedFile file) {
    
            UploadedFile myfile = file;
            String path = null;
            if (myfile == null) {
    
            } else {
                // All uploaded files will be stored in below path
                path = "D://FileStore//" + myfile.getFilename();
                InputStream inputStream = null;
                try {
                    FileOutputStream out = new FileOutputStream(path);
                    inputStream = myfile.getInputStream();
                    byte[] buffer = new byte[8192];
                    int bytesRead = 0;
                    while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                        out.write(buffer, 0, bytesRead);
                    }
                    out.flush();
                    out.close();
                } catch (Exception ex) {
                    // handle exception
                    ex.printStackTrace();
                } finally {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                    }
                }
    
            }
            //Returns the path where file is stored
            return path;
        }
    

    AMImpl method to insert record in table for Uploaded file




        /**Method to set file path and name
         * @param name
         * @param path
         */
        public void setFileData(String name, String path,String contTyp) {
            ViewObject fileVo = this.getFileUpdDwn1();
            Row newRow = fileVo.createRow();
            newRow.setAttribute("FileName", name);
            newRow.setAttribute("Path", path);
            newRow.setAttribute("ContentType", contTyp);
            fileVo.insertRow(newRow);
            this.getDBTransaction().commit();
            fileVo.executeQuery();
        }
    

    ValueChangeListener to execute all methods -




        /*****Generic Method to Get BindingContainer**/
        public BindingContainer getBindingsCont() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    
        /**
         * Generic Method to execute operation
         * */
        public OperationBinding executeOperation(String operation) {
            OperationBinding createParam = getBindingsCont().getOperationBinding(operation);
            return createParam;
    
        }
    
        /**Method to Upload File ,called on ValueChangeEvent of inputFile
         * @param vce
         */
        public void uploadFileVCE(ValueChangeEvent vce) {
            if (vce.getNewValue() != null) {
                //Get File Object from VC Event
                UploadedFile fileVal = (UploadedFile) vce.getNewValue();
                //Upload File to path- Return actual server path
                String path = uploadFile(fileVal);
                System.out.println(fileVal.getContentType());
                //Method to insert data in table to keep track of uploaded files
                OperationBinding ob = executeOperation("setFileData");
                ob.getParamsMap().put("name", fileVal.getFilename());
                ob.getParamsMap().put("path", path);
                ob.getParamsMap().put("contTyp", fileVal.getContentType());
                ob.execute();
                // Reset inputFile component after upload
                ResetUtils.reset(vce.getComponent());
            }
        }
    

  • Now run application and select files and see- 


  • See uploaded files in folder


  • I have seen that developers often use servlet to download and open file in browser window using HTTP response , but no need to to do this as ADF provides built in component for this <af:fileDownloadActionListener> that automatically generate http response
  • Now Upload part is complete , for download functionality added a link in table column and dropped an af:fileDownloadActionListener inside link and set properties for DownloadActionListener



  • See the code in Download Listener

  •     /**Method to download file from actual path
         * @param facesContext
         * @param outputStream
         */
        public void downloadFileListener(FacesContext facesContext, OutputStream outputStream) throws IOException {
            //Read file from particular path, path bind is binding of table field that contains path
            File filed = new File(pathBind.getValue().toString());
            FileInputStream fis;
            byte[] b;
            try {
                fis = new FileInputStream(filed);
    
                int n;
                while ((n = fis.available()) > 0) {
                    b = new byte[n];
                    int result = fis.read(b);
                    outputStream.write(b, 0, b.length);
                    if (result == -1)
                        break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            outputStream.flush();
        }
    

  • Now run application and see how Upload and download works 

Happy Learning :) Sample ADF Application

Next Post is this series - (Must Read)
Uploading mulitiple files to server path in Oracle ADF using af:inputFile
Uploading and downloading files from database (BLOB) in Oracle ADF

Friday 1 August 2014

Exporting viewObject data in text file using af:fileDownloadActionListener in Oracle ADF (12.1.3)

Hello All
This post is about using af:fileDownloadActionListener to generate file on run-time, suppose i have a viewObject and i want to export it's data in CSV or plain text so for this requirement we can generate file at run-time and send it to client UI to download

What is af:fileDownloadActionListener-
as per oracle docs-
The fileDownloadActionListener tag is a declarative way to allow an action source (<commandButton>, <commandLink>, etc.) to programatically send the contents of a file to the user, optionally with a specific content type and filename. Since file downloads must be processed with an ordinary request - not XMLHttp AJAX requests - this tag forces partialSubmit to be false on the parent component, if it supports that attribute.
The fileDownloadActionListener uses the native (browser built-in) filedownload popup, so this popup cannot be configured.

In this post i am using Departments table of HR schema



  • Prepare model part using Departments table and drop it on page as a table and add a button to UI for downloading


  • drop af:fileDownloadActionListener as child of button and set it's property as contentType, method , fileName 


  • Now see code written in download Listener-

  •     /**Method to get BindingsContainer for current page
         * @return
         */
        public BindingContainer getBindingsCont() {
            return BindingContext.getCurrent().getCurrentBindingsEntry();
        }
    
        /**Method to download ViewObject's data in plain text file
         * @param facesContext
         * @param outputStream
         * @throws UnsupportedEncodingException
         * @throws IOException
         */
        public void fileDownloadListener(FacesContext facesContext,
                                         OutputStream outputStream) throws UnsupportedEncodingException, IOException {
            OutputStreamWriter w = new OutputStreamWriter(outputStream, "UTF-8");
            //Get itertaor from bindings
            DCIteratorBinding deptIter = (DCIteratorBinding) getBindingsCont().get("Departments1Iterator");
            //Get ViewObject from Iterator
            ViewObjectImpl vo = (ViewObjectImpl) deptIter.getViewObject();
            ViewAttributeDefImpl[] attrDefs = vo.getViewAttributeDefImpls();
            int count = 0;
            RowSetIterator rsi = vo.createRowSetIterator(null);
            while (rsi.hasNext()) {
                Row nextRow = rsi.next();
                if (nextRow != null) {
                    // Code to iterate over ViewObject's column to get all columns value at runtime
                    for (ViewAttributeDefImpl attrDef : attrDefs) {
                        byte attrKind =
                            attrDefs[count].getAttributeKind(); //checks attribute kind for each element in an array of AttributeDefs
                        if (attrKind != AttributeDef.ATTR_ASSOCIATED_ROW &&
                            attrKind != AttributeDef.ATTR_ASSOCIATED_ROWITERATOR) {
                            String columnName = attrDef.getName();
                            w.write(columnName + " - " + nextRow.getAttribute(columnName) + "  ");
                        }
                    }
                    // Code to create new line text line for new Row
                    w.write(System.getProperty("line.separator"));
                }
            }
            //Flush the writer after wrting file
            w.flush();
        }
    }
    

  • Run this application and click on download button, browser download box appears , open downloaded file and see how your data appears in text file, to export data in a pdf file you have to generate PDF file using some API then you can download it in same way


Cheers:) Happy Learning