7 Replies Latest reply on Mar 5, 2007 11:35 PM by Tony Herstell

    Anybody made s:upload work in Seam+ICEfaces app?

    Gus Gu Expert

      Hi all,

      Did anybody make s:upload work in the Seam+ICEfaces application? I always got a null value of the uploaded byte[] data? Any help is appreciative! Thanks.

        • 1. Re: Anybody made s:upload work in Seam+ICEfaces app?
          Gus Gu Expert

          Sorry typed wrong tag, s:upload should be s:fileUpload.

          • 2. Re: Anybody made s:upload work in Seam+ICEfaces app?
            Tony Herstell Master

            Yes I did.
            There is a bug (in JIRA) with IceFaces upload when it tries to talk to the progress bar so don't use a progress bar).

            I can get images uploaded but cant get it working with seam @End annotations yet.. there are a few things to finish on IceFaces...

            I do callbacks to "parental" stateful session beans to pass them an updated child.

            A "bit" of this was cribbed from the seamspace app.


            Ignore the "Done" button below

            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml"
             xmlns:h="http://java.sun.com/jsf/html"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns:ice="http://www.icesoft.com/icefaces/component">
             <head>
             <meta http-equiv="Content-Type"
             content="text/html; charset=iso-8859-1" />
             <link rel="stylesheet" type="text/css" href="./css/risingstars.css" />
             <link rel="stylesheet" type="text/css" href="./xmlhttp/css/xp/xp.css" />
             <title>Upload</title>
             </head>
             <body>
            
             <ui:composition xmlns="http://www.w3.org/1999/xhtml"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:h="http://java.sun.com/jsf/html"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:s="http://jboss.com/products/seam/taglib"
             xmlns:ice="http://www.icesoft.com/icefaces/component"
             template="/WEB-INF/pages/template.xhtml">
            
             <!-- content -->
             <ui:define name="title">
             <ice:outputText value="#{messages.form_upload}" />
             </ui:define>
             <ui:define name="content">
            
             <ice:form>
             <ice:panelGrid columns="1">
             <fieldset>
             <legend>
             <ice:outputText value="#{messages.fieldset_upload}" />
             </legend>
             <!-- Messages -->
             <ice:panelGrid columns="1">
             <ice:messages infoClass="error" globalOnly="true" />
             </ice:panelGrid>
            
             <ice:panelGrid columns="1">
             <fieldset>
             <legend>
             <ice:outputText value="#{messages.fieldset_upload}"/>
             </legend>
            
             <ice:panelGrid columns="1">
             <ice:inputFile style="border:none; width:400px; height:70px;"
             actionListener="#{uploadController.action}"/> <!-- progressListener="#{uploadController.progress}" -->
             <ice:outputProgress id="progress" value="#{uploadController.percent}"/>
             </ice:panelGrid>
            
             <ice:panelGrid columns="1" width="100%">
             <div align="right">
             <ice:commandButton action="#{uploadController.cancel}"
             value="#{messages.button_cancel}" immediate="true"
             type="submit" />
             <ice:commandButton id="done" type="submit"
             value="#{messages.button_done}" immediate="true"
             action="#{uploadController.done}" />
             </div>
             </ice:panelGrid>
            
             </fieldset>
             </ice:panelGrid>
            
             </fieldset>
             </ice:panelGrid>
             </ice:form>
            
             </ui:define>
             <!-- content -->
             </ui:composition>
            
             </body>
            
            </html>
            


            notice the hack to "jump out" of a conversation below (nasty hack) but have to do this to get to see the images... and it causes real problems later...

            package nz.co.risingstars.actions.upload;
            
            import javax.faces.event.ActionEvent;
            import java.util.EventObject;
            
            /**
             * @author Tony Herstell
             * @version $Revision: 1.3 $ $Date: 2007-02-12 22:28:39 $
             */
            public interface UploadController {
            
             public String startUpload(Object selectedObject);
            
             public void setPercent(int percent);
            
             public int getPercent();
            
             public void action(ActionEvent event);
            
             public void progress(EventObject event);
            
             public String done();
            
             public String cancel();
            
             public void destroy();
            }
            
            
            
            package nz.co.risingstars.actions.upload;
            
            import static javax.persistence.PersistenceContextType.EXTENDED;
            
            import com.icesoft.faces.component.inputfile.InputFile;
            import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
            import com.icesoft.faces.webapp.xmlhttp.RenderingException;
            
            import javax.ejb.Remove;
            import javax.ejb.Stateful;
            import javax.ejb.TransactionAttribute;
            import javax.ejb.TransactionAttributeType;
            import javax.faces.event.ActionEvent;
            import javax.imageio.ImageIO;
            import javax.persistence.EntityManager;
            import javax.persistence.PersistenceContext;
            import javax.swing.ImageIcon;
            
            import nz.co.risingstars.actions.organisation.FindOrganisationController;
            import nz.co.risingstars.actions.user.FindUserController;
            import nz.co.risingstars.entities.Image;
            import nz.co.risingstars.entities.Organisation;
            import nz.co.risingstars.entities.User;
            
            import org.jboss.seam.Component;
            import org.jboss.seam.annotations.Begin;
            import org.jboss.seam.annotations.Conversational;
            import org.jboss.seam.annotations.Destroy;
            import org.jboss.seam.annotations.End;
            import org.jboss.seam.annotations.In;
            import org.jboss.seam.annotations.Logger;
            import org.jboss.seam.annotations.Name;
            import org.jboss.seam.core.Conversation;
            import org.jboss.seam.core.FacesMessages;
            import org.jboss.seam.log.Log;
            
            import java.awt.Graphics2D;
            import java.awt.RenderingHints;
            import java.awt.image.BufferedImage;
            import java.io.BufferedInputStream;
            import java.io.BufferedOutputStream;
            import java.io.ByteArrayOutputStream;
            import java.io.File;
            import java.io.FileInputStream;
            import java.io.IOException;
            import java.io.InputStream;
            import java.io.OutputStream;
            import java.util.EventObject;
            
            /**
             * @author Tony Herstell
             * @version $Revision: 1.4 $ $Date: 2007-02-13 04:46:40 $
             */
            @Stateful
            @Name("uploadController")
            @Conversational
            public class UploadControllerImpl implements UploadController {
            
             /**
             * The maximum width allowed for image rescaling
             */
             private static final int MAX_IMAGE_WIDTH = 1024;
            
             @PersistenceContext(type = EXTENDED)
             private EntityManager em;
            
             @Logger
             private Log log;
            
             @In(required = false)
             private Conversation conversation;
            
             @In(create = true)
             private transient FacesMessages facesMessages;
            
             private enum ParentObjectKind {ORGANISATION, USER};
             private ParentObjectKind parentObjectKind = null;
             private long primaryKey;
            
             private int percent = -1;
             private PersistentFacesState state = null;
            
             private Image image = null;
            
             @Begin
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             public String startUpload(Object selectedObject) {
             log.info("> startUpload");
             String theValueToBeReturned = null;
             state = PersistentFacesState.getInstance();
             if (selectedObject instanceof Organisation) {
             parentObjectKind = ParentObjectKind.ORGANISATION;
             primaryKey = ((Organisation)selectedObject).getId();
             log.info("Organisation Id was =>" + primaryKey);
             theValueToBeReturned = "upload";
             } else if (selectedObject instanceof User) {
             parentObjectKind = ParentObjectKind.USER;
             primaryKey = ((User)selectedObject).getId();
             log.info("User Id was =>" + primaryKey);
             theValueToBeReturned = "upload";
             } else {
             log.error("upload called with object type not supported.");
             }
             logConversation("Upload");
             log.info("< startUpload");
             return theValueToBeReturned;
             }
            
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             public void setPercent(int percent) {
             log.info("> setPercent");
             this.percent = percent;
             log.info("< setPercent");
             }
            
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             public int getPercent() {
             log.info("> getPercent");
             log.info("< getPercent");
             return percent;
             }
            
             //@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             @TransactionAttribute(TransactionAttributeType.REQUIRED)
             public void action(ActionEvent event) {
             log.info("> action");
             InputFile inputFile = (InputFile) event.getSource();
             if (inputFile.getStatus() == InputFile.SAVED) {
             String fileName = inputFile.getFileInfo().getFileName();
             String contentType = inputFile.getFileInfo().getContentType();
            
             File file = inputFile.getFile();
             byte[] inputFileAsBytes = getFileAsBytes(file);
            
             // Check if the image needs to be rescaled
             int width = Math.min(MAX_IMAGE_WIDTH, 70);
             ImageIcon icon = new ImageIcon(inputFileAsBytes);
             boolean rescale = false;
             if (width > 0 && width != icon.getIconWidth()) {
             rescale = true;
             }
            
             byte[] inputFileAsThumbnailAsBytes = null;
             // Rescale the image if required
             if (rescale) {
             inputFileAsThumbnailAsBytes = getRescaledImageAsBytes(contentType, width, icon);
             } else {
             inputFileAsThumbnailAsBytes = inputFileAsBytes;
             }
             Image image = (Image)Component.getInstance("image", true);
             image.setName(fileName);
             image.setType(contentType);
             image.setThumbnail(inputFileAsThumbnailAsBytes);
             image.setImage(inputFileAsBytes);
             image.setVersion(0);
             this.image = image;
            
             } else if (inputFile.getStatus() == InputFile.INVALID) {
             inputFile.getFileInfo().getException().printStackTrace();
             } else if (inputFile.getStatus() == InputFile.SIZE_LIMIT_EXCEEDED) {
             inputFile.getFileInfo().getException().printStackTrace();
             } else if (inputFile.getStatus() == InputFile.UNKNOWN_SIZE) {
             inputFile.getFileInfo().getException().printStackTrace();
             }
            done(); // HACK!
             log.info("< action");
             }
            
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             private byte[] getFileAsBytes(File file) {
             byte[] valueToReturn = null;
             log.info("> getAsBytes");
             InputStream in = null;
             OutputStream out = null;
             try {
             in = new BufferedInputStream(new FileInputStream(file));
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             out = new BufferedOutputStream(baos);
            
             final int toRead = 1024;
             byte[] buffy = new byte[toRead];
             int read;
            
             while ((read = in.read(buffy)) != -1) {
             out.write(buffy, 0, read);
             out.flush();
             }
            
             valueToReturn = baos.toByteArray();
            
             } catch (IOException e) {
             throw new IllegalStateException(e.getMessage());
             } finally { // Try to release any resources.
            
             try {
             if (in != null) {
             in.close();
             }
             } catch (IOException ignored) {}
            
             try {
             if (out != null) {
             out.close();
             }
             } catch (IOException ignored) {}
             }
             log.info("< getAsBytes");
             return valueToReturn;
             }
            
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             private byte[] getRescaledImageAsBytes(String contentType , int width, ImageIcon icon) {
             double ratio = (double) width / icon.getIconWidth();
             int height = (int) (icon.getIconHeight() * ratio);
            
             int imageType = "image/png".equals(contentType) ? BufferedImage.TYPE_INT_ARGB
             : BufferedImage.TYPE_INT_RGB;
             BufferedImage bImg = new BufferedImage(width, height, imageType);
             Graphics2D g2d = bImg.createGraphics();
             g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
             RenderingHints.VALUE_INTERPOLATION_BICUBIC);
             g2d.drawImage(icon.getImage(), 0, 0, width, height, null);
             g2d.dispose();
            
             String formatName = "";
             if ("image/png".equalsIgnoreCase(contentType))
             formatName = "png";
             else if ("image/jpeg".equalsIgnoreCase(contentType))
             formatName = "jpeg";
             else if ("image/jpg".equalsIgnoreCase(contentType))
             formatName = "jpg";
             else if ("image/gif".equalsIgnoreCase(contentType))
             formatName = "gif";
            
             ByteArrayOutputStream baos = null;
             OutputStream out = null;
             try {
             baos = new ByteArrayOutputStream();
             out = new BufferedOutputStream(baos);
             try {
             ImageIO.write(bImg, formatName, out);
             } catch (IOException e) {
             e.printStackTrace();
             }
             } finally { // Try to release any resources.
             try {
             if (baos != null) {
             baos.close();
             }
             } catch (IOException ignored) {}
             try {
             if (out != null) {
             out.close();
             }
             } catch (IOException ignored) {}
             }
             return baos.toByteArray();
             }
            
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             public void progress(EventObject event) {
             log.info("> progress");
             InputFile file = (InputFile) event.getSource();
             this.percent = file.getFileInfo().getPercent();
             try {
             if (state != null) {
             state.render();
             } else {
             System.out.println("state is null");
             }
             } catch (RenderingException ee) {
             System.out.println(ee.getMessage());
             }
             log.info("< progress");
             }
            
             //@End
             //@TransactionAttribute(TransactionAttributeType.REQUIRED)
             public String done() {
             log.info("> done");
             String valueToReturn = null;
            
             em.persist(image);
             if (parentObjectKind == ParentObjectKind.ORGANISATION) {
             Organisation organisationToBeUploadedTo = em.find(Organisation.class, primaryKey);
             if (organisationToBeUploadedTo == null) {
             log.warn("Organisation to be Uploaded to is not found." + primaryKey);
             } else {
             organisationToBeUploadedTo.setPicture(image);
             em.persist(organisationToBeUploadedTo);
             em.flush();
             FindOrganisationController findOrganisationController = (FindOrganisationController)Component.getInstance("findOrganisationController", false);
             if (findOrganisationController != null) {
             // We have to inform the Stateful findOrganisationController that one of its children has been updated.
             findOrganisationController.updateOrganisationInExistingList(organisationToBeUploadedTo);
             }
             facesMessages.addFromResourceBundle("organisation_picture_added");
             valueToReturn = "findOrganisation";
             }
             } else if (parentObjectKind == ParentObjectKind.USER) {
             User userToBeUploadedTo = em.find(User.class, primaryKey);
             if (userToBeUploadedTo == null) {
             log.warn("User to be Uploaded to is not found." + primaryKey);
             } else {
             userToBeUploadedTo.setPicture(image);
             em.persist(userToBeUploadedTo);
             em.flush();
             FindUserController findUserController = (FindUserController)Component.getInstance("findUserController", false);
             if (findUserController != null) {
             // We have to inform the Stateful findUserController that one of its children has been updated.
             findUserController.updateUserInExistingList(userToBeUploadedTo);
             }
             facesMessages.addFromResourceBundle("user_picture_added");
             valueToReturn = "findUser";
             }
             } else {
             log.error("done called with object type not supported.");
             }
            
             log.info("< done");
             return valueToReturn;
             }
            
             @End
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             public String cancel() {
             log.info("> cancel");
             String valueToReturn = null;
             if (parentObjectKind == ParentObjectKind.ORGANISATION) {
             valueToReturn = "findOrganisation";
             } else if (parentObjectKind == ParentObjectKind.USER) {
             valueToReturn = "findUser";
             } else {
             log.error("cancel called with object type not supported.");
             }
             log.info("< cancel");
             return valueToReturn;
             }
            
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             private void logConversation(String name) {
             log.info("Starting " + name + " conversation.");
             if (conversation != null) {
             log.info("Conversation. (" + conversation.getId() + ")");
             }
             }
            
             @Remove
             @Destroy
             @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
             public void destroy() {
             log.info("> destroy");
             log.info("< destroy");
             }
            
            }
            
            
            


            • 3. Re: Anybody made s:upload work in Seam+ICEfaces app?
              Tony Herstell Master

              to see the images I go via the servlet (again see seamspace for this).

              (I can also look into the hypersonic database to see the bytes arrive [and cut/paste them to see my database]).

               <ice:dataTable id="organisationsTableComponent" value="#{organisations}" var="the_organisation"
               sortColumn="#{findOrganisationController.sortColumn}"
               sortAscending="#{findOrganisationController.ascending}"
               rows="10">
              
               <ice:column>
               <f:facet name="header">
               <ice:outputText value="#{messages.column_title_image}" />
               </f:facet>
               <ice:graphicImage value="/content/images?id=#{the_organisation.picture.id}" width="70"/>
               </ice:column>
              


              • 4. Re: Anybody made s:upload work in Seam+ICEfaces app?
                Gus Gu Expert

                Hi Tony,

                Thank you very much for your very detailed codes, but I still have a problem with servlet mapping. Could you please share your web.xml and faces-config.xml codes? Thank you!!!

                Gus

                • 5. Re: Anybody made s:upload work in Seam+ICEfaces app?
                  Gus Gu Expert

                  Hi Tony,

                  Oh, I found the solution. I missed the following code in web.xml:

                  <!-- 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-mapping>
                   <servlet-name>uploadServlet</servlet-name>
                   <url-pattern>/uploadHtml</url-pattern>
                   </servlet-mapping>

                  Thank you.

                  • 6. Re: Anybody made s:upload work in Seam+ICEfaces app?
                    Tony Herstell Master

                    I am glad you found the answer.