Using the session does not work, but using the RequestCycle works fine.

Below is how I solved the problem, and it seems to work quite well for
stateless pages.

Thank you for your help.

public class StatelessAjaxSelfUpdatingTimerBehavior extends
AjaxSelfUpdatingTimerBehavior {

        private final static MetaDataKey<Integer> requestIdsSequenceMetaDataKey
= new MetaDataKey<Integer>() {
                private static final long serialVersionUID = 1L;
        };

        static final String GENERATED_IDS_PREFIX = "SASUTB";

        public StatelessAjaxSelfUpdatingTimerBehavior(Duration updateInterval)
{
                super( updateInterval );
        }

        @Override
        public boolean getStatelessHint(@SuppressWarnings( "unused" ) Component
component) {
                return true;
        }

        private static int getRequestNextSequenceValue() {
                Integer currentSequence =
RequestCycle.get().getMetaData( requestIdsSequenceMetaDataKey );
                if( currentSequence == null )
                        currentSequence = 0;
                else
                        currentSequence++;

                RequestCycle.get().setMetaData( requestIdsSequenceMetaDataKey,
currentSequence );

                return currentSequence;
        }

        @Override
        protected void onBind() {
                Object storedMarkupId = getComponent().getMarkupIdImpl();
                if( storedMarkupId == null || storedMarkupId instanceof Integer 
){
                        String markupIdPrefix = "id";
                        if( 
!getComponent().getApplication().usesDeploymentConfig() ){
                                // in non-deployment mode we make the markup id 
include component id
                                // so it is easier to debug
                                markupIdPrefix = getComponent().getId();
                        }

                        String markupIdPostfix = GENERATED_IDS_PREFIX +
Integer.toHexString( getRequestNextSequenceValue() ).toLowerCase();

                        String markupId = markupIdPrefix + markupIdPostfix;

                        getComponent().setMarkupId( markupId );
                }

                super.onBind();
        }
}

On Wed, 2011-09-07 at 21:42 +0300, Martin Grigorov wrote:

> Session#nextSequenceValue() is public and non-final.
> 
> You can override it in YourWebSession to do whatever fits for your
> needs.
> 
> 
> On Wed, Sep 7, 2011 at 9:35 PM, Sylvain Vieujot <[email protected]>
> wrote:
> 
>         On Wed, 2011-09-07 at 10:19 -0700, Igor Vaynberg wrote: 
>         
>         > On Wed, Sep 7, 2011 at 10:11 AM, Sylvain Vieujot 
> <[email protected]> wrote:
>         > > I looked at this code, but it does not really help as it has to 
> bind to an
>         > > event, whilst I am trying to do an auto update component.
>         > >
>         > > I have 2 questions :
>         > >
>         > > 1) Why does the AbstractAjaxBehavior sets the getStatelessHint to 
> false ?
>         > > It seems to me that this "non stateless" hint could be set much 
> lower in the
>         > > classe hierarchy, but I must be missing something.
>         > 
>         > because the behavior itself is stateful. it needs to generate a
>         > callback url to a component, which means it needs a page id - which
>         > means the page has to exist already - which means it cannot be
>         > stateless. it works much the same way as a Link component.
>         
>         But if the page is stateless you should not need the page id,
>         just the page class to create a new instance isn't it ? (that
>         is if the page's components ids are stable - see 2 below)
>         
>         
>         
>         
>         > > 2) The main problem I have is in the component's id generation.
>         > > In Component.getMarkupId, line 1505, we have :
>         > >     final int generatedMarkupId = storedMarkupId instanceof 
> Integer ?
>         > > (Integer)storedMarkupId
>         > > : getSession().nextSequenceValue();
>         > > So on every request, the id changes because of the
>         > > getSession().nextSequenceValue().
>         > > If in the Behaviour's onBind method, the component's id is fixed, 
> then I
>         > > have no problem ... except this is not very clean programming!
>         > 
>         > if you fix the id yourself you have no way to guarantee it is 
> unique.
>         > eg if this is a panel you can have two instances of the panel in the
>         > page, etc. the id itself should not matter much as long as you 
> repaint
>         > the component so its markup id changes to the new value.
>         
>         I agree that fixing the id is not a great idea ;-)
>         But if the id generation could be stable for stateless pages,
>         it would be quite helpful.
>         My behaviour needs to repaint a component on a stateless page
>         (which in the concept is like a stateless version of the clock
>         example
>         http://www.wicket-library.com/wicket-examples/ajax/clock ).
>         
>         In the Component id generation, couldn't we replace
>         getSession().nextSequenceValue() by a new
>         RequestCycle.get().nextSequenceValue() ( like the
>         Page.getAutoIndex(), but we can not use the Page.getAutoIndex
>         here as the page is not yet accessible) ?
>         The ids would then be fixed for 2 instances of the same
>         stateless page ?
>         The ids would be much more stable and we could then have
>         stable callback urls, i.e. stateless behaviours.
>         
>         Would this work ? 
>         
>         
>         > -igor
>         > 
>         > 
>         > >
>         > > public class StatelessAjaxTimerBehavior extends
>         > > AjaxSelfUpdatingTimerBehavior {
>         > >
>         > > public StatelessAjaxTimerBehavior(Duration updateInterval) {
>         > > super( updateInterval );
>         > > }
>         > >
>         > > @Override
>         > > public boolean getStatelessHint(@SuppressWarnings( "unused" ) 
> Component
>         > > component) {
>         > > return true;
>         > > }
>         > >
>         > > @Override
>         > > protected void onBind() {
>         > > getComponent().setMarkupId( "myForcedID" ); // FIXME: This works, 
> but is not
>         > > very clean ... to say the least
>         > > super.onBind();
>         > > }
>         > > }
>         > >
>         > > Is there a recommended way to fix this ?
>         > >
>         > > Thank you,
>         > >
>         > > Sylvain.
>         > >
>         > > On Wed, 2011-09-07 at 08:34 -0700, Igor Vaynberg wrote:
>         > >
>         > > use something like this [1] as a base and build your own timer 
> behavior
>         > >
>         > > [1]
>         > > 
> https://github.com/jolira/wicket-stateless/blob/master/stateless/src/main/java/com/google/code/joliratools/StatelessAjaxEventBehavior.java
>         > >
>         > > -igor
>         > >
>         > >
>         > > On Wed, Sep 7, 2011 at 3:36 AM, Sylvain Vieujot 
> <[email protected]> wrote:
>         > >> Hello,
>         > >>
>         > >> I have a stateless page, and I would like to periodically 
> refresh a
>         > >> section
>         > >> of this page.
>         > >> If I do :
>         > >>
>         > >> add( new MyPanel( "header" )
>         > >>         .setOutputMarkupId( true )
>         > >>         .add( new AjaxSelfUpdatingTimerBehavior( 
> Duration.minutes( 2 ) )
>         > >>       );
>         > >>
>         > >> The page becomes stateless.
>         > >>
>         > >> If in MyPanel, I have :
>         > >> class MyPanel{
>         > >>      ...
>         > >>      @Override
>         > >>      public boolean getStatelessHint(@SuppressWarnings( "unused" 
> )
>         > >> Component
>         > >> component) {
>         > >>           return true;
>         > >>      }
>         > >>      ...
>         > >> }
>         > >>
>         > >> The update does not work as the expected component's HTML id 
> does not
>         > >> remain
>         > >> constant :
>         > >>
>         > >> Wicket.Ajax: Wicket.Ajax.Call.processComponent: Component with id
>         > >> [[header2]] was not found while trying to perform markup update. 
> Make sure
>         > >> you called component.setOutputMarkupId(
>         > > true) on the component whose markup
>         > >> you are trying to update. console.error('Wicket.Ajax: ' + msg);
>         > >> I also tried to use .setVersioned( false ) on both the component 
> and the
>         > >> page, but without success.
>         > >> Is there a way to do this ?
>         > >>
>         > >> Thank you,
>         > >>
>         > >> Sylvain.
>         > >
>         > > 
> ---------------------------------------------------------------------
>         > > To unsubscribe, e-mail: [email protected]
>         > > For additional commands, e-mail: [email protected]
>         > >
>         > >
>         > 
>         > 
> ---------------------------------------------------------------------
>         > To unsubscribe, e-mail: [email protected]
>         > For additional commands, e-mail: [email protected]
>         > 
> 
> 
> 
> 
> 
> 
> 
> -- 
> 
> Martin Grigorov
> jWeekend
> Training, Consulting, Development
> http://jWeekend.com
> 
> 
> 

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to