-
1. Re: Anybody made s:upload work in Seam+ICEfaces app?
gus888 Feb 25, 2007 11:07 PM (in response to gus888)Sorry typed wrong tag, s:upload should be s:fileUpload.
-
2. Re: Anybody made s:upload work in Seam+ICEfaces app?
tony.herstell1 Feb 25, 2007 11:12 PM (in response to gus888)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.herstell1 Feb 25, 2007 11:16 PM (in response to gus888)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?
gus888 Mar 5, 2007 10:39 PM (in response to gus888)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?
gus888 Mar 5, 2007 10:57 PM (in response to gus888)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.herstell1 Mar 5, 2007 11:34 PM (in response to gus888)I am glad you found the answer.
-
7. Re: Anybody made s:upload work in Seam+ICEfaces app?
tony.herstell1 Mar 5, 2007 11:35 PM (in response to gus888)Poke about in here if you are using Icefaces....
http://jira.icefaces.org/secure/IssueNavigator.jspa?reset=true&mode=hide&pid=10021&sorter/order=DESC&sorter/field=priority&resolution=-1&component=10012