tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Andrew Love (JIRA)" <tapestry-...@jakarta.apache.org>
Subject [jira] Created: (TAPESTRY-631) Foreach doesn't render the nested form components when rewind
Date Tue, 06 Sep 2005 06:45:30 GMT
Foreach doesn't render the nested form components when rewind
-------------------------------------------------------------

         Key: TAPESTRY-631
         URL: http://issues.apache.org/jira/browse/TAPESTRY-631
     Project: Tapestry
        Type: Bug
  Components: Framework  
    Versions: 4.0    
 Environment: Windows 2000, tomcat, hivemind-1.1-beta3, tapestry-4.0-beta5
    Reporter: Andrew Love


when rewind, Foreach doesn't render the nested components, the getSource() method always return
null, so if there are form compenents in it, and a form components after it, exception will
happen.

the error message is like this:
Rewind of form admin/productEdit/productForm expected allocated id #5 to be 'Upload', but
was 'Submit' (requested by component admin/productEdit/$Submit).

Here are the code:
products.html
<title><span jwcid="@Insert" value="message:userList.title"/></title>
<content tag="heading"><span key="productList.heading"/></content>

<!-- Success Messages -->
<span jwcid="@Conditional" condition="ognl:message != null">
    <div class="message">
        <img jwcid="@Any" src="ognl:engine.contextPath+'/images/iconInformation.gif'"
                alt="message:icon.information" class="icon" />
        <span jwcid="@Insert" value="ognl:message" raw="true"/>
    </div>
</span>

<button class="button" onclick="location.href='productEdit.html'"><span key="button.add"/></button>
<button class="button" onclick="location.href='mainMenu.html'"><span key="button.cancel"/></button>

<table jwcid="table@contrib:Table" class="list productList" id="productList"
    rowsClass="ognl:beans.evenOdd.next" row="ognl:row" 
    columns="product.id:id,productName:name, product.price:price, product.description:description"

    source="ognl:listPageOfProducts.list" initialSortColumn="name"
    arrowUpAsset="ognl:assets.upArrow" arrowDownAsset="ognl:assets.downArrow">
    <span jwcid="productNameColumnValue@Block">
        <a jwcid="@DirectLink" listener="listener:edit" parameters="ognl:row.id">
            <span jwcid="@Insert" value="ognl:row.name"/>
        </a>
    </span>
    <tr jwcid="product_priceColumnValue@Block">
        <a jwcid="@Any" href="ognl:+'mailto:'+row.price">
            <span jwcid="@Insert" value="ognl:row.price"/>
        </a>
    </tr>
</table>
	<form jwcid="@Form">

<input class="button" jwcid="@Submit" value="message:button.add" id="add" listener="ognl:listeners.add"

							type="submit" />
<button class="button" onclick="location.href='mainMenu.html'"><span key="button.cancel"/></button>
</form>
<script type="text/javascript">
highlightTableRows("productList");
</script>

products.page

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification
      PUBLIC "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
      "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">

<page-specification class="org.myproduct.webapp.action.ProductList">
    <inject property="productManager" object="spring:productManager" />    
    
    <property name="message"/>
    <property name="row"/>
    <property name="listPageOfProducts"/>
    
    <bean name="evenOdd" class="org.apache.tapestry.bean.EvenOdd"/>
    <asset name="upArrow" path="/images/arrow_up.png"/>
    <asset name="downArrow" path="/images/arrow_down.png"/>
</page-specification>

ProductList.java
package org.myproduct.webapp.action;

import java.util.HashSet;
import java.util.Set;

import net.mlw.vlh.ValueList;
import net.mlw.vlh.ValueListInfo;

import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.event.PageBeginRenderListener;
import org.apache.tapestry.event.PageEvent;
import org.myproduct.model.Image;
import org.myproduct.model.Product;
import org.myproduct.service.ProductManager;

public abstract class ProductList extends BasePage implements PageBeginRenderListener {
    public abstract ProductManager getProductManager();
    public abstract ValueList getListPageOfProducts();
    public abstract void setListPageOfProducts(ValueList products);

    public void pageBeginRender(PageEvent event) {
        setListPageOfProducts(getProductManager().listPage("productList",new ValueListInfo()));
    }

    public void edit(IRequestCycle cycle) { 
        ProductForm nextPage = (ProductForm) cycle.getPage("admin/productEdit");
        Product product=findProduct(cycle);
        initialProduct(product);
        fetchProduct(cycle,product,nextPage);
    }
    
    public void add(IRequestCycle cycle) {
        ProductForm nextPage = (ProductForm) cycle.getPage("admin/productEdit");
        Product product=new Product();
        initialProduct(product);
        fetchProduct(cycle,product,nextPage);
    }
    
    public void detail(IRequestCycle cycle) { 
        ProductForm nextPage = (ProductForm) cycle.getPage("productDetail");
        Product product=findProduct(cycle);
        fetchProduct(cycle,product,nextPage);
    }
    
    private void fetchProduct(IRequestCycle cycle,Product product,ProductForm nextPage){
        nextPage.setProduct(product);
        cycle.activate(nextPage);
    }
    
    private Product findProduct(IRequestCycle cycle){
        Object[] parameters = cycle.getListenerParameters();
        Long id = (Long) parameters[0];
        Product product = getProductManager().getProduct(id);
        if (log.isDebugEnabled()) {
            log.debug("fetching product with id: " + id);
        }
        return product;
    }
    
    private void initialProduct(Product product){
        Set images=product.getImages();
        if(images==null){
            images=new HashSet();
            product.setImages(images);
        }
        images.add(new Image());        
    }
}

productEdit.html

<html>
<head>
  <title><span jwcid="@Insert" value="message:product.detail"/></title>
  <content tag="heading"></content>
</head>
<body jwcid="@Body">
	<!-- Error Messages -->
	<span jwcid="@Conditional" condition="ognl:beans.delegate.hasErrors">
		<div class="error">
			<img jwcid="@Any" 
				src="ognl:engine.contextPath+'/images/iconWarning.gif'" 
				alt="message:icon.warning" class="icon" />
			<span jwcid="@Delegator" delegate="ognl:beans.delegate.firstError" 
				raw="true"> Error Message </span>
		</div>
	</span>
	<!-- Success Messages -->
	<span jwcid="@Conditional" condition="ognl:message != null">
		<div class="message">
			<img jwcid="@Any" 
				src="ognl:engine.contextPath+'/images/iconInformation.gif'" 
				alt="message:icon.information" class="icon" />
			<span jwcid="@Insert" value="ognl:message" raw="true"></span>
		</div>
	</span>
	<div class="separator"></div>
	<form jwcid="productForm@Form" delegate="ognl:beans.delegate" 
		id="productForm">
		<input jwcid="@Hidden" value="ognl:product.id" type="hidden" />
		<table class="detail" cellpadding="10" cellspacing="10">
			<tbody>
				<tr>
				 <td width="45%">
				  <table width="100%">
				   <tr>
					<th><span jwcid="@Insert" value="message:productName"/></th>
					<td>
						<div>
							<input jwcid="@TextField" value="ognl:product.name" 
								type="text" />
						</div>
					</td>
				   </tr>
				<tr>
					<th><span jwcid="@Insert" value="message:product.price"/></th>
					<td>
						<input jwcid="priceField" size="40" type="text" />
					</td>
				</tr>
				<tr>
					<th><span jwcid="@Insert" value="message:product.description"/></th>
					<td>
						<input jwcid="@TextField" size="40" 
							value="ognl:product.description" type="text" />
					</td>
				</tr>
				</table>
				</td>
					
					
				<td>
					<table>
					<tr jwcid="images">
					<td>
					<img jwcid="productImg" />
					<br />
					<input jwcid="@Upload" file="ognl:image.uploadFile" size="50" 
							type="file" />
					</td>
					</tr>
					</table>
						
					</td>
				</tr>
				<tr>
					<td colspan="2">
					
						<input class="button" jwcid="@Submit" 
							value="message:button.save" id="save" 
							listener="ognl:listeners.save" type="submit" />
						<span jwcid="@contrib:FormConditional" 
							condition="ognl:product.name != null">
							<input class="button" jwcid="@Submit" 
								value="message:button.delete" id="delete" 
								listener="ognl:listeners.delete" 
								onclick="form.onsubmit = null" type="submit" />
							<!-- Removed confirm since WebTest can't handle it: ;return confirmDelete('User')
-->
						</span>
						<input class="button" jwcid="@Submit" 
							value="message:button.cancel" id="cancel" 
							listener="ognl:listeners.cancel" 
							onclick="form.onsubmit = null" type="submit" />
					</td>					
				</tr>
			</tbody>
		</table>
	</form>
	<script type="text/javascript"> <span jwcid="@Conditional" 
		condition="ognl:product.name == null"> 
		document.getElementById("name").focus(); </span> <span 
		jwcid="@Conditional" condition="ognl:product.price == null"> 
		document.getElementById("price").focus(); </span> 
		highlightFormElements(); </script>
</body>
</html>

productEdit.page

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE page-specification 
    PUBLIC "-//Apache Software Foundation//Tapestry Specification 4.0//EN" 
    "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd"> 
        
<page-specification class="org.myproduct.webapp.action.ProductForm">
    <inject property="productManager" object="spring:productManager" />
        
    <property name="product"/>


    <bean name="delegate" class="org.myproduct.webapp.action.Validator"/>
	<bean name="priceValidator" class="org.apache.tapestry.valid.NumberValidator">
	    <set name="required" value="true"/>
	    <set name="valueType" value="'float'"/>    
	</bean>

	  <component id="images" type="Foreach">
	    <binding name="source" value="product.images"/>
	    <binding name="value" value="image"/>
	    <binding name="element" value="literal:tr"/>
	  </component>
    <component id="priceField" type="ValidField">
        <binding name="value" value="product.price"/>
        <binding name="validator" value="bean:priceValidator"/>
        <binding name="displayName" value="product.price"/>
    </component>
    <component id="productImg" type="Any">
        <binding name="src" value="asset:productImage"/>
    </component>
	<asset name="productImage" path="ognl:image.url+image.name"/>
</page-specification>

package org.myproduct.webapp.action;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.event.PageBeginRenderListener;
import org.apache.tapestry.event.PageEvent;
import org.apache.tapestry.request.IUploadFile;
import org.myproduct.Constants;
import org.myproduct.model.Image;
import org.myproduct.model.Product;
import org.myproduct.service.ProductManager;


public abstract class ProductForm extends BasePage implements PageBeginRenderListener {
    public abstract ProductManager getProductManager();
    public abstract void setProduct(Product product);
    public abstract Product getProduct();
    public abstract Image getImage();
    
    public void pageBeginRender(PageEvent event) {
        if ((getProduct() == null) && !event.getRequestCycle().isRewinding()) {
            setProduct(new Product());
        } else if (event.getRequestCycle().isRewinding()) { // add
            setProduct(new Product());
        }
    }

    public void cancel(IRequestCycle cycle) {
        if (log.isDebugEnabled()) {
            log.debug("Entering 'cancel' method");
        }

        cycle.activate("admin/products");
    }

    public void delete(IRequestCycle cycle) {
        if (log.isDebugEnabled()) {
            log.debug("entered 'delete' method");
        }

        getProductManager().removeProduct(getProduct().getId());

        ProductList nextPage = (ProductList) cycle.getPage(Constants.AdminProductListPage);
        nextPage.setMessage(getMessage("product.deleted"));
        cycle.activate(nextPage);
    }

    public void save(IRequestCycle cycle) throws IOException {
        if (getValidationDelegate().getHasErrors()) {
            return;
        }

        boolean isNew = (getProduct().getId() == null);
        Product product=getProduct();


        String key = (isNew) ? "product.added" : "product.updated";

        upload(cycle,product);
        
        this.getProductManager().saveProduct(product);
        if (isNew) {
            ProductList nextPage = (ProductList) cycle.getPage(Constants.AdminProductListPage);
            nextPage.setMessage(getMessage(key));
            cycle.activate(nextPage);
        } else {
            ProductForm nextPage = (ProductForm) cycle.getPage(Constants.AdminProductPage);
            nextPage.setMessage(getMessage(key));
            cycle.activate(nextPage); // return to current page
        }
    }
    
    private void upload(IRequestCycle cycle,Product product) throws IOException {
    	
    	Set images=product.getImages();
    	List imagesList=new ArrayList(images);
        // write the file to the filesystem
        // the directory to upload to
        String uploadDir =
            getServletContext().getRealPath("/img") + "/";

        // Create the directory if it doesn't exist
        File dirPath = new File(uploadDir);

        if (!dirPath.exists()) {
            dirPath.mkdirs();
        }
    	for(int i=0;i<imagesList.size();i++){
    		Image image=(Image) imagesList.get(i);    		
            IUploadFile file = image.getUploadFile();            
            if (file == null) {
            	if(image.getId()==null){
            		imagesList.remove(image);
            		i--;
            	}
                continue;
            }
            //retrieve the file data
            InputStream stream = file.getStream();

            int fileSize=(int)file.getSize();
            ByteBuffer bbuffer=ByteBuffer.allocate(fileSize);
            byte[] buffer = new byte[8192];

            int bytesRead = 0;
            while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
            	bbuffer.put(buffer,0,bytesRead);
            }
            stream.close();
            
            //first, store the file to database
            image.setName(file.getFileName());
            image.setFile(bbuffer.array());
            image.setUrl(uploadDir);
            image.setProduct(product);
            
            //write the file to the file specified
            OutputStream bos =
                new FileOutputStream(uploadDir + file.getFileName());

                bos.write(bbuffer.array(), 0, fileSize);

            bos.close();

            //close the stream
    	}   	

    }
}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Mime
View raw message