Hi Alexander Thanks a lot for the workaround. It is working without any problems. Hopefully wicket devs will consider making the framework more GAE enabled.
/Murat On Wed, May 5, 2010 at 9:20 AM, Alexander Monakhov <[email protected]> wrote: > Hey. > > I met the same problem when I started to implement my app using Wicket and > GAE. On GAE there is problem with serialization. GAE prohibits to use > replacement substitution, so WIcket's methods like Component#modelChanged() > or Component#modelChanging() cause AccessControlContext. To fix this problem > I extended TabbedPanel class and overwrote some significant methods. Here is > code for you. It works on GAE for my application more then 3 month without > any problem. > > /** > * @author dominity > * > * Implementation of Wicket's {...@link TabbedPanel} that has ability to work > on > * Google App Engine. Currently there is problem with serialization of > model. > * GAE prohibits to use replacement substitution, so any time tab switching > is > * invoked, AccessControlContext is threw. To avoid this behavior > * {...@link Component#setDefaultModelObject(Object)} is overwritten to > * hide {...@link Component#modelChanging()} and > * {...@link Component#modelChanged()} methods invocation before/after model's > * object setting. Also, {...@link TabbedPanel#setSelectedTab(int)} is > overwritten > * to switch from using of {...@link Component#setDefaultModelObject(Object)} > to > * {...@link #setDefModelObject(Object)}. > */ > public class GAETabbedPanel extends TabbedPanel { > > // copy of boolean array from TabbedPanel to avoid serialization > problems on > // GAE > private transient Boolean[] tabsVisibilityCache; > > /** > * @param id > * id of span on markup page > * @param tabs > * list of {...@link ITab}s > * @see TabbedPanel > */ > public GAETabbedPanel( String id, List<ITab> tabs ) { > super( id, tabs ); > > } > > �...@override > public void setSelectedTab( int index ) { > if ( index < 0 || ( index >= getTabs().size() && index > 0 ) ) { > throw new IndexOutOfBoundsException(); > } > > // here is only change in comparison to > TabbedPanel#setSelectedTab(int) > setDefModelObject( new Integer( index ) ); > > final Component component; > > if ( getTabs().size() == 0 || !isTabVisible( index ) ) { > // no tabs or the currently selected tab is not visible > component = new WebMarkupContainer( TAB_PANEL_ID ); > } else { > // show panel from selected tab > ITab tab = getTabs().get( index ); > component = tab.getPanel( TAB_PANEL_ID ); > if ( component == null ) { > throw new WicketRuntimeException( > "ITab.getPanel() returned null. TabbedPanel [" > + getPath() + "] ITab index [" + index + "]" > ); > > } > } > > if ( !component.getId().equals( TAB_PANEL_ID ) ) { > throw new WicketRuntimeException( > "ITab.getPanel() returned a panel with invalid id [" > + component.getId() > + "]. You must always return a panel with id > equal " > + "to the provided panelId parameter. > TabbedPanel [" > + getPath() + "] ITab index [" + index + "]" ); > } > > addOrReplace( component ); > } > > /* duplication of the same method at TabbedPanel class in case of > * setDefaultModelObject(Object) overwriting.*/ > private boolean isTabVisible( int tabIndex ) { > if ( tabsVisibilityCache == null ) { > tabsVisibilityCache = new Boolean[ getTabs().size() ]; > } > > if ( tabsVisibilityCache.length > 0 ) { > Boolean visible = tabsVisibilityCache[ tabIndex ]; > if ( visible == null ) { > visible = getTabs().get( tabIndex ).isVisible(); > tabsVisibilityCache[ tabIndex ] = visible; > } > return visible; > } else { > return false; > } > } > > /** > * It's duplication of {...@link #setDefaultModelObject(Object)} except it > * doesn't invoke {...@link #modelChanging()} and {...@link > #modelChanged()} > * before/after model's object setting. This prevents > * {...@link AccessControlException} is threw during tab switching. > * > * @param object > * The object to set > * @return this > * @see #setDefaultModelObject(Object) > */ > �...@suppresswarnings( "unchecked" ) > public final Component setDefModelObject( final Object object ) { > final IModel<Object> model = (IModel<Object>) getDefaultModel(); > > // Check whether anything can be set at all > if ( model == null ) { > throw new IllegalStateException( > "Attempt to set model object on null model of component: > " > + getPageRelativePath() ); > } > > // Check authorization > if ( !isActionAuthorized( ENABLE ) ) { > throw new UnauthorizedActionException( this, ENABLE ); > } > > // Check whether this will result in an actual change > if ( !getModelComparator().compare( this, object ) ) { > // modelChanging(); > model.setObject( object ); > // modelChanged(); > } > > return this; > } > > } > > Best regards, Alexander. > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
