Please disable your adblock and script blockers to view this page

Search this blog

Friday, 15 August 2014

How to change default icons (info, Error, Warning) of FacesMessage and af:messages in Oracle ADF

Hello all
this post is about customizing or changing default icons of FacesMessage , it is very basic but sometimes it's hard to do easy things
if we need to use alternate icons in af:messages or in programmatic FacesMessage, so to do this just create a small ,simple CSS file (ADF Skin) in viewController project and use this code

Change url as per your icon image path, you can also define same for Fatal Error and Confirmation icon also




af|messages::info-icon
{
  content: url("../../information.png"); 
}

af|messages::warning-icon
{
  content: url("../../warning.png"); 
}
af|messages::error-icon
{
  content: url("../../error.png"); 
}

apply this skin to project and run your application to see changes

Default Icon Changed Icon

Happy Learning :)

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