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.
- To store the uploaded file in a temporary directory or
- 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.
1 2 3 4 | <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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 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:-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @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