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]

Reply via email to