feedburner

Subscribe to the site feed for newer articles

feedback-image

RichFaces File Upload Tutorial

Labels: , ,


Rich Faces consists of some really useful components that can be used to make as they say  some very "rich web applications".
In this tutorial i will be explaining about how to use richfaces file upload component to store a file into the database and then retrieve the file using a Jersey restful web service.

The file upload component of rich faces supports two modes of uploading.
  1. To store the uploaded file in a temporary directory or
  2. To keep an in memory representation of it.
I will be explaining about how to use the latter one the reason being that  as we are going to store files in the database there's no point in creating temporary files.

If you want to create temp files then specify the following filter initialization parameter in the web.xml file.
<init-param>
<param-name>createTempFiles</param-name>
<param-value>true</param-value>
</init-param>

But we are going to set it to false.
Following is the filter configuration for richfaces
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>ruby</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
<init-param>
<param-name>createTempFiles</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>maxRequestSize</param-name>
<param-value>10000000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

The relevant code for jsp file is listed below.
<h:form enctype="multipart/form-data">
....
   <h:panelGrid columns="2" columnClasses="top,top">
            <rich:fileUpload fileUploadListener="#{fileUpload.listener}"
              maxFilesQuantity="#{fileUpload.uploadsAvailable}"
                 
                id="upload"
                immediateUpload="#{fileUpload.autoUpload}"
                allowFlash="#{fileUpload.useFlash}">
                <a4j:support event="onuploadcomplete" reRender="info" />
            </rich:fileUpload>
          
            
            <h:panelGroup id="info">
                <rich:panel bodyClass="info">
                    <f:facet name="header">
                        <h:outputText value="Uploaded Files Info" />
                    </f:facet>
                    <h:outputText value="No files currently uploaded"
                        rendered="#{fileUpload.size==0}" />
                    <rich:dataGrid columns="1" value="#{fileUpload.files}"
                        var="file" rowKeyVar="row">
                        <rich:panel bodyClass="rich-laguna-panel-no-header">
                            <h:panelGrid columns="2">
                                <a4j:mediaOutput element="img" mimeType="#{file.mime}"
                                    createContent="#{fileUpload.paint}" value="#{row}"
                                    style="width:100px; height:100px;" cacheable="false">
                                    <f:param value="#{fileUpload.timeStamp}" name="time"/>  
                                </a4j:mediaOutput>
                                <h:panelGrid columns="2">
                                    <h:outputText value="File Name:" />
                                    <h:outputText value="#{file.name}" />
                                    <h:outputText value="File Length(bytes):" />
                                    <h:outputText value="#{file.length}" />
                                </h:panelGrid>
                            </h:panelGrid>
                        </rich:panel>
                    </rich:dataGrid>
                </rich:panel>
                <rich:spacer height="3"/>
                <br />
                <a4j:commandButton action="#{fileUpload.clearUploadData}"
                    reRender="info, upload" value="Clear Uploaded Data"
                    rendered="#{fileUpload.size>0}" />
            </h:panelGroup>
        </h:panelGrid>
  </h:form>

The code for the fileUpload backing bean is mentioned below.
In the code below all the parameters are passed to the DAO class directly i recommend that you use a DTO and pass it instead.

public class FileUploadBacking {

 private ArrayList<filevo> files = new ArrayList<filevo>();
 private int uploadsAvailable = 10;
 private boolean autoUpload = false;
 private boolean useFlash = false; 
 public int getSize() {
  if (getFiles().size() > 0) {
   return getFiles().size();
  } else {
   return 0;
  }
 }


 //used to write in the display pane 

 public void paint(OutputStream stream, Object object) throws IOException {
  stream.write(getFiles().get((Integer) object).getData());
 }

 public void listener(UploadEvent event) throws Exception {
  UploadItem item = event.getUploadItem();
  FileStoreDAO fdao=FileStoreDAO.getInstance();
  FacesContext fctx=FacesContext.getCurrentInstance();
  HttpServletRequest request=(HttpServletRequest)fctx.getExternalContext().getRequest();
  HttpSession session=request.getSession();
  // Call the storeFile method of fileStoreDAO passing it the params. //Create a DTO for such calls
                String result=fdao.storeFile(item.getData(),item.getFileName(),item.getContentType(),session.getAttribute("userID").toString());
   
  if(result.equalsIgnoreCase("success"))
  {
  FileVO fileVO = new FileVO();
                fileVO.setName("your application domain"+" context root"+"rest resource mapping"+item.getFileName());
fileVO.setLength(item.getData().length); 
fileVO.setData(item.getData()); 
else{
   FacesMessage fmsg=new FacesMessage(FacesMessage.SEVERITY_ERROR,"Db error","Some Db error  has occured could not upload your files");
   fctx.addMessage(null, fmsg);
  }

  files.add(fileVO);
  uploadsAvailable--;
}
//clear the data
 public String clearUploadData() {
  for(int i=0;i<files.size();i++){
    
    FileStoreDAO fdao=FileStoreDAO.getInstance();
    fdao.removeData(files.get(i).getFileName());
  }
  files.clear();
  return "success";
 }

//rest of the code

The DAO class for storing,reading or updating files is listed below:-

public class FileStoreDAO {
    
    private FileStoreDAO(){
        
    }
    public static FileStoreDAO getInstance(){
        return new FileStoreDAO();
        
    }
public void removeData(String fileName){
    DBConnection conn = null;
    PreparedStatement pstmt = null;
    Statement stmt=null;
     try{
         conn = new DBConnection();
        stmt = conn.getStatement();
        stmt.executeUpdate("delete from file_store where file_name like '"+fileName+"'");        
     }
     catch (Exception e) {
         
            e.printStackTrace();
            
        }
        finally {
            try {
                if (stmt != null) {
                    stmt.close();

                }
                conn.closeConnection();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        
    } 
    public String storeFile(byte data[],String fileName,String fileType,String userID){
        
        DBConnection conn = null;
        PreparedStatement pstmt = null;
        Statement stmt=null;
        ResultSet rs = null;
        String outcome;
        boolean flag=false;
        try{
            conn = new DBConnection();
            stmt = conn.getStatement();
            ByteArrayInputStream bis=new ByteArrayInputStream(data);
            rs=stmt.executeQuery("Select count(*) from file_store  where file_name like '"+fileName+"'"); 
            if(rs.next()){
                
                if(rs.getInt(1)>0){
                    flag=true;
                }
            }
            rs=null;
            if(flag){
                pstmt=conn.getPreparedStatement("update file_store set file_data=? , file_type=? , user_id=? , file_size=? , mod_date=sysdate() where file_name like ?" );
                pstmt.setAsciiStream(1,(InputStream)bis,data.length);
                pstmt.setString(2,fileType);
                pstmt.setString(3,userID);
                pstmt.setLong(4,data.length);
                pstmt.setString(5,"'"+fileName+"'");
                pstmt.executeUpdate();
                
                
            }
            else{
            pstmt = conn.getPrepareStatement("Insert into file_store (file_name,file_data,file_type,user_id,file_size,mod_date) values (?,?,?,?,?,sysdate())");
            pstmt.setString(1,fileName);
            pstmt.setAsciiStream(2,(InputStream)bis,data.length);
            pstmt.setString(3,fileType);
            pstmt.setString(4,userID);
            pstmt.setLong(5,data.length);
            pstmt.executeUpdate();
            System.out.println("After insert");
            }
        }
        catch (Exception e) {
           
            e.printStackTrace();
            outcome="failure";
            
        }
        finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();

                }
                if (stmt != null) {
                    stmt.close();

                }
                conn.closeConnection();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        outcome="success";
        return outcome;
    }
public FileDTO readFile(String fileName){
        
        DBConnection conn = null;
    Statement stmt = null;
        ResultSet rs = null;
        FileDTO fileDTO=new FileDTO();
        
        try {
            conn = new DBConnection();
String query="Select file_name,file_type,file_size,file_data from file_store where file_name=?";             
            
pstmt = conn.getPrepardedStatement(query);
            pstmt.setString(1,"'"+fileName +"'");
            rs=stmt.executeQuery();
            if(rs.next()){
                fileDTO.setFileData(rs.getAsciiStream("file_data"));
                fileDTO.setMime(rs.getString("file_type"));
                fileDTO.setLength(rs.getLong("file_size"));
                fileDTO.setFileName(rs.getString("file_name"));
                
            }
        }
            catch (Exception e) {
               fileDTO=null;
                e.printStackTrace();
            }
            finally {
                try {
                    if (rs != null) {
                        rs.close();
                    }
                    if (stmt != null) {
                        stmt.close();

                    }
                    conn.closeConnection();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
    }
            return fileDTO;
    }
}
    

Now all we have to do is write the code of the jersey based restful web service and configure the jersey servlet.

The jersey servlet configuration is shown below:-
<servlet>
    <servlet-name>JerseyWebService</servlet-name>
    <servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>
com.blogspot.ramannanda.editor.rest
</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>JerseyWebService</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

The jersey servlet intercepts any call to the resource under /rest.
The code for the resource class is shown below.


@Path("/") 
public class FileResource {
    /**
     * @param filename passed in the get request
     * @returns builds and returns the response
*
**/       
@GET
@Path("/files/{filename}")
@Produces(MediaType.WILDCARD)
public Response returnFileAsStream(@PathParam("filename") String fileName){
FileStoreDAO ftDAO=FileStoreDAO.getInstance();
FileDTO fdto=ftDAO.readFile(fileName);
if(fdto!=null){
String contentType=fdto.getMime();
InputStream is=fdto.getFileData();
return Response.ok(is,contentType).build();
}
else
{
return Response.noContent().build();
}
}
}
The FileResouce class has a mapping of /files/{filename} specified where filename is the path parameter. For example if a call to http://your-domain/yourcontextroot/rest/files/abc.jpg comes the method annotated with the get annotation simply call's the DAO class's readFile method passing it the file name as abc.jpg and get the data as a stream(if the file exists), The method then builds a response and returns it to the client.

Hope this tutorial was helpful