[jboss-user] [JBoss Seam] - Re: Restrict

tony.herstell@gmail.com do-not-reply at jboss.com
Wed Feb 14 17:33:03 EST 2007


Ugh.. its a bit crappy at the moment...

but here it is:

1. Don't use the progress viewer as that just goes SPLAT (I don't think IceFaces passes to the callback it makes the actual conversationId so you get a "not part of long running conversation" exception.


  | <!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="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>
  | 
  | 

For the backing bean I stole the code from the seamspace example (Who Hoo!)... (well I am not THAT stupid!)

So... add this to your web.xml:


  | 
  |     <!-- Content Servlet -->
  |     
  |     <servlet>
  |         <servlet-name>Content Servlet</servlet-name>
  |         <servlet-class>nz.co.risingstars.content.ContentServlet</servlet-class>
  |     </servlet>
  |     
  |     <servlet-mapping>
  |         <servlet-name>Content Servlet</servlet-name>
  |         <url-pattern>/content/*</url-pattern>
  |     </servlet-mapping>
  |     
  |     <filter>
  |         <filter-name>Seam Servlet Filter</filter-name>
  |         <filter-class>org.jboss.seam.servlet.SeamServletFilter</filter-class>
  |     </filter>
  |     
  |     <filter-mapping>
  |         <filter-name>Seam Servlet Filter</filter-name>
  |         <url-pattern>/content/*</url-pattern>
  |     </filter-mapping>    
  | 
  |     <!-- 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>
  | 
  | 


Now to handle the stuff coming in... here is the code...

with the following hack(s):
action is called when the image is uploaded... since you can't pass back a new state to "go to" you are stuffed for now as moving away from the page screws things up..
I tried adding a  DONE button to the gui that called my "done" routine but thats crashes... so I hack the action success route to call Done Instead (OUCH!)... 
This leaves a transaction incomplete however... HACK!
I then have to quite the browser and run up a new browser (usually) to see the results when I look at my list of xxx's (users or orgs).

Hackity Hackity Hack.

Not long till you get all things going wrong as something barfs over the "hanging" transaction or Hibernate reports a Heap Space error..


  | 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");
  | 	}
  | 
  | }
  | 

It's going to be sorted out in the next IceFaces release of course ;).. It would be nice to hand over the project with all my hack removed to IceFaces and the next release be dependent on all this code working; but thats pretty unlikely... so I asked for an Alpha of their next release asap!

You will notice I do some image manipulation to store a thunbmnail with the main image.. which SEEMS to work (visually), but until I get this stable.. then I don't really know.

I aim to post this complete project to the wiki when its actually working well enough (post some nasty IceFaces bugs)



View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4016698#4016698

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4016698



More information about the jboss-user mailing list