Re: Wicket 9 clustered sessions
Hi, >'org.apache.wicket.pageStore.InSessionPageStore' can not be asynchronous yes, pages cannot be stored in the session asynchronously. Same holds for the old HttpSessionDataStore in Wicket 8.x. >Adding this fixes the warning getStoreSettings().setAsynchronous(false); Yes, that's the correct fix. >Might this clustered use-case be common enough to justify adding another >IPageManagerProvider implementation to Wicket with default behavior more >appropriate for clustering? As you've seen, there are many possible combinations for these page stores: https://github.com/apache/wicket/blob/master/wicket-core/src/main/java/org/apache/wicket/DefaultPageManagerProvider.java#L43 I'm not sure which concrete combination would be *the* most appropriate for clustering. Have fun Sven On 20.01.21 18:34, Greb Lindqvist wrote: Overriding #newPersistentStore() should be enough: Thank you for your response. I tried only overriding newPersistentStore() like this setPageManagerProvider(new DefaultPageManagerProvider(this) { @Override protected IPageStore newPersistentStore() { return new InSessionPageStore(20); } }); but get warnings like WARN o.a.w.p.AsynchronousPageStore - Delegated page store 'org.apache.wicket.pageStore.InSessionPageStore' can not be asynchronous Adding this fixes the warning getStoreSettings().setAsynchronous(false); but looking at the DefaultPageManagerProvider chain: RequestPageStore -> CachingPageStore -> SerializingPageStore -> AsynchronousPageStore -> CryptingPageStore -> DiskPageStore CachingPageStore wraps an InSessionPageStore of its own but I'm thinking that is not useful when clustering - especially since I'm using DeflatedJavaSerializer and want it invoked before storing in the session. For clustering, maybe this makes more sense (assuming using something like Spring Session) RequestPageStore -> SerializingPageStore -> CryptingPageStore -> InSessionPageStore It seems like this does what I want but I need to test more. setPageManagerProvider(new DefaultPageManagerProvider(this) { @Override protected IPageStore newPersistentStore() { return new InSessionPageStore(20); } @Override protected IPageStore newCachingStore(IPageStore pageStore) { return pageStore; } @Override protected IPageStore newAsynchronousStore(IPageStore pageStore) { return pageStore; } }); Might this clustered use-case be common enough to justify adding another IPageManagerProvider implementation to Wicket with default behavior more appropriate for clustering? Thanks again On Tue, Jan 19, 2021 at 11:57 AM Sven Meier wrote: Hi, > Is it helpful if I add documentation issues to Wicket Jira? pull-requests are always preferred :P > https://ci.apache.org/projects/wicket/guide/9.x/single.html#_httpsessiondatastore I will take care of this. >For Wicket 9 I'm overriding DefaultPageManagerProvider like below. Is that > a good replacement for my Wicket 8 code? Overriding #newPersistentStore() should be enough: @Override protected IPageStore newPersistentStore() { return new InSessionPageStore(20); } >Wicket alive and well! I've been using it since 1.3 :) Thanks for reporting back. Regards Sven On 19.01.21 16:02, Greb Lindqvist wrote: Hello everyone, I'm updating an application from Wicket 8 to Wicket 9 and see that IDataStore has been removed. I think the documentation needs to be updated here https://ci.apache.org/projects/wicket/guide/9.x/single.html#_httpsessiondatastore Is it helpful if I add documentation issues to Wicket Jira? My application uses https://spring.io/projects/spring-session-data-redis so it can be clustered. My Wicket 8 code is like setSessionStoreProvider(HttpSessionStore::new); setPageManagerProvider(new DefaultPageManagerProvider(this) { @Override protected IDataStore newDataStore() { return new HttpSessionDataStore(getPageManagerContext(), new PageNumberEvictionStrategy(20)); } }); For Wicket 9 I'm overriding DefaultPageManagerProvider like below. Is that a good replacement for my Wicket 8 code? It seems to mostly work but I'm seeing slight weirdness that doesn't happen in Wicket 8. If overriding DefaultPageManagerProvider is the correct approach, it would be helpful to mention it in the migration guide with a pointer to the updated documentation. Thanks to everyone for keeping Wicket alive and well! I've been using it since 1.3 :) setPageManagerProvider(new DefaultPageManagerProvider(this) { @Override public IPageManager get() { IPageStore store = newPersistentStore(); store = newSerializingSt
Re: Wicket 9 clustered sessions
> Overriding #newPersistentStore() should be enough: Thank you for your response. I tried only overriding newPersistentStore() like this setPageManagerProvider(new DefaultPageManagerProvider(this) { @Override protected IPageStore newPersistentStore() { return new InSessionPageStore(20); } }); but get warnings like WARN o.a.w.p.AsynchronousPageStore - Delegated page store 'org.apache.wicket.pageStore.InSessionPageStore' can not be asynchronous Adding this fixes the warning getStoreSettings().setAsynchronous(false); but looking at the DefaultPageManagerProvider chain: RequestPageStore -> CachingPageStore -> SerializingPageStore -> AsynchronousPageStore -> CryptingPageStore -> DiskPageStore CachingPageStore wraps an InSessionPageStore of its own but I'm thinking that is not useful when clustering - especially since I'm using DeflatedJavaSerializer and want it invoked before storing in the session. For clustering, maybe this makes more sense (assuming using something like Spring Session) RequestPageStore -> SerializingPageStore -> CryptingPageStore -> InSessionPageStore It seems like this does what I want but I need to test more. setPageManagerProvider(new DefaultPageManagerProvider(this) { @Override protected IPageStore newPersistentStore() { return new InSessionPageStore(20); } @Override protected IPageStore newCachingStore(IPageStore pageStore) { return pageStore; } @Override protected IPageStore newAsynchronousStore(IPageStore pageStore) { return pageStore; } }); Might this clustered use-case be common enough to justify adding another IPageManagerProvider implementation to Wicket with default behavior more appropriate for clustering? Thanks again On Tue, Jan 19, 2021 at 11:57 AM Sven Meier wrote: > Hi, > > > Is it helpful if I add documentation issues to Wicket Jira? > > pull-requests are always preferred :P > > > > > https://ci.apache.org/projects/wicket/guide/9.x/single.html#_httpsessiondatastore > > > I will take care of this. > > >For Wicket 9 I'm overriding DefaultPageManagerProvider like below. Is > that > > a good replacement for my Wicket 8 code? > > Overriding #newPersistentStore() should be enough: > >@Override >protected IPageStore newPersistentStore() { > return new InSessionPageStore(20); >} > > >Wicket alive and well! I've been using it since 1.3 :) > > Thanks for reporting back. > > Regards > Sven > > On 19.01.21 16:02, Greb Lindqvist wrote: > > Hello everyone, > > > > I'm updating an application from Wicket 8 to Wicket 9 and see that > > IDataStore has been removed. I think the documentation needs to be > updated > > here > > > https://ci.apache.org/projects/wicket/guide/9.x/single.html#_httpsessiondatastore > > Is it helpful if I add documentation issues to Wicket Jira? > > > > My application uses > > https://spring.io/projects/spring-session-data-redis > > so it can be clustered. > > > > My Wicket 8 code is like > > setSessionStoreProvider(HttpSessionStore::new); > > > > setPageManagerProvider(new DefaultPageManagerProvider(this) { > > @Override > > protected IDataStore newDataStore() { > > return new HttpSessionDataStore(getPageManagerContext(), > > new PageNumberEvictionStrategy(20)); > > } > > }); > > > > For Wicket 9 I'm overriding DefaultPageManagerProvider like below. Is > that > > a good replacement for my Wicket 8 code? It seems to mostly work but I'm > > seeing slight weirdness that doesn't happen in Wicket 8. If > > overriding DefaultPageManagerProvider is the correct approach, it would > be > > helpful to mention it in the migration guide with a pointer to the > updated > > documentation. > > > > Thanks to everyone for keeping Wicket alive and well! I've been using it > > since 1.3 :) > > > > setPageManagerProvider(new DefaultPageManagerProvider(this) { > > @Override > > public IPageManager get() > > { > > IPageStore store = newPersistentStore(); > > store = newSerializingStore(store); > > store = newRequestStore(store); > > return new PageManager(store); > > } > > > > @Override > > protected IPageStore newPersistentStore() { > > return new InSessionPageStore(20); > > } > > }); > > > > - > To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org > For additional commands, e-mail: users-h...@wicket.apache.org > >
Re: Checking preconditions/changes in models
Hi Bas, >E.g. do you handle exceptions within the model itself, or with a RequestCycleListener? a requestCycleListener is my preferred solution: - I've used Spring interceptors to wrap all exceptions from the service layer for easier identification of the origin of the problem - check the current handler to differentiate between actions or rendering - in case of actions check targeted component (e.g. use annotations to mark optional components) - in case of rendering you can identify the failing component with Behavior#onException() (utilizing a ThreadLocal) - inspect the stacktrace as last resort - re-render the page and show a feedback message Regards Sven On 20.01.21 09:18, Bas Gooren wrote: Hi Sven, Thank you for your reply. On catching failure “when it happens”: can you explain what that looks like for you? E.g. do you handle exceptions within the model itself, or with a RequestCycleListener? I think the tricky part is handling exceptions thrown by models, unless I guard every call to “getModelObject()” inside my components with a try-catch (so in methods like onConfigure, onClick etc). Met vriendelijke groet, Kind regards, Bas Gooren Op 14 januari 2021 bij 19:18:57, Sven Meier (s...@meiers.net) schreef: Hi Bas, in my experience is is very hard to check every possible failure upfront in preconditions (whether from page or models). There's always a corner-case waiting to hunt you. Therefore I prefer using option 1: catch the failure when it happens. Worked fine for me (most of the time), but maybe not a suitable approach for all kind of applications. Regards Sven On 12.01.21 14:37, Bas Gooren wrote: Hi all, First off: best wishes to everyone for 2021, and that we may all have fun this year building stuff in Wicket! I’m wondering how others implement the following requirement… Suppose a page has a model backed by something stored in the session or database (e.g. an e-commerce basket page or checkout). When the user opens multiple tabs (with different instances of the page), either page can become “outdated” with regards to the actual data. E.g. in Tab A the customer removes a product. When the users then tries to update the quantity of that product in Tab B, it can lead to a variety of runtime exceptions: For example: Basket items are rendered with a repeater; If the # items in the basket changes, rows may reference non-existant items (either by database ID or by list index in the basket rows). This sort of problem appears in various shapes and forms when a page references data that may change independent from the page itself. Over the years I have attempted to fix this in three ways: 1. Catch RTEs/Exceptions and re-render page (works OK); But suppose a ListView is used, this also needs to handle things like IndexOutOfBoundsException (thrown from inside ListItemModel) / EntityNotFoundException / NullPointerException. Feels cluttered and “cleaning up after the fact” instead of preventing the RTE in the first place. 2. Check preconditions in page’s onConfigure(). Mixed results, preconditions not always checked before action is executed (e.g. ajax link click, form submit). So leads to finding more spots to check for preconditions, e.g. Form#process 3. Wrap models with decorating models at the page level that check preconditions; E.g. BasketNotEmptyModel; Usually combined with specialized subclass of Form which manages transaction and commit/rollback Of all these ways I prefer option 3 nowadays, as this is a close to the “root” of the problem as possible: at the point where the data is accessed. Since such models are always caching models (LDM), the overhead is minimal (called once or twice per request). Another advantage is that all components in the page point to the parent model, which means preconditions are always checked for any component on the page. When using JPA we can even do a simple check for the entity “last modified” or version, to ensure that the entity did not change between requests. However, I’m evaluating which variant I will use from now on in projects (to standardize) and am wondering how others handle this. Any input/feedback is highly appreciated! Kind regards, Bas - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: Checking preconditions/changes in models
Hi Sven, Thank you for your reply. On catching failure “when it happens”: can you explain what that looks like for you? E.g. do you handle exceptions within the model itself, or with a RequestCycleListener? I think the tricky part is handling exceptions thrown by models, unless I guard every call to “getModelObject()” inside my components with a try-catch (so in methods like onConfigure, onClick etc). Met vriendelijke groet, Kind regards, Bas Gooren Op 14 januari 2021 bij 19:18:57, Sven Meier (s...@meiers.net) schreef: Hi Bas, in my experience is is very hard to check every possible failure upfront in preconditions (whether from page or models). There's always a corner-case waiting to hunt you. Therefore I prefer using option 1: catch the failure when it happens. Worked fine for me (most of the time), but maybe not a suitable approach for all kind of applications. Regards Sven On 12.01.21 14:37, Bas Gooren wrote: > Hi all, > > First off: best wishes to everyone for 2021, and that we may all have fun > this year building stuff in Wicket! > > I’m wondering how others implement the following requirement… > > Suppose a page has a model backed by something stored in the session or > database (e.g. an e-commerce basket page or checkout). > When the user opens multiple tabs (with different instances of the page), > either page can become “outdated” with regards to the actual data. > > E.g. in Tab A the customer removes a product. > > When the users then tries to update the quantity of that product in Tab B, > it can lead to a variety of runtime exceptions: > For example: Basket items are rendered with a repeater; If the # items in > the basket changes, rows may reference non-existant items (either by > database ID or by list index in the basket rows). > > This sort of problem appears in various shapes and forms when a page > references data that may change independent from the page itself. > > Over the years I have attempted to fix this in three ways: > > 1. Catch RTEs/Exceptions and re-render page (works OK); But suppose a > ListView is used, this also needs to handle things like > IndexOutOfBoundsException (thrown from inside ListItemModel) / > EntityNotFoundException / NullPointerException. Feels cluttered and > “cleaning up after the fact” instead of preventing the RTE in the first > place. > 2. Check preconditions in page’s onConfigure(). Mixed results, > preconditions not always checked before action is executed (e.g. ajax link > click, form submit). So leads to finding more spots to check for > preconditions, e.g. Form#process > 3. Wrap models with decorating models at the page level that check > preconditions; E.g. BasketNotEmptyModel; Usually combined with specialized > subclass of Form which manages transaction and commit/rollback > > Of all these ways I prefer option 3 nowadays, as this is a close to the > “root” of the problem as possible: at the point where the data is accessed. > Since such models are always caching models (LDM), the overhead is minimal > (called once or twice per request). > Another advantage is that all components in the page point to the parent > model, which means preconditions are always checked for any component on > the page. > > When using JPA we can even do a simple check for the entity “last modified” > or version, to ensure that the entity did not change between requests. > > However, I’m evaluating which variant I will use from now on in projects > (to standardize) and am wondering how others handle this. > > Any input/feedback is highly appreciated! > > Kind regards, > > Bas > - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org