You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Andrew B <ch...@yahoo.com> on 2005/11/06 22:49:11 UTC

StaleLinkException

Hi,

I am using Tapestry 4. I am getting a StaleLinkError
when I attempt to submit a form. Briefly, the form
consists of invoice details. All the line items are
listed under the invoice, as editable fields. Also,
there is an empty line item at the bottom, and if data
has been entered into those fields, a new LineItem
object is created when the form is submitted, and
appended to the Invoice's LineItems list to be
displayed. The new LineItem fields are properties of a
LineItem object, accessible from Home via its
NewLineItem property.

It works OK for adding one new line item. The form
submits, and re-renders with the new line item shown.
If you try to submit it with a second one, though, it
fails with the StaleLinkException.

The Invoice and LineItem classes are just beans with
properties, so I won't list those.

Page class:

public abstract class Home extends BasePage
{
	private Invoice invoice;
	private LineItem newLineItem;
	private LineItem deletedLineItem;
	
	public LineItem getDeletedLineItem()
	{
		return deletedLineItem;
	}

	public void setDeletedLineItem(LineItem
deletedLineItem)
	{
		this.deletedLineItem = deletedLineItem;
	}

	public abstract IInvoiceDao getInvoiceDao();

	public LineItem getNewLineItem()
	{
		if (newLineItem == null)
			newLineItem = new LineItem();
		return newLineItem;
	}

	public Invoice getInvoice()
	{
		if (invoice == null)
		{
			invoice = new Invoice();
			invoice.setLineItems(new HashSet());
		}
		return invoice;
	}
	
	public void formSubmit(IRequestCycle cycle)
	{
		if (newLineItem.isPopulated())
		{
			invoice.getLineItems().add( newLineItem );
			newLineItem.setInvoice(invoice);
			newLineItem = new LineItem();
		}
		
		if (deletedLineItem != null)
			removeDeletedItem();
	}

	private void removeDeletedItem()
	{
		Iterator it = invoice.getLineItems().iterator();
		while (it.hasNext())
			if ( ((LineItem)it.next()) == deletedLineItem )
			{
				invoice.getLineItems().remove(deletedLineItem);
				deletedLineItem = null;
			}
	}
	public void setNewLineItem(LineItem newLineItem)
	{
		this.newLineItem = newLineItem;
	}
	
}

Home.html:

 <html>
 <form jwcid="invoiceForm">
 	<table>
 		<tr>
 			<td>Amount:</td><td><input type="text"
jwcid="amount" /></td>
 			<td>Order Person:</td><td><input type="text"
jwcid="orderPerson" /><td>
 			<td>Car Number:</td><td><input type="text"
jwcid="carNumber" /></td>
 		</tr>
 	</table>
 	
 	<br/>
 	<b>Line Items</b>
 	<table>
 		<tr>
 			<th>Part Number</th>
 			<th>Quantity</th>
 			<th>Unit Cost</th>
 		</tr>
 		<tr jwcid="lineitems" element="tr">
 			<td><input type="text" jwcid="partNumber"/></td>
 			<td><input type="text" jwcid="quantity"/></td>
 			<td><input type="text" jwcid="unitCost" /></td>
 			<td width="10%"><input type="submit"
jwcid="deleteItem"/></td>
 		</tr>
 		<tr>
 			<td><input type="text"
jwcid="newPartNumber"/></td>
 			<td><input type="text" jwcid="newQuantity"/></td>
 			<td><input type="text" jwcid="newUnitCost" /></td>
 		</tr> 		
 	</table>
 	<input type="submit" value="Save" />
 	
 </form>
</html>


Home.page:

<?xml version="1.0"?>
<!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="com.gett.subbill.Home">
    
    <!-- Invoice input fields -->
    <component id="amount" type="TextField">
        <binding name="value"
value="ognl:invoice.amount" />
    </component>
    
    <component id="invoiceForm" type="Form">
        <binding name="listener"
value="listener:formSubmit" />
    </component>
    
    <component id="orderPerson" type="TextField">
        <binding name="value"
value="ognl:invoice.orderPerson" />
    </component>
    
    <component id="carNumber" type="TextField">
        <binding name="value"
value="ognl:invoice.carNumber" />
    </component>
    
    <!-- Line item loop -->
    <component id="lineitems" type="Foreach">
        <binding name="source"
value="ognl:invoice.lineItems" />
        <binding name="value" value="ognl:item" />
	</component>
    
    <!-- Line item input fields -->
    <component id="partNumber" type="TextField">
        <binding name="value"
value="ognl:item.partNumber" />
    </component>
    
    <component id="quantity" type="TextField">
        <binding name="value"
value="ognl:item.quantity" />
    </component>
    
    <component id="unitCost" type="TextField">
        <binding name="value"
value="ognl:item.unitCost" />
    </component>
    
    <!-- New line item input fields -->
    <component id="newPartNumber" type="TextField">
        <binding name="value"
value="ognl:newLineItem.partNumber" />
    </component>
    
    <component id="newQuantity" type="TextField">
        <binding name="value"
value="ognl:newLineItem.quantity" />
    </component>
    
    <component id="newUnitCost" type="TextField">
        <binding name="value"
value="ognl:newLineItem.unitCost" />
    </component>
    
    <!-- Page properties -->
        
    <property name="item" />
    
    <!-- Delete button -->
    <component id="deleteItem" type="Submit">
        <binding name="selected"
value="ognl:deletedLineItem" />
        <binding name="tag" value="ognl:item" />
        <binding name="label" value="'X'"/>
    </component>
        
 </page-specification>
 
 
 Error message:
 
 You have clicked on a stale link. 
 Rewind of form Home/invoiceForm expected allocated id
#4 to be 'partNumber', but was 'newPartNumber'
(requested by component Home/newPartNumber). 
 
 Viewing the form's HTML just prior to getting the
error shows:
 
  <html>
  <form method="post" action="/SubBill/app"
name="invoiceForm" id="invoiceForm">
 <div><input type="hidden" name="formids"
value="amount,orderPerson,carNumber,partNumber,quantity,unitCost,deleteItem,newPartNumber,newQuantity,newUnitCost"/>
 <input type="hidden" name="component"
value="invoiceForm"/>
 <input type="hidden" name="page" value="Home"/>
 <input type="hidden" name="service" value="direct"/>
 <input type="hidden" name="submitmode" value=""/>
 </div>
  	<table>
  		<tr>
  			<td>Amount:</td><td><input type="text"
name="amount" value="100.0" id="amount"/></td>
  			<td>Order Person:</td><td><input type="text"
name="orderPerson" value="fred" id="orderPerson"/><td>
  			<td>Car Number:</td><td><input type="text"
name="carNumber" value="132" id="carNumber"/></td>
  		</tr>
  	</table>
  	
  	<br/>
  	<b>Line Items</b>
  	<table>
  		<tr>
  			<th>Part Number</th>
  			<th>Quantity</th>
  			<th>Unit Cost</th>
  		</tr>
  		<tr>
  			<td><input type="text" name="partNumber"
value="1234" id="partNumber"/></td>
  			<td><input type="text" name="quantity" value="1"
id="quantity"/></td>
  			<td><input type="text" name="unitCost"
value="10.99" id="unitCost"/></td>
  			<td width="10%"><input type="submit"
name="deleteItem" value="X" id="deleteItem"/></td>
  		</tr>
  		<tr>
  			<td><input type="text" name="newPartNumber"
value="" id="newPartNumber"/></td>
  			<td><input type="text" name="newQuantity"
value="0" id="newQuantity"/></td>
  			<td><input type="text" name="newUnitCost"
value="0.0" id="newUnitCost"/></td>
  		</tr> 		
  	</table>
  	<input type="submit" value="Save" />
  	
  </form>
</html>

It has the first LineItem, as you can see, and the
formids hidden field shows all the ids for the
invoice, the first line item, and the new line item
fields. I don't see how the browser is getting out of
sync with the server. It all looks right to me. What
am I missing?

Thanks in advance,

Andrew



		
__________________________________ 
Yahoo! FareChase: Search multiple travel sites in one click.
http://farechase.yahoo.com

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


Re: StaleLinkException

Posted by Andrew B <ch...@yahoo.com>.
Thanks for your input. I replaced it with 'For' but
that made it blow up on trying to submit the first
line item, not the second :( I must be missing
something really fundamental. Any help is appreciated!

--- Mind Bridge <mi...@yahoo.com> wrote:

> Hi,
> 
> I cannot look at your message in details at the
> moment (perhaps someone 
> else can), but the following stands out:
> 
> <component id="lineitems" type="Foreach">
> 
> Replace 'Foreach' with a 'For'. The 'For' component
> is like 'Foreach'  
> (see doc), but if in a form, it automatically stores
> information about 
> the iterations performed in hidden fields.
> StaleLinkException does not 
> occur as a result upon submission.
> 
> Andrew B wrote:
> > Hi,
> >
> > I am using Tapestry 4. I am getting a
> StaleLinkError
> > when I attempt to submit a form. Briefly, the form
> > consists of invoice details. All the line items
> are
> > listed under the invoice, as editable fields.
> Also,
> > there is an empty line item at the bottom, and if
> data
> > has been entered into those fields, a new LineItem
> > object is created when the form is submitted, and
> > appended to the Invoice's LineItems list to be
> > displayed. The new LineItem fields are properties
> of a
> > LineItem object, accessible from Home via its
> > NewLineItem property.
> >
> > It works OK for adding one new line item. The form
> > submits, and re-renders with the new line item
> shown.
> > If you try to submit it with a second one, though,
> it
> > fails with the StaleLinkException.
> >
> > The Invoice and LineItem classes are just beans
> with
> > properties, so I won't list those.
> >
> > Page class:
> >
> > public abstract class Home extends BasePage
> > {
> > 	private Invoice invoice;
> > 	private LineItem newLineItem;
> > 	private LineItem deletedLineItem;
> > 	
> > 	public LineItem getDeletedLineItem()
> > 	{
> > 		return deletedLineItem;
> > 	}
> >
> > 	public void setDeletedLineItem(LineItem
> > deletedLineItem)
> > 	{
> > 		this.deletedLineItem = deletedLineItem;
> > 	}
> >
> > 	public abstract IInvoiceDao getInvoiceDao();
> >
> > 	public LineItem getNewLineItem()
> > 	{
> > 		if (newLineItem == null)
> > 			newLineItem = new LineItem();
> > 		return newLineItem;
> > 	}
> >
> > 	public Invoice getInvoice()
> > 	{
> > 		if (invoice == null)
> > 		{
> > 			invoice = new Invoice();
> > 			invoice.setLineItems(new HashSet());
> > 		}
> > 		return invoice;
> > 	}
> > 	
> > 	public void formSubmit(IRequestCycle cycle)
> > 	{
> > 		if (newLineItem.isPopulated())
> > 		{
> > 			invoice.getLineItems().add( newLineItem );
> > 			newLineItem.setInvoice(invoice);
> > 			newLineItem = new LineItem();
> > 		}
> > 		
> > 		if (deletedLineItem != null)
> > 			removeDeletedItem();
> > 	}
> >
> > 	private void removeDeletedItem()
> > 	{
> > 		Iterator it = invoice.getLineItems().iterator();
> > 		while (it.hasNext())
> > 			if ( ((LineItem)it.next()) == deletedLineItem )
> > 			{
> > 			
> invoice.getLineItems().remove(deletedLineItem);
> > 				deletedLineItem = null;
> > 			}
> > 	}
> > 	public void setNewLineItem(LineItem newLineItem)
> > 	{
> > 		this.newLineItem = newLineItem;
> > 	}
> > 	
> > }
> >
> > Home.html:
> >
> >  <html>
> >  <form jwcid="invoiceForm">
> >  	<table>
> >  		<tr>
> >  			<td>Amount:</td><td><input type="text"
> > jwcid="amount" /></td>
> >  			<td>Order Person:</td><td><input type="text"
> > jwcid="orderPerson" /><td>
> >  			<td>Car Number:</td><td><input type="text"
> > jwcid="carNumber" /></td>
> >  		</tr>
> >  	</table>
> >  	
> >  	<br/>
> >  	<b>Line Items</b>
> >  	<table>
> >  		<tr>
> >  			<th>Part Number</th>
> >  			<th>Quantity</th>
> >  			<th>Unit Cost</th>
> >  		</tr>
> >  		<tr jwcid="lineitems" element="tr">
> >  			<td><input type="text"
> jwcid="partNumber"/></td>
> >  			<td><input type="text" jwcid="quantity"/></td>
> >  			<td><input type="text" jwcid="unitCost"
> /></td>
> >  			<td width="10%"><input type="submit"
> > jwcid="deleteItem"/></td>
> >  		</tr>
> >  		<tr>
> >  			<td><input type="text"
> > jwcid="newPartNumber"/></td>
> >  			<td><input type="text"
> jwcid="newQuantity"/></td>
> >  			<td><input type="text" jwcid="newUnitCost"
> /></td>
> >  		</tr> 		
> >  	</table>
> >  	<input type="submit" value="Save" />
> >  	
> >  </form>
> > </html>
> >
> >
> > Home.page:
> >
> > <?xml version="1.0"?>
> > <!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="com.gett.subbill.Home">
> >     
> >     <!-- Invoice input fields -->
> >     <component id="amount" type="TextField">
> >         <binding name="value"
> > value="ognl:invoice.amount" />
> >     </component>
> >     
> >     <component id="invoiceForm" type="Form">
> >         <binding name="listener"
> > value="listener:formSubmit" />
> >     </component>
> >     
> >     <component id="orderPerson" type="TextField">
> >         <binding name="value"
> > value="ognl:invoice.orderPerson" />
> >     </component>
> >     
> >     <component id="carNumber" type="TextField">
> >         <binding name="value"
> > value="ognl:invoice.carNumber" />
> >     </component>
> >     
> >     <!-- Line item loop -->
> >     <component id="lineitems" type="Foreach">
> >         <binding name="source"
> > value="ognl:invoice.lineItems" />
> >         <binding name="value" value="ognl:item" />
> > 	</component>
> >     
> 
=== message truncated ===



	
		
__________________________________ 
Yahoo! Mail - PC Magazine Editors' Choice 2005 
http://mail.yahoo.com

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


Re: StaleLinkException

Posted by Mind Bridge <mi...@yahoo.com>.
Hi,

I cannot look at your message in details at the moment (perhaps someone 
else can), but the following stands out:

<component id="lineitems" type="Foreach">

Replace 'Foreach' with a 'For'. The 'For' component is like 'Foreach'  
(see doc), but if in a form, it automatically stores information about 
the iterations performed in hidden fields. StaleLinkException does not 
occur as a result upon submission.

Andrew B wrote:
> Hi,
>
> I am using Tapestry 4. I am getting a StaleLinkError
> when I attempt to submit a form. Briefly, the form
> consists of invoice details. All the line items are
> listed under the invoice, as editable fields. Also,
> there is an empty line item at the bottom, and if data
> has been entered into those fields, a new LineItem
> object is created when the form is submitted, and
> appended to the Invoice's LineItems list to be
> displayed. The new LineItem fields are properties of a
> LineItem object, accessible from Home via its
> NewLineItem property.
>
> It works OK for adding one new line item. The form
> submits, and re-renders with the new line item shown.
> If you try to submit it with a second one, though, it
> fails with the StaleLinkException.
>
> The Invoice and LineItem classes are just beans with
> properties, so I won't list those.
>
> Page class:
>
> public abstract class Home extends BasePage
> {
> 	private Invoice invoice;
> 	private LineItem newLineItem;
> 	private LineItem deletedLineItem;
> 	
> 	public LineItem getDeletedLineItem()
> 	{
> 		return deletedLineItem;
> 	}
>
> 	public void setDeletedLineItem(LineItem
> deletedLineItem)
> 	{
> 		this.deletedLineItem = deletedLineItem;
> 	}
>
> 	public abstract IInvoiceDao getInvoiceDao();
>
> 	public LineItem getNewLineItem()
> 	{
> 		if (newLineItem == null)
> 			newLineItem = new LineItem();
> 		return newLineItem;
> 	}
>
> 	public Invoice getInvoice()
> 	{
> 		if (invoice == null)
> 		{
> 			invoice = new Invoice();
> 			invoice.setLineItems(new HashSet());
> 		}
> 		return invoice;
> 	}
> 	
> 	public void formSubmit(IRequestCycle cycle)
> 	{
> 		if (newLineItem.isPopulated())
> 		{
> 			invoice.getLineItems().add( newLineItem );
> 			newLineItem.setInvoice(invoice);
> 			newLineItem = new LineItem();
> 		}
> 		
> 		if (deletedLineItem != null)
> 			removeDeletedItem();
> 	}
>
> 	private void removeDeletedItem()
> 	{
> 		Iterator it = invoice.getLineItems().iterator();
> 		while (it.hasNext())
> 			if ( ((LineItem)it.next()) == deletedLineItem )
> 			{
> 				invoice.getLineItems().remove(deletedLineItem);
> 				deletedLineItem = null;
> 			}
> 	}
> 	public void setNewLineItem(LineItem newLineItem)
> 	{
> 		this.newLineItem = newLineItem;
> 	}
> 	
> }
>
> Home.html:
>
>  <html>
>  <form jwcid="invoiceForm">
>  	<table>
>  		<tr>
>  			<td>Amount:</td><td><input type="text"
> jwcid="amount" /></td>
>  			<td>Order Person:</td><td><input type="text"
> jwcid="orderPerson" /><td>
>  			<td>Car Number:</td><td><input type="text"
> jwcid="carNumber" /></td>
>  		</tr>
>  	</table>
>  	
>  	<br/>
>  	<b>Line Items</b>
>  	<table>
>  		<tr>
>  			<th>Part Number</th>
>  			<th>Quantity</th>
>  			<th>Unit Cost</th>
>  		</tr>
>  		<tr jwcid="lineitems" element="tr">
>  			<td><input type="text" jwcid="partNumber"/></td>
>  			<td><input type="text" jwcid="quantity"/></td>
>  			<td><input type="text" jwcid="unitCost" /></td>
>  			<td width="10%"><input type="submit"
> jwcid="deleteItem"/></td>
>  		</tr>
>  		<tr>
>  			<td><input type="text"
> jwcid="newPartNumber"/></td>
>  			<td><input type="text" jwcid="newQuantity"/></td>
>  			<td><input type="text" jwcid="newUnitCost" /></td>
>  		</tr> 		
>  	</table>
>  	<input type="submit" value="Save" />
>  	
>  </form>
> </html>
>
>
> Home.page:
>
> <?xml version="1.0"?>
> <!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="com.gett.subbill.Home">
>     
>     <!-- Invoice input fields -->
>     <component id="amount" type="TextField">
>         <binding name="value"
> value="ognl:invoice.amount" />
>     </component>
>     
>     <component id="invoiceForm" type="Form">
>         <binding name="listener"
> value="listener:formSubmit" />
>     </component>
>     
>     <component id="orderPerson" type="TextField">
>         <binding name="value"
> value="ognl:invoice.orderPerson" />
>     </component>
>     
>     <component id="carNumber" type="TextField">
>         <binding name="value"
> value="ognl:invoice.carNumber" />
>     </component>
>     
>     <!-- Line item loop -->
>     <component id="lineitems" type="Foreach">
>         <binding name="source"
> value="ognl:invoice.lineItems" />
>         <binding name="value" value="ognl:item" />
> 	</component>
>     
>     <!-- Line item input fields -->
>     <component id="partNumber" type="TextField">
>         <binding name="value"
> value="ognl:item.partNumber" />
>     </component>
>     
>     <component id="quantity" type="TextField">
>         <binding name="value"
> value="ognl:item.quantity" />
>     </component>
>     
>     <component id="unitCost" type="TextField">
>         <binding name="value"
> value="ognl:item.unitCost" />
>     </component>
>     
>     <!-- New line item input fields -->
>     <component id="newPartNumber" type="TextField">
>         <binding name="value"
> value="ognl:newLineItem.partNumber" />
>     </component>
>     
>     <component id="newQuantity" type="TextField">
>         <binding name="value"
> value="ognl:newLineItem.quantity" />
>     </component>
>     
>     <component id="newUnitCost" type="TextField">
>         <binding name="value"
> value="ognl:newLineItem.unitCost" />
>     </component>
>     
>     <!-- Page properties -->
>         
>     <property name="item" />
>     
>     <!-- Delete button -->
>     <component id="deleteItem" type="Submit">
>         <binding name="selected"
> value="ognl:deletedLineItem" />
>         <binding name="tag" value="ognl:item" />
>         <binding name="label" value="'X'"/>
>     </component>
>         
>  </page-specification>
>  
>  
>  Error message:
>  
>  You have clicked on a stale link. 
>  Rewind of form Home/invoiceForm expected allocated id
> #4 to be 'partNumber', but was 'newPartNumber'
> (requested by component Home/newPartNumber). 
>  
>  Viewing the form's HTML just prior to getting the
> error shows:
>  
>   <html>
>   <form method="post" action="/SubBill/app"
> name="invoiceForm" id="invoiceForm">
>  <div><input type="hidden" name="formids"
> value="amount,orderPerson,carNumber,partNumber,quantity,unitCost,deleteItem,newPartNumber,newQuantity,newUnitCost"/>
>  <input type="hidden" name="component"
> value="invoiceForm"/>
>  <input type="hidden" name="page" value="Home"/>
>  <input type="hidden" name="service" value="direct"/>
>  <input type="hidden" name="submitmode" value=""/>
>  </div>
>   	<table>
>   		<tr>
>   			<td>Amount:</td><td><input type="text"
> name="amount" value="100.0" id="amount"/></td>
>   			<td>Order Person:</td><td><input type="text"
> name="orderPerson" value="fred" id="orderPerson"/><td>
>   			<td>Car Number:</td><td><input type="text"
> name="carNumber" value="132" id="carNumber"/></td>
>   		</tr>
>   	</table>
>   	
>   	<br/>
>   	<b>Line Items</b>
>   	<table>
>   		<tr>
>   			<th>Part Number</th>
>   			<th>Quantity</th>
>   			<th>Unit Cost</th>
>   		</tr>
>   		<tr>
>   			<td><input type="text" name="partNumber"
> value="1234" id="partNumber"/></td>
>   			<td><input type="text" name="quantity" value="1"
> id="quantity"/></td>
>   			<td><input type="text" name="unitCost"
> value="10.99" id="unitCost"/></td>
>   			<td width="10%"><input type="submit"
> name="deleteItem" value="X" id="deleteItem"/></td>
>   		</tr>
>   		<tr>
>   			<td><input type="text" name="newPartNumber"
> value="" id="newPartNumber"/></td>
>   			<td><input type="text" name="newQuantity"
> value="0" id="newQuantity"/></td>
>   			<td><input type="text" name="newUnitCost"
> value="0.0" id="newUnitCost"/></td>
>   		</tr> 		
>   	</table>
>   	<input type="submit" value="Save" />
>   	
>   </form>
> </html>
>
> It has the first LineItem, as you can see, and the
> formids hidden field shows all the ids for the
> invoice, the first line item, and the new line item
> fields. I don't see how the browser is getting out of
> sync with the server. It all looks right to me. What
> am I missing?
>
> Thanks in advance,
>
> Andrew
>
>
>
> 		
> __________________________________ 
> Yahoo! FareChase: Search multiple travel sites in one click.
> http://farechase.yahoo.com
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
>
>
>   

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