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 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?

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?

Reply via email to