Tuesday 25 December 2012

Insert Multiple records in DB

There are many scenarios where we have to check the performance in ADF while retrieving thousands of records from Database. For that we need this many records in our DB.

We can insert multiple records in one go by using PL/SQL block.

Begin
For <counter>in <start_counter>..<end_counter>
Loop
Insert into <table_name>(<column1>,<coulumn2>,<column3>)
values(
value1, value2,value3);
End loop;
End;


commit;

Example:

Begin
For i in 1..4000
Loop
Insert into Student (id,name,address)
values(i, dbms_random.string('A',5), dbms_random.string('B',5));
End loop;
End;

commit;


Sunday 23 December 2012

ADF Single/Multiple files uploading and downloading

This post is about to upload single file/multiple files from the client to the server and store the data in a BLOB column in Database.

First of all, we have to create a table to store files in database:

CREATE TABLE "HR"."DOCUMENTS"
  (
    "DOCUMENT_ID"   NUMBER NOT NULL ENABLE,
    "DOCUMENT_NAME" VARCHAR2(50 BYTE),
    "DOCUMENT_TYPE" VARCHAR2(100 BYTE),
    "DOCUMENT_FILE" BLOB,
    CONSTRAINT "DOCUMENTS_PK" PRIMARY KEY ("DOCUMENT_ID") 

  )

Single file upload 

Below is the UI for single file upload  with a table with uploaded files along with the download button for each file.


 Steps to achieve single file uploading:

1. Add inputFile component on jspx page:

  <af:inputFile label="Upload File" id="if1"
       binding="#{pageFlowScope.SingleFileUploadDownloadBean.inputFile}"
       valueChangeListener="#{pageFlowScope.SingleFileUploadDownloadBean.onFileUploadVCL}"
        autoSubmit="true"/>

  
  Add a button to trigger the action to upload the File:

 <af:commandButton text="Upload" id="cb1"
          disabled="#{pageFlowScope.SingleFileUploadDownloadBean.inputFile.value == null ? true : false}"
          partialTriggers="if1"
          actionListener="#{pageFlowScope.SingleFileUploadDownloadBean.onFileUpload}"
          partialSubmit="true"/>


2. Drag and drop the DocumentsVO on page as Adf Table. Remove the Blob column from the table and add a new column in UI to enable File downloading:

//Comment out or remove Blob Column from the table
<!--<af:column sortProperty="DocumentFile" sortable="false"
                             headerText="#{bindings.DocumentsVO1.hints.DocumentFile.label}"
                             id="c1">
                    <af:inputText value="#{row.bindings.DocumentFile.inputValue}"
                                  label="#{bindings.DocumentsVO1.hints.DocumentFile.label}"
                                  required="#{bindings.DocumentsVO1.hints.DocumentFile.mandatory}"
                                  columns="#{bindings.DocumentsVO1.hints.DocumentFile.displayWidth}"
                                  maximumLength="#{bindings.DocumentsVO1.hints.DocumentFile.precision}"
                                  shortDesc="#{bindings.DocumentsVO1.hints.DocumentFile.tooltip}"
                                  id="it1">
                      <f:validator binding="#{row.bindings.DocumentFile.validator}"/>
                    </af:inputText>
  </af:column>-->

//Add new Column to add Download button in each row
 <af:column id="c1" width="413"
                                     headerText="File Download">
                            <af:commandButton text="Download File" id="cb3">
                              <af:fileDownloadActionListener contentType="#{row.bindings.DocumentType.inputValue}"
                                                             filename="#{row.bindings.DocumentName.inputValue}"
                                                             method="#{pageFlowScope.SingleFileUploadDownloadBean.downloadFile}"/>
                            </af:commandButton>
 </af:column>


3. In ManagedBean : (Here bean name is SingleFileUploadDownloadBean)

    private RichInputFile inputFile;
    private String fileName;
    private String contentType;
    private UploadedFile file;
    private BlobDomain blob;

 // Value Change Listener for inputFileComponent
    public void onFileUploadVCL(ValueChangeEvent valueChangeEvent) {
        file = (UploadedFile)valueChangeEvent.getNewValue();
        // Get the file name
        fileName = file.getFilename();
        // get the mime type
        contentType = file.getContentType();
        // get blob
        blob=getBlob(file);     
    }

 // Method to get Blob
    public BlobDomain getBlob(UploadedFile file){      
            InputStream in = null;
            BlobDomain blobDomain = null;
            OutputStream out = null;
            try
            {               
                in = file.getInputStream();             
                blobDomain = new BlobDomain();              
                out = blobDomain.getBinaryOutputStream();               
                IOUtils.copy(in, out);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            catch (SQLException e)
            {
                e.fillInStackTrace();
            }          
            return blobDomain;
    }

//Method to invoke Operation binding to upload file in database
    public void onFileUpload(ActionEvent actionEvent) {      
        DCBindingContainer bc = ADFUtil.getBindingContainer();
        OperationBinding operationbinding = bc.getOperationBinding("uploadFiletoDB");
        if(operationbinding!=null){
            operationbinding.getParamsMap().put("fileName", fileName);
            operationbinding.getParamsMap().put("contentType", contentType);
            operationbinding.getParamsMap().put("blob", blob);
            operationbinding.execute();
        }
        System.out.println("File uploaded successfully");
        if (inputFile != null) {
            inputFile.resetValue();
            inputFile.setValid(true);
        }
    }

//Method to download File
Note: Make sure that Row Selection must be single and in SelectionListener should be present in ADF table on jspx page:

    public void downloadFile(FacesContext facesContext,
                             OutputStream outputStream) {
        DCBindingContainer bindings = ADFUtil.getBindingContainer();
        DCIteratorBinding iteratorbinding =
            bindings.findIteratorBinding("DocumentsVO1Iterator");
        BlobDomain blob =
            (BlobDomain)iteratorbinding.getCurrentRow().getAttribute("DocumentFile");
        try {
            IOUtils.copy(blob.getInputStream(), outputStream);
            blob.closeInputStream();
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


Multiple files upload :

Here we can add multiple inputFile component on click of Add Attachment button and remove the same by clicking Remove Attachment button. By default one inputFile component will be displayed. And after uploading single/multiple files, on click of Upload Files button, the uploaded files will be stored in database.


  Steps to achieve multiple files uploading:

 1. We will use forEach to add multiple inputFile component

<af:forEach items="#{pageFlowScope.MultipleFileUploadDownloadBean.rowFields}" var="row">
   <af:inputFile label="Upload File" id="if2"
    binding="#{pageFlowScope.MultipleFileUploadDownloadBean.map['FIELD'].inputFile}"
    autoSubmit="true"
     valueChangeListener="#{pageFlowScope.MultipleFileUploadDownloadBean.onFileUploadVCL}"
     partialTriggers="cb5"/>            
  </af:forEach>


//Add attachment Button to create new inputFile at runtime 
 <af:commandButton text="Add Attachment" id="cb4"
    actionListener="#{pageFlowScope.MultipleFileUploadDownloadBean.onAddFile}"/>


 2. We will create a separate class to create Multiple inputFile component:

import oracle.adf.view.rich.component.rich.input.RichInputFile;

public class FileUpload {
    private RichInputFile inputFile;
    public FileUpload() {
        super();
    }

    public void setInputFile(RichInputFile inputFile) {
        this.inputFile = inputFile;
    }

    public RichInputFile getInputFile() {
        return inputFile;
    }
}
 

3. In ManagedBean:

    private List fileNameList = new ArrayList();
    private List fileContentTypeList = new ArrayList();
    private List fileBlobList = new ArrayList();
    private List fileSizeList = new ArrayList();
    private List<HashMap> fieldlist = new ArrayList<HashMap>();
    private HashMap<String, FileUpload> map;

    private int fileCounter = 0; 

//In constructor add below code to add single inputFile component on first time page load
    public MultipleFileUploadDownloadBean() {
        map = new HashMap<String, FileUpload>();
        try {
            FileUpload test = new FileUpload();
            map.put("FIELD", test);
            fieldlist.add(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 


// Method to create new InputFile on UI
    public void onAddFile(ActionEvent actionEvent) {
        map = new HashMap<String, FileUpload>();
        try {
            FileUpload inputFile = new FileUpload();
            map.put("FIELD", inputFile);
            fieldlist.add(map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 


//Method to remove inputFile on UI 
    public void onRemoveFile(ActionEvent actionEvent) {
        if (fieldlist.size() > 1) {
            fieldlist.remove(fieldlist.size() - 1);
        }
    }

 


 //Value Change Listener for inputFile
     public void onFileUploadVCL(ValueChangeEvent valueChangeEvent) {
        UploadedFile file;
        file = (UploadedFile)valueChangeEvent.getNewValue();
        fileNameList.add(file.getFilename());
        fileContentTypeList.add(file.getContentType());
        fileSizeList.add(file.getLength());
        fileBlobList.add(getBlob(file));

        // file counter to limit no of files that can be uploaded
        fileCounter++;
    }

  
// Method to invoke Operation binding to upload multiple files in database
    public void onFileUpload(ActionEvent actionEvent) {
        DCBindingContainer bc = ADFUtil.getBindingContainer();
        OperationBinding operationbinding =
            bc.getOperationBinding("uploadMultipleFilestoDB");
        if (operationbinding != null) {
            operationbinding.getParamsMap().put("fileNameList", fileNameList);
            operationbinding.getParamsMap().put("fileContentTypeList",
                                                fileContentTypeList);
            operationbinding.getParamsMap().put("fileBlobList", fileBlobList);
            operationbinding.execute();
        }
        System.out.println("File uploaded successfully");
    }



 Find the sample app here


Wednesday 19 December 2012

ADF POJO Data Control

POJO data control obtains the structure of the data from POJOs (plain, old Java objects).
To create data control, right-click a Java class file (in the Application Navigator), and choose Create Data Control.

Steps:

In  Model project :
1. Create a pojo (java class). eg. Product.java

package model.pojo;

public class Product {
    private String productId;
    private String productName;
    public Product() {      
        super();
    }
    public Product(String productId,String productName) {      
       this.productId=productId;
       this.productName=productName;          
    }
    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getProductName() {
        return productName;
    }
}

 2. Create Service Bean class. e.g. ProductBean.java

package model;
import java.util.ArrayList;
import java.util.List;
import model.pojo.Product;

public class ProductBean {
    private List<Product> products=new ArrayList();
    public ProductBean() {
       this.createData();
    }
   
    private void createData(){
        products.add(new Product("101","Alto"));
        products.add(new Product("102","Benz"));
        products.add(new Product("103","Chevrolet"));
        products.add(new Product("104","Cruze"));
        products.add(new Product("105","Accord"));
    }
   
    public List<Product> findAllProducts() {
        return products;
      }  
}


3. Right click on ProductBean.java and choose "Create Data Control".

In ViewController project:
4. Create a jspx page.

5. In Data Controls panel, drag and drop the data collections on jspx page as ADF Table.

6. Run the jspx page.

Find the sample app here

Tuesday 18 December 2012

Regular Expression validation in ADF


We can use regular expressions for validations in ADF.
  • For UI input components we can use regex as below:
<af:inputText label="Label 1" autoSubmit="true">
 <af:validateRegExp pattern="[0-9]{1,10}"
                               noMatchMessageDetail="Only Numbers are allowed"/>
</af:inputText>
<af:commandButton text="commandButton 1"/>

In above example, the moment we tab out of input text, we get an error message with the text we provided.

  • We can also write our custom validator in managed bean:
    public void inputTextValidator(FacesContext facesContext,
                                   UIComponent uIComponent, Object object) {
        // Add event code here...
    }


 <af:inputText label="Label 1" id="it3"
                            validator="#{pageFlowScope.UIBean.inputTextValidator}">              
              </af:inputText>


  • Also we can use regex in the model layer with an attribute level validator - this will eliminate getting wrong data if someone uses the same business service in another UI.

Some common regex examples are:

Validation for decimal places

 String REGEX_CHECK_DECIMAL =
            "^-?\\d{1," + (length - decimal) + "}(?>\\.\\d{1," + decimal+ "})?$";

where length is total length of the String and decimal is no of decimal digits.

Validation for String uppercase

String REGEX_CHECK_UPPERCASE ="[A-Z]+";

more to come....

Monday 17 December 2012

java.lang.ClassNotFoundException: oracle.stellent.ridc.IdcClientManager

IdcClientManager class is present in oracle.ucm.ridc-11.1.1.jar which is a part of RIDC JDeveloper Extension deployed as shared lib oracle.ucm.ridc.app-lib(11.1.1,11.1.1) on weblogic.

On the Project Technologies tab, select RIDC, which will automatically add the RIDC shared lib reference to weblogic-application.xml/weblogic.xml.
<library-ref>
    <library-name>oracle.ucm.ridc.app-lib</library-name>
</library-ref> 
Refer http://docs.oracle.com/cd/E23943_01/doc.1111/e10807/c23_ridc.htm#BABEIGAA

Thursday 13 December 2012

File Uploading in ADF

We use inputFile component to upload file in ADF which returns object of UploadedFile class.
To implement file upload functionality, follow the below steps:

1. add af:inputFile component to the form.
2. set usesUpload property of the af:form element to true.
3. create binding of inputFile and its valueChangeListener in managed bean.
4. write code to implement file upload and display its content in text area as shown in below example:

Here I am uploading a txt file and showing its name and content on click of Upload button. On successful upload, I am resetting inputFile component. I followed a basic use case here. But we can change the design and functionality as per different use cases like we can check content Type and content size etc.





jspx code:

 <af:panelGroupLayout id="pgl1" layout="vertical">
              <af:panelGroupLayout id="pgl2" layout="horizontal">
                <af:inputFile label="Upload File" id="if1"
                              binding="#{pageFlowScope.UIBean.inputFile}"
                              valueChangeListener="#{pageFlowScope.UIBean.onFileUploadValueChangeListener}"
                              autoSubmit="true"/>
                <af:spacer width="10" height="10" id="s1"/>
                <af:commandButton text="Upload" id="cb1"
                                  disabled="#{pageFlowScope.UIBean.inputFile.value == null ? true : false}"
                                  partialTriggers="if1"
                                  actionListener="#{pageFlowScope.UIBean.onUploadFile}"/>
              </af:panelGroupLayout>
              <af:spacer width="10" height="10" id="s3"/>
              <af:panelFormLayout id="pfl1" partialTriggers="cb1">
                <af:inputText label="File Name" id="it2" columns="30"
                              readOnly="true"
                              value="#{pageFlowScope.UIBean.fileName}"/>
                <af:inputText label="File Content" id="it1" rows="10"
                              columns="100" readOnly="true"
                              value="#{pageFlowScope.UIBean.fileContent}"/>
              </af:panelFormLayout>
              <af:spacer width="10" height="10" id="s2"/>
            </af:panelGroupLayout>

 Managed Bean Code:


import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import oracle.adf.view.rich.component.rich.input.RichInputFile;
import org.apache.commons.io.IOUtils;
import org.apache.myfaces.trinidad.model.UploadedFile;

public class UIBean {
    private RichInputFile inputFile;
    private UploadedFile file;
    private String fileContent;
    private String fileName;
    private InputStream inputstream;

    public UIBean() {
        super();
    }

    public void onFileUploadValueChangeListener(ValueChangeEvent valueChangeEvent) {
        resetValue();
        file = (UploadedFile)valueChangeEvent.getNewValue();
        try {
            inputstream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void onUploadFile(ActionEvent actionEvent) {
        if (file != null && inputstream != null) {
            fileName = file.getFilename();
            StringWriter writer = new StringWriter();
            try {
                IOUtils.copy(inputstream, writer);
                fileContent = writer.toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (inputFile != null) {
            inputFile.resetValue();
            inputFile.setValid(true);
        }
    }

    public void resetValue() {
        if (fileName != null)
            fileName = null;
        if (fileContent != null)
            fileContent = null;
        if (inputstream != null)
            inputstream = null;
    }

    public void setInputFile(RichInputFile inputFile) {
        this.inputFile = inputFile;
    }

    public RichInputFile getInputFile() {
        return inputFile;
    }

    public void setFile(UploadedFile file) {
        this.file = file;
    }

    public UploadedFile getFile() {
        return file;
    }

    public String getFileContent() {
        return fileContent;
    }

    public String getFileName() {
        return fileName;
    }
}

Find the sample application here.


Friday 30 November 2012

Populate ADF table from Managed Bean

To create a ADF table and populate it from backing bean, define a List in backing bean and populate it with table data. Also the EL #{row.col1} won't work since String.getCol1() does not exists. So define a pojo class to populate the row values. In below example, its Employee.


In adf page :


<af:table var="row" rowBandingInterval="0" id="t1"
                      value="#{pageFlowScope.SampleManagedBean.empList}">
              <af:column sortable="false" headerText="EmpId" id="c1">
                <af:outputText value="#{row.empid}" id="ot2"/>
              </af:column>
              <af:column sortable="false" headerText="EmpName" id="c2">
                <af:outputText value="#{row.empname}" id="ot1"/>
              </af:column>
</af:table>


In managed bean:


public class SampleManagedBean {
    private List<Employee> empList;

    public SampleManagedBean() {
        super();
    }

    public void populateList() {
        empList=new ArrayList();
        empList.add(new Employee(1, "Emp1"));
        empList.add(new Employee(2, "Emp2"));
        empList.add(new Employee(3, "Emp3"));
    }

    public void setEmpList(List<Employee> empList) {
        this.empList = empList;
    }

    public List<Employee> getEmpList() {
        if(empList==null)
        this.populateList();
        return empList;
    }
}

In Employee class :

public class Employee {
    private int empid;
    private String empname;
    public Employee(int id,String name) {
       this.empid=id;
       this.empname=name;
    }

    public void setEmpid(int empid) {
        this.empid = empid;
    }

    public int getEmpid() {
        return empid;
    }

    public void setEmpname(String empname) {
        this.empname = empname;
    }

    public String getEmpname() {
        return empname;
    }
}

You can download the SampleApp here

Tuesday 27 November 2012

Invoke ADF bindings in page templates

In order to access method binding in page template pagedef , get its reference in consumer pagedef executable section. We can use standard ADFUtil for this. Find the attached ADFUtil here

In DataBindings.cpx file, we can find the pagetemplate pagedef id.


Executable section of consumer pagedef :

    public void getEmployeeRecord() {       
        //access page template Pagedef reference in executable section of consumer page PageDef
        DCBindingContainer binding =
           (DCBindingContainer)ADFUtil.evaluateEL("#{bindings.data.portal_pageTemplate_globePageDef}");
      
        //get the MethodBinding
        OperationBinding operationbinding = (OperationBinding)binding.get("getEmployeeNames");
       
        //invoke the method
        if (operationbinding != null)
            operationbinding.execute();
    }