Hi,

I'm glad you are making progress with your adventure!


On Thu, Dec 19, 2013 at 7:40 AM, Steve Coughlan <[email protected]>wrote:

> A few weeks back I made a post about the first version of universal
> expression language for wicket.  Since then it's come quite a way.  The
> initial version hooked into by implementing IMarkupResourceStreamProvider
> for markup owning MarkupContainers (Panel, Page etc...) and by regenerating
> markup fragments for markup receiving MarkupContainers (ListView).
> Unfortunately due to the fact that the EL expressions need to be evaluated
> on every request this meant a huge performance hit (about 75% less than
> standard wicket) due to forcing wicket to constantly parse markup on every
> request cycle.
>
> The current evolution of wicket-el hooks in very differently.  My first
> preference was to create a dynamic version of Markup and MarkupFragment
> that replaces MarkupElements that contain EL expressions with a dynamic
> version.  Unfortuantely this was impossible because I need to subclass
> Markup (wicket uses a few case of 'instanceof Markup') and Markup has many
> final methods.  And simply wrapping all the MarkupElements isn't possible
> because RawMarkup is a final class and is also reference inside wicket with
> 'instanceof'.
>

So far no one needed to add custom MarkupElements and that's why it is not
very easy.
You can fork Wicket and create a branch where you can make modifications to
make it easier and
later we can review the needed changes and probably apply them back in
Wicket.


>
> So the only way I could think of to do it (which I've done and it works) is
> to create a subclass of Markup (ModifiableMarkup) that takes the original
> wicket-parsed markup, and adds all it's elements.  Then during the onRender
> phase EL enabled components call
> ModifiableMarkup.resolve(ExpressionResolver, ELParseMatchList) which
> internally replaces RawMarkup elements belonging to that compenent with an
> EL resolved version.  This is done just before calling super.onRender().
> Sounds ugly but it works and performance is now equal to standard wicket
> (in some cases can even be a little faster due to not needing
> PropertyModels).
>
> Because the Markup instances are now mutable I can't use wicket's markup
> cache as it's one per class and ModifiableMarkup.resolve method could
> easily be called by many threads at once.  So I've had to implement caching
> per thread/class combination.  i.e. ELPanel will have a cached instance of
> Markup for every thread.
>
> My question is twofold:
> 1/ As I have no choice but to leave ModifiableMarkup mutable, what is the
> purpose of making Markup immutable?  From what I can see from browsing
> wicket source all it achieves is a bit of safety and releasing some
> resources from the backing XmlTags in the MarkupElements.  Is there any
> other purpose to it?  i.e. can you forsee any problems with using a mutable
> instance of Markup for rendering?
>

Why ModifiableMarkup has to be mutable ?
Do you expect that the markup will change at runtime in some conditions ?
I think what you need is a new impl of MarkupElement for the expressions.
So org.apache.wicket.markup.Markup#markupElements will have more elements.
Then when rendering starts each element will render itself as appropriate.
But the list itself won't change once created.
If the developer changes the markup then the whole Markup instance is
replaced with a new one. As now.


>
> 2/ Is the per thread/class caching strategy really safe?  The only way I
> could think it could be broken is if it was possible for the server to
> suspend a thread mid-render cycle and give another request use of that
> thread.  If that happened the new request would overwrite the markup
> expressions and the when the old resumed and expressions already resolved
> would have values from the the request that interrupted it.
> As far as I'm aware with the work I've done with Jetty and NIO connectors
> before this will only happen if you ask Jetty to do it while processing the
> request. Is this a possibility with wicket or can I rely on a complete
> render cycle to happen uninterrupted before the thread is reused for
> another request?
>

It is safe to assume that exactly one thread will process the request.
This is how Wicket's thread locals work today.
Using Servlet 3.0 AsyncContext in a page will break many other things.

Reply via email to