You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Leszek Gawron <lg...@apache.org> on 2007/08/14 16:43:33 UTC

how to indicate a model changed when item has been removed?

Hello,
let me outline a problem I have. If you won't get much from my ramblings 
I'll try to provide a simplified ready-to-run example:

I have a list of "thermometers":
	
> 	public ThermometersPanel( String id, IModel model ) {
> 		super( id, model );
> 
> 		add( new RefreshingView( "list", new PropertyModel( getModel(), "thermometers" ) ) {
> 			@SuppressWarnings("unchecked")
> 			@Override
> 			protected Iterator getItemModels() {
> 				System.out.println( "get item models called" );
> 				Map<Integer, Thermometer> thermometers = (Map<Integer, Thermometer>) getModelObject();
> 				return new ModelIteratorAdapter( thermometers.values().iterator() ) {
> 					@Override
> 					protected IModel model( Object obj ) {
> 						return new ThermometerModel( (Thermometer) obj );
> 					}
> 				};
> 			}
> 
> 			@Override
> 			protected void populateItem( final Item item ) {
> 				item.add( new Link( "edit", item.getModel() ) {
> 					@Override
> 					public void onClick() {
> 						setResponsePage( new ThermometerPage( getModel(), getPage() ) );
> 					}
> 				}.add( new Label( "name", new PropertyModel( item.getModel(), "name" ) ) ) );
> 				item.add( new ThermometerSensorPanel( "lowLevelSensorPanel", new PropertyModel( item.getModel(),
> 								"lowLevelSensor" ), new ResourceModel( "lowLevelActions" ) ) );
> 				item.add( new ThermometerSensorPanel( "highLevelSensorPanel", new PropertyModel( item.getModel(),
> 								"highLevelSensor" ), new ResourceModel( "highLevelActions" ) ) );
> 			}
> 		} );
> 	}

All models are loadable detachable (hibernate based), storing only 
entity id.

The most important part here is:
> 				item.add( new Link( "edit", item.getModel() ) {
> 					@Override
> 					public void onClick() {
> 						setResponsePage( new ThermometerPage( getModel(), getPage() ) );
> 					}
> 				}.add( new Label( "name", new PropertyModel( item.getModel(), "name" ) ) ) );

Here, when "edit" clicked I would like to show edit page and after 
submission return to the list. So ThermometerPage gets currentPage as 
parameter.

Unfortunately one of edit operations in ThermometerPage is delete:

> Button deleteButton = new Button( "delete", new ResourceModel( "delete" ) ) {
> 	@Override
> 	public void onSubmit() {
> 		UnitConfig unitConfig = unitConfigService.getCurrentUnitConfig( UserUtils.getCurrentUnit() );
> 		unitConfigService.removeThermometer(	unitConfig,
> 												(Thermometer) getForm().getModelObject() );
> 		setResponsePage( ThermometerPage.this.back );
> 	}
> 
> 	@Override
> 	public boolean isEnabled() {
> 		return ( (Thermometer) getForm().getModelObject() ).getId() != null;
> 	}
> };
> deleteButton.setDefaultFormProcessing( false );
> this.add( deleteButton );

When I click delete button this throws:
> org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.mobilebox.indigo.model.Thermometer#5]
>      at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:377)
>      at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:79)
>      at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:68)
>      at org.hibernate.Hibernate.initialize(Hibernate.java:306)
>      at org.springframework.orm.hibernate3.HibernateTemplate.initialize(HibernateTemplate.java:590)
>      at com.mobilebox.persistence.GenericHibernateDaoSupport.findById(GenericHibernateDaoSupport.java:53)
>      at com.mobilebox.indigo.service.impl.UnitConfigServiceImpl.findThermometerById(UnitConfigServiceImpl.java:165)
>      at java.lang.reflect.Method.invoke(Unknown Source)
>      at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)
>      at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)
>      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
>      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
>      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
>      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
>      at $Proxy32.findThermometerById(Unknown Source)
>      at java.lang.reflect.Method.invoke(Unknown Source)
>      at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:402)
>      at org.apache.wicket.proxy.$Proxy43.findThermometerById(Unknown Source)
>      at com.mobilebox.indigo.configurator.model.ThermometerModel.loadEntity(ThermometerModel.java:51)
>      at com.mobilebox.indigo.configurator.model.ThermometerModel.loadEntity(ThermometerModel.java:1)
>      at com.mobilebox.indigo.common.model.PersistentEntityModel.load(PersistentEntityModel.java:56)
>      at com.mobilebox.indigo.common.model.PersistentEntityModel.load(PersistentEntityModel.java:1)
>      at org.apache.wicket.model.LoadableDetachableModel.getObject(LoadableDetachableModel.java:111)
>      at org.apache.wicket.model.AbstractPropertyModel.getTarget(AbstractPropertyModel.java:186)
>      at org.apache.wicket.model.AbstractPropertyModel.getObject(AbstractPropertyModel.java:107)
>      at org.apache.wicket.Component.getModelObject(Component.java:1293)
>      at com.mobilebox.indigo.configurator.panel.thermometer.ThermometersPanel$ThermometerSensorPanel.isVisible(ThermometersPanel.java:84)
 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

the underlined panel is list item's child (see first code snippet)

which clearly mean the list of thermometers hasn't been updated and now 
one of thermometer models references an entity that does not exist anymore.

How can I inform the page I am returning to that it's model is no longer 
valid? Why doesn't the RefreshingView simply refresh itself from the model?

Please advise.

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: how to indicate a model changed when item has been removed?

Posted by Leszek Gawron <lg...@apache.org>.
Igor Vaynberg wrote:
> yeah, thats pretty interesting, what does that panel look like? are you
> using the latest 1.3 trunk?

Yes i have just tried latest trunk - the same.

Here goes the full code:
> public class ThermometersPanel extends Panel {
> 	@SpringBean
> 	protected UnitConfigService	unitConfigService;
> 
> 	private class ThermometerSensorPanel extends Panel {
> 		private class ThermometerSensorActionHandler implements ActionHandler {
> 			public ThermometerSensorActionHandler() {
> 			}
> 
> 			@Override
> 			public void delete( Action action ) {
> 				TemperatureSensor sensor = (TemperatureSensor) getModelObject();
> 				sensor.removeAction( action );
> 				// TODO czemu to nie jest kaskada?
> 				unitConfigService.makePersistent( sensor );
> 				unitConfigService.makeTransient( action );
> 			}
> 
> 			@Override
> 			public void save( Action action ) {
> 				TemperatureSensor sensor = (TemperatureSensor) getModelObject();
> 				if ( action.getId() == null ) {
> 					sensor.addAction( action );
> 					unitConfigService.makePersistent( sensor );
> 				} else
> 					unitConfigService.makePersistent( action );
> 			}
> 		}
> 
> 		public ThermometerSensorPanel( String id, IModel model, IModel captionModel ) {
> 			super( id, model );
> 			add( new ActionsPanel( "actions", new PropertyModel( getModel(), "actions" ), captionModel,
> 							new ThermometerSensorActionHandler() ) );
> 		}
> 
> 		@Override
> 		public boolean isVisible() {

this throws:

> 			return ( (TemperatureSensor) getModelObject() ).isLevelEnabled();
> 		}
> 	}
> 
> 	public ThermometersPanel( String id, IModel model ) {
> 		super( id, model );
> 
> 		add( new Link( "add", getModel() ) {
> 			@Override
> 			public void onClick() {
> 				setResponsePage( new ThermometerPage( new ThermometerModel( (Long) null ), getPage() ) );
> 			}
> 
> 			@Override
> 			public boolean isVisible() {
> 				return ( unitConfigService.getAvailableThermometerSlots( (UnitConfig) getModelObject() ).size() > 0 );
> 			}
> 		} );
> 
> 		add( new RefreshingView( "list", new PropertyModel( getModel(), "thermometers" ) ) {
> 			@SuppressWarnings("unchecked")
> 			@Override
> 			protected Iterator getItemModels() {
> 				System.out.println( "get item models called" );
> 				Map<Integer, Thermometer> thermometers = (Map<Integer, Thermometer>) getModelObject();
> 				return new ModelIteratorAdapter( thermometers.values().iterator() ) {
> 					@Override
> 					protected IModel model( Object obj ) {
> 						return new ThermometerModel( (Thermometer) obj );
> 					}
> 				};
> 			}
> 
> 			@Override
> 			protected void populateItem( final Item item ) {
> 				item.add( new Link( "edit", item.getModel() ) {
> 					@Override
> 					public void onClick() {
> 						setResponsePage( new ThermometerPage( getModel(), getPage() ) );
> 					}
> 				}.add( new Label( "name", new PropertyModel( item.getModel(), "name" ) ) ) );
> 				item.add( new Link( "delete", item.getModel() ) {
> 					@Override
> 					public void onClick() {
> 						UnitConfig unitConfig = unitConfigService.getCurrentUnitConfig( UserUtils.getCurrentUnit() );
> 						unitConfigService.removeThermometer(	unitConfig,
> 																(Thermometer) getModelObject() );
> 					}
> 				} );
> 				item.add( new ThermometerSensorPanel( "lowLevelSensorPanel", new PropertyModel( item.getModel(),
> 								"lowLevelSensor" ), new ResourceModel( "lowLevelActions" ) ) );
> 				item.add( new ThermometerSensorPanel( "highLevelSensorPanel", new PropertyModel( item.getModel(),
> 								"highLevelSensor" ), new ResourceModel( "highLevelActions" ) ) );
> 			}
> 		} );
> 	}
> }

> public class ActionsPanel extends Panel {
> 	public ActionsPanel( String id, IModel model, IModel captionModel, final ActionHandler handler ) {
> 		super( id, model );
> 		add( new Label( "caption", captionModel ) );
> 		add( new Link( "add", getModel() ) {
> 			@Override
> 			public void onClick() {
> 				setResponsePage( new ActionPage( new ActionModel( (Long) null ), handler, getPage() ) );
> 			}
> 
> 			@SuppressWarnings("unchecked")
> 			@Override
> 			public boolean isVisible() {
> 				Set<Action> actions = (Set<Action>) getModelObject();
> 				return actions.size() < ActionListSerializer.MAX_PER_PAGE_ACTION_COUNT;
> 			}
> 
> 		} );
> 
> 		add( new RefreshingView( "list", getModel() ) {
> 			@SuppressWarnings("unchecked")
> 			@Override
> 			protected Iterator getItemModels() {
> 				Set<Action> actions = (Set<Action>) getModelObject();
> 				return new ModelIteratorAdapter( actions.iterator() ) {
> 					@Override
> 					protected IModel model( Object object ) {
> 						return new ActionModel( (Action) object );
> 					}
> 				};
> 			}
> 
> 			@Override
> 			protected void populateItem( Item item ) {
> 				item.add( new Label( "name", new PropertyModel( item.getModel(), "actionDefinition.name" ) ) );
> 				item.add( new Link( "delete", item.getModel() ) {
> 					@Override
> 					public void onClick() {
> 						handler.delete( (Action) getModelObject() );
> 					}
> 				} );
> 			}
> 		} );
> 	}
> }


The model looks like this:

unitconfig -> thermometers
each thermometer is being wrapped with loadable detachable thermometer 
model which holds its   id

thermometer -> lowlevelsensor

lowlevelsensor -> actions

each action wrapped with loadable detachable action model

everything is based on property models apart from building refreshing 
list elements which do not need parent model.

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: how to indicate a model changed when item has been removed?

Posted by Igor Vaynberg <ig...@gmail.com>.
yeah, thats pretty interesting, what does that panel look like? are you
using the latest 1.3 trunk?

-igor


On 8/16/07, Leszek Gawron <lg...@apache.org> wrote:
>
> Leszek Gawron wrote:
> > Igor,
> >
> > Igor Vaynberg wrote:
> >> sounds like you are caching the list inside model returned by new
> >> PropertyModel( getModel(), "thermometers") getModel() there.
> >
> > This is not the case. the thermometer is removed from parent entity and
> > the parent itself is being persisted, so memory model is in sync with
> > database.
> >
> > If I remove child panels from list then everything works fine. If the
> > list was cached as you suggest then even after removal the return page
> > would show the removed thermometer, which it does not.
> >
> It looks like this:
>
> - query for thermometers' list page
> - RefreshingView.getItemModels() called
> - show page
> - click edit on some thermometer
> - page with form shown
> - click delete
> - RefreshingView.getItemModels() !NOT! called
> - exception in list child panel
>    ThermometersPanel$ThermometerSensorPanel.isVisible
>
> why isn't thermometers list refreshed first?
>
>
> when I remove child panels this happens:
> - query for thermometers' list page
> - RefreshingView.getItemModels() called
> - show page
> - click edit on some thermometer
> - page with form shown
> - click delete
> - RefreshingView.getItemModels() called
> - page shown
>
> --
> Leszek Gawron
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

Re: how to indicate a model changed when item has been removed?

Posted by Leszek Gawron <lg...@apache.org>.
Leszek Gawron wrote:
> Igor,
> 
> Igor Vaynberg wrote:
>> sounds like you are caching the list inside model returned by new
>> PropertyModel( getModel(), "thermometers") getModel() there.
> 
> This is not the case. the thermometer is removed from parent entity and 
> the parent itself is being persisted, so memory model is in sync with 
> database.
> 
> If I remove child panels from list then everything works fine. If the 
> list was cached as you suggest then even after removal the return page 
> would show the removed thermometer, which it does not.
> 
It looks like this:

- query for thermometers' list page
- RefreshingView.getItemModels() called
- show page
- click edit on some thermometer
- page with form shown
- click delete
- RefreshingView.getItemModels() !NOT! called
- exception in list child panel
   ThermometersPanel$ThermometerSensorPanel.isVisible

why isn't thermometers list refreshed first?


when I remove child panels this happens:
- query for thermometers' list page
- RefreshingView.getItemModels() called
- show page
- click edit on some thermometer
- page with form shown
- click delete
- RefreshingView.getItemModels() called
- page shown

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: how to indicate a model changed when item has been removed?

Posted by Leszek Gawron <lg...@apache.org>.
Igor,

Igor Vaynberg wrote:
> sounds like you are caching the list inside model returned by new
> PropertyModel( getModel(), "thermometers") getModel() there.

This is not the case. the thermometer is removed from parent entity and 
the parent itself is being persisted, so memory model is in sync with 
database.

If I remove child panels from list then everything works fine. If the 
list was cached as you suggest then even after removal the return page 
would show the removed thermometer, which it does not.

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: how to indicate a model changed when item has been removed?

Posted by Igor Vaynberg <ig...@gmail.com>.
sounds like you are caching the list inside model returned by new
PropertyModel( getModel(), "thermometers") getModel() there.

-igor


On 8/14/07, Leszek Gawron <lg...@apache.org> wrote:
>
> Leszek Gawron wrote:
> > Hello,
> > let me outline a problem I have. If you won't get much from my ramblings
> > I'll try to provide a simplified ready-to-run example:
> a small follow up:
>
> commenting out child panels:
>
> >               add( new RefreshingView( "list", new PropertyModel(
> getModel(), "thermometers" ) ) {
> >                       @SuppressWarnings("unchecked")
> >                       @Override
> >                       protected Iterator getItemModels() {
> >                               System.out.println( "get item models
> called" );
> >                               Map<Integer, Thermometer> thermometers =
> (Map<Integer, Thermometer>) getModelObject();
> >                               return new ModelIteratorAdapter(
> thermometers.values().iterator() ) {
> >                                       @Override
> >                                       protected IModel model( Object obj
> ) {
> >                                               return new
> ThermometerModel( (Thermometer) obj );
> >                                       }
> >                               };
> >                       }
> >
> >                       @Override
> >                       protected void populateItem( final Item item ) {
> >                               item.add( new Link( "edit", item.getModel()
> ) {
> >                                       @Override
> >                                       public void onClick() {
> >                                               setResponsePage( new
> ThermometerPage( getModel(), getPage() ) );
> >                                       }
> >                               }.add( new Label( "name", new
> PropertyModel( item.getModel(), "name" ) ) ) );
> > //                            item.add( new ThermometerSensorPanel(
> "lowLevelSensorPanel", new PropertyModel( item.getModel(),
> >
> //                                                            "lowLevelSensor"
> ), new ResourceModel( "lowLevelActions" ) ) );
> > //                            item.add( new ThermometerSensorPanel(
> "highLevelSensorPanel", new PropertyModel( item.getModel(),
> >
> //                                                            "highLevelSensor"
> ), new ResourceModel( "highLevelActions" ) ) );
> >                       }
> >               } );
>
> makes the list work as expected. I do not get it.
>
> --
> Leszek Gawron
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>

Re: how to indicate a model changed when item has been removed?

Posted by Leszek Gawron <lg...@apache.org>.
Leszek Gawron wrote:
> Hello,
> let me outline a problem I have. If you won't get much from my ramblings 
> I'll try to provide a simplified ready-to-run example:
a small follow up:

commenting out child panels:

> 		add( new RefreshingView( "list", new PropertyModel( getModel(), "thermometers" ) ) {
> 			@SuppressWarnings("unchecked")
> 			@Override
> 			protected Iterator getItemModels() {
> 				System.out.println( "get item models called" );
> 				Map<Integer, Thermometer> thermometers = (Map<Integer, Thermometer>) getModelObject();
> 				return new ModelIteratorAdapter( thermometers.values().iterator() ) {
> 					@Override
> 					protected IModel model( Object obj ) {
> 						return new ThermometerModel( (Thermometer) obj );
> 					}
> 				};
> 			}
> 
> 			@Override
> 			protected void populateItem( final Item item ) {
> 				item.add( new Link( "edit", item.getModel() ) {
> 					@Override
> 					public void onClick() {
> 						setResponsePage( new ThermometerPage( getModel(), getPage() ) );
> 					}
> 				}.add( new Label( "name", new PropertyModel( item.getModel(), "name" ) ) ) );
> //				item.add( new ThermometerSensorPanel( "lowLevelSensorPanel", new PropertyModel( item.getModel(),
> //								"lowLevelSensor" ), new ResourceModel( "lowLevelActions" ) ) );
> //				item.add( new ThermometerSensorPanel( "highLevelSensorPanel", new PropertyModel( item.getModel(),
> //								"highLevelSensor" ), new ResourceModel( "highLevelActions" ) ) );
> 			}
> 		} );

makes the list work as expected. I do not get it.

-- 
Leszek Gawron

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org