seam and ice:inputFile component issues
[Logo]
ICEsoft.org Forums: ICEfaces, ICEmobile, ICEpdf
[Search] Search   [Recent Topics] Recent Topics   [Groups] Home Page | www.icefaces.org  [Register] Register  [Login] Login 
seam and ice:inputFile component issues  XML
Forum Index -> JBoss Seam Integration
Author Message
nepveul

Joined: 13/05/2008 00:00:00
Messages: 13
Offline


I am trying to use the ice:inputFile component with a few issues.

I use :

icefaces 1.8.2
jboss 4.2.3
seam 2.2.0.

I started from a basic empty seam-gen project and imported code from the seam-comp-showcase src files.

My results are:

- File gets uploaded OK
- Response from FileUploadServlet is always empty so the upload form disappears after first upload. I need to reload the page for the form to comeback.
- None of the listeners are called. Either the upload listener or the progress listener.

Here is my view:

Code:
 <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                 xmlns:s="http://jboss.com/products/seam/taglib"
                 xmlns:ui="http://java.sun.com/jsf/facelets"
                 xmlns:f="http://java.sun.com/jsf/core"
                 xmlns:h="http://java.sun.com/jsf/html"
                 xmlns:ice="http://www.icesoft.com/icefaces/component"
                 template="layout/template.xhtml">
 
 <ui:define name="body">
 
         <ice:panelGrid id="homePanelGrid" columns="2" columnClasses="leftMenu,leftMenu">
              <img src="img/ICEfaces-logo.gif" alt="Icefaces and Seam: framework demo"/>   
              <ice:panelGroup id="homePanelGroup">
              <form>
              	<ice:inputFile
              		id="inputFileName"
                     progressRender="true"
                        submitOnUpload="postUpload"
                        progressListener="#{inputFileController.fileUploadProgress}"
                        actionListener="#{inputFileController.uploadFile}"
              	/>
              
         		<ice:outputProgress 
         			value="#{inputFileController.fileProgress}"
                     styleClass="uploadProgressBar"
                 />
              	
              
             	<h:messages layout="table"
                     globalOnly="false"
                     showDetail="true"
                     showSummary="false"/>
              </form>
             </ice:panelGroup>
         </ice:panelGrid>
     
 </ui:define> 
 </ui:composition>
 


Here is my controller:
Code:
 package com.mydomain.testupload.action;
 
 import java.io.File;
 import java.io.FileFilter;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EventObject;
 import java.util.List;
 import java.util.Map;
 
 import javax.faces.context.FacesContext;
 import javax.faces.event.ActionEvent;
 
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.Logger;
 import org.jboss.seam.annotations.Name;
 import org.jboss.seam.annotations.Scope;
 import org.jboss.seam.log.Log;
 
 import com.icesoft.faces.component.inputfile.InputFile;
 
 @Scope(ScopeType.SESSION)
 @Name("inputFileController")
 public class SeamInputFileController implements Serializable{
 	@Logger Log log;
 
     // File sizes used to generate formatted label
     public static final long MEGABYTE_LENGTH_BYTES = 1048000l;
     public static final long KILOBYTE_LENGTH_BYTES = 1024l;
 
     // files associated with the current user
     private final List<InputFileData> fileList =
             Collections.synchronizedList(new ArrayList<InputFileData>());
     // latest file uploaded by client
     private InputFileData currentFile;
     // file upload completed percent (Progress)
     private int fileProgress = 10;
     private String parentDirectory="";
 
     /**
      * <p>Action event method which is triggered when a user clicks on the
      * upload file button.  Uploaded files are added to a list so that user have
      * the option to delete them programatically.  Any errors that occurs
      * during the file uploaded are added the messages output.</p>
      *
      * @param event jsf action event.
      */
     public void uploadFile(ActionEvent event) {
     	log.info("SeamInputFileController.uploadFile");
         InputFile inputFile = (InputFile) event.getSource();
         if (inputFile.getStatus() == InputFile.SAVED) {
         	if (this.parentDirectory.equals("")){
         		this.parentDirectory = inputFile.getFile().getParent();
         	}
             // reference our newly updated file for display purposes and
             // added it to our history file list.
             currentFile = new InputFileData(inputFile.getFileInfo());
 
             synchronized (fileList) {
             	if (!listContains(currentFile.getFile().getName())){
             		//only add the file to the list if it isn't already there
             		//fileupload will just update a more recent version of the file
                     fileList.add(currentFile);
             	}
             }
         }
     }
     protected boolean listContains(String fileNm){
     	for (InputFileData ifd: this.fileList){
     		if (ifd.getFileInfo().getFileName().trim().equals(fileNm.trim())){
     			return true;
     		}
     	}
     	return false;
     }
 
     /**
      * <p>This method is bound to the inputFile component and is executed
      * multiple times during the file upload process.  Every call allows
      * the user to finds out what percentage of the file has been uploaded.
      * This progress information can then be used with a progressBar component
      * for user feedback on the file upload progress. </p>
      *
      * @param event holds a InputFile object in its source which can be probed
      *              for the file upload percentage complete.
      */
     public void fileUploadProgress(EventObject event) {
     	log.info("SeamInputFileController.fileUploadProgress");
         InputFile ifile = (InputFile) event.getSource();
         fileProgress = ifile.getFileInfo().getPercent();
     }
 
     /**
      * <p>Allows a user to remove a file from a list of uploaded files.  This
      * methods assumes that a request param "fileName" has been set to a valid
      * file name that the user wishes to remove or delete</p>
      *
      * @param event jsf action event
      */
     public void removeUploadedFile(ActionEvent event) {
         // Get the inventory item ID from the context.
         FacesContext context = FacesContext.getCurrentInstance();
         Map map = context.getExternalContext().getRequestParameterMap();
         String fileName = (String) map.get("fileName");
 
         synchronized (fileList) {
             InputFileData inputFileData;
             for (int i = 0; i < fileList.size(); i++) {
                 inputFileData = (InputFileData)fileList.get(i);
                 // remove our file
                 if (inputFileData.getFileInfo().getFileName().equals(fileName)) {
                 	//first remove it from the server
                 	File f = new File(inputFileData.getFile().getAbsolutePath());
    	                if (f.exists()) { 
     	        		f.delete();
    	        	        if (log.isDebugEnabled())log.debug("File "+f.getName()+" is deleted");
     	            }
 
                 	//then remove it from the list
                     fileList.remove(i);
                     break;
                 }
             }
         }
     }
 
     public InputFileData getCurrentFile() {
         return currentFile;
     }
 
     public int getFileProgress() {
         return fileProgress;
     }
 
     public List getFileList() {
         return fileList;
     }
     public void destroy(){
     	log.info("destroying InputfileController");
 	 	try{
 		 	if (this.parentDirectory!=null){
 		        /* remove the files that have been uploaded during this session */
 		  		File[] files = null;
 			    File dir = new File(parentDirectory);
 			    /* use a FileFilter to only get files & not directories */
 			    if (dir!=null){
 			    	FileFilter fileFilter = new FileFilter(){
 			    		public boolean accept(File file){
 			    			return !file.isDirectory();
 			    		}
 			    	};
 			    	files = dir.listFiles(fileFilter);
 			    }
 			    if (files!=null){
 			    	for (int i=0; i< files.length; i++){
 			    		File f = (File)files[i];
 			    		String fname=f.getName();
 			    		if (f.exists()){
 			    			f.delete();
 			    			log.info("\t\tfile: "+fname+" deleted");
 	 		    			if (log.isDebugEnabled())log.debug("file: "+fname+" deleted");
 			    		}
 			    	}
 			    }
 		 	}
 	    } catch(Exception ex) {
 	    	/* no files to delete */
  	    	log.info("uploadDirectory is not set--no files to delete! exception");
  	    	ex.printStackTrace();
 	    } 	
     }
 }


My web.xml:

Code:
 
 <?xml version="1.0" encoding="UTF-8"?>
 <web-app version="2.5"
          xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 
     <!-- Seam (using Icefaces) generated project-->
 
     <!-- listeners required for this application -->
     <listener>
         <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
     </listener>
 
     <listener>
         <listener-class>com.icesoft.faces.util.event.servlet.ContextEventRepeater</listener-class>
     </listener>
 
     <!-- filters -->
     <filter>
         <filter-name>Seam Filter</filter-name>
         <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
     </filter>
 
     <filter-mapping>
         <filter-name>Seam Filter</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
 
     <context-param>
         <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
         <param-value>server</param-value>
     </context-param>
 
     <!-- Facelets development mode (disable in production) -->
     <context-param>
         <param-name>facelets.DEVELOPMENT</param-name>
         <param-value>@debug@</param-value>
     </context-param>
 
     <context-param>
         <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
         <param-value>.xhtml</param-value>
     </context-param>
 
     <context-param>
         <param-name>com.icesoft.faces.actionURLSuffix</param-name>
         <param-value>.seam</param-value>
     </context-param>
 
     <context-param>
         <param-name>com.icesoft.faces.synchronousUpdate</param-name>
         <param-value>false</param-value>
     </context-param>
 
     <context-param>
         <param-name>com.icesoft.faces.doJSFStateManagement</param-name>
 	<param-value>true</param-value>
     </context-param>
 
     <context-param>
         <param-name>org.icesoft.examples.serverClock</param-name>
         <param-value>false</param-value>
     </context-param>
 
     <context-param>
         <param-name>com.icesoft.faces.standardRequestScope</param-name>
         <param-value>true</param-value>
     </context-param>
     <context-param>
             <param-name>com.icesoft.faces.uploadDirectory</param-name>
             <param-value>upload</param-value>
     </context-param>
 
     <!-- servlets -->
     
     
     <!-- file upload Servlet -->
     <servlet>
          <servlet-name>uploadServlet</servlet-name>
          <servlet-class>com.icesoft.faces.component.inputfile.FileUploadServlet</servlet-class>
          <load-on-startup> 1 </load-on-startup>
     </servlet>
         
     
     <servlet>
         <servlet-name>Faces Servlet</servlet-name>
         <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
         <load-on-startup>1</load-on-startup>
     </servlet>
 
     <servlet>
         <servlet-name>Seam Resource Servlet</servlet-name>
         <servlet-class>org.jboss.seam.servlet.ResourceServlet</servlet-class>
     </servlet>
 
     <servlet>
         <servlet-name>Persistent Faces Servlet</servlet-name>
         <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
         <load-on-startup> 1 </load-on-startup>
     </servlet>
     <servlet>
         <servlet-name>Blocking Servlet</servlet-name>
         <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
         <load-on-startup> 1 </load-on-startup>
     </servlet>
 
 
     <!-- servlet mappings -->
     
     
 
     <servlet-mapping>
          <servlet-name>uploadServlet</servlet-name>
          <url-pattern>/uploadHtml</url-pattern>
     </servlet-mapping>    
     
     <servlet-mapping>
         <servlet-name>Persistent Faces Servlet</servlet-name>
         <url-pattern>*.seam</url-pattern>
     </servlet-mapping>
 
      <servlet-mapping>
         <servlet-name>Persistent Faces Servlet</servlet-name>
         <url-pattern>/xmlhttp/*</url-pattern>
     </servlet-mapping>
 
     <!-- Blocking Servlet Mapping -->
     <servlet-mapping>
         <servlet-name>Blocking Servlet</servlet-name>
         <url-pattern>/block/*</url-pattern>
     </servlet-mapping>
 
     <servlet-mapping>
         <servlet-name>Seam Resource Servlet</servlet-name>
         <url-pattern>/seam/resource/*</url-pattern>
     </servlet-mapping>
 
     <security-constraint>
        <display-name>Restrict raw XHTML Documents</display-name>
        <web-resource-collection>
           <web-resource-name>XHTML</web-resource-name>
           <url-pattern>*.xhtml</url-pattern>
        </web-resource-collection>
        <auth-constraint/>
     </security-constraint>
 
    <!-- uncomment <ejb-local-ref> entries when deploying to GlassFish and (optionally) JBoss AS 5 -->
    <!--
    <ejb-local-ref>
       <ejb-ref-name>testupload/AuthenticatorBean/local</ejb-ref-name>
       <ejb-ref-type>Session</ejb-ref-type>
       <local-home/>
       <local>com.mydomain.testupload.action.Authenticator</local>
    </ejb-local-ref>
    -->
 
    <!-- Add entries for each EJB session bean which is also a Seam component (not required on JBoss AS) -->
 
    <persistence-unit-ref>
       <persistence-unit-ref-name>testupload/pu</persistence-unit-ref-name>
       <persistence-unit-name>../testupload.jar#testupload</persistence-unit-name>
       <!-- The relative reference doesn't work on GlassFish. Instead, set the <persistence-unit-name> to "testupload",
            package persistence.xml in the WAR, and add a <jar-file> element in persistence.xml with value "../../testupload.jar".
       <persistence-unit-name>testupload</persistence-unit-name>
       -->
    </persistence-unit-ref>
 
 </web-app>
 


These are basically the only pieces of code I modified from the seam-gen'ed project.

I tested the seam-comp-showcase on the same platform and it works, so I have a hard time understanding what I am doing wrong.

Any help would be much apprecaited.
nepveul

Joined: 13/05/2008 00:00:00
Messages: 13
Offline


Here is the full project less the jar files.
 Filename testupload.zip [Disk] Download
 Description
 Filesize 188 Kbytes
 Downloaded:  127 time(s)

judy.guglielmin

Joined: 20/02/2007 00:00:00
Messages: 1196
Offline


Place an <ice:form> around your panelGrid. This component (most ice components) must be encased within a form.
nepveul

Joined: 13/05/2008 00:00:00
Messages: 13
Offline


Judy, thank you very much for your help. Indeed that was the problem, kinda dumb.

My small test project is not working fine. I tried to incorporate in my main application, but still without any luck.

Tried to find out the main differences between the test app and the main app. In my main app, I am using just-ice.jar instead of icefaces.jar. Upload works in the main app with icefaces.jar, but not with just-ice.jar.

Any idea why it is breaking with just-ice.jar?

Thanks!

Laurent
judy.guglielmin

Joined: 20/02/2007 00:00:00
Messages: 1196
Offline


The major difference between just-ice and icefaces jars is that with just-ice, you allow the standard jsf renderers to render all the h tags. This means that you have pages with all <ice> components on them and other pages with no <ice> tags. The non-ice pages are delegated to the standard jsf renderer. You need to specify the context-param for jsf-delegation (see the (ICEfaces Developer's manual). If you aren't trying to integrate another (non-ICEfaces) library's tags into your application (in which case, you have to be really careful that there are no javascript conflicts as well), then you should just be going with the regular icefaces.jar.
 
Forum Index -> JBoss Seam Integration
Go to:   
Powered by JForum 2.1.7ice © JForum Team