> > I think we should not try to support Wicket 1.x. Right now, I know of 3
> > projects that are using Pax Wicket, and all of those we (Jayway Malaysia)
> > are in charge of the code maintenance, so we could handle the transition to
> > Wicket 2.0 quite easily. So, even though Wicket 2.0 is still not released,
> > I suggest that we drop Wicket 1.x support in Pax Wicket and just move
> > ahead. Wicket 2.0 will probably be out before we consider Pax Wicket final
> > 1.0.

I expect 2.0 to be out Q3 this year. Final and hopefully as an
incubated ASF project with Wicket In Action covering that version.

That said 1.x is a good version to work with now, and we'll keep on
supporting that for quite some time, as a couple of the core
developers (including yours truly) are building some pretty large
applications with it that'll be around for a while. But if you have
the choice without a big preference, go for 2.0.

> Well, this is harder than I thought.
>
> In all honesty, we have not been using the "expected practices" of Wicket in
> the Pax Wicket patterns. For instance;
>
> ListView view = new ListView()
> {
>     public void populateItem( ListItem item )
>     {
>         Component c = item.getModelObject();
>         item.add( c );
>     }
> };
>
> List<Component> c = createComponents( SOME_WICKET_ID, null );
> view.setModelObject( c );
>
>
> Here, we are actually storing the Components of the ListView directly in the
> model of the ListView, whereas Wicket is designed to take "values" which are
> then created. In Wicket 1.x, this "rape" of the ideas didn't matter much, but
> in Wicket 2.0, the "item" is the parent of the component, and must be passed
> to the child component, but we don't have the parent "item" until after we
> have created the child components.

> Catch22.

I'm a pervert; I'm never able to actually finish funny books like that
(and funny it is!), while I'm swallowing boring books by the dozen.

> So, to support this, we must kill the notion of createComponents(), and
> instead introduce some form of "model", "tag" or "callback" system, more in
> line with Wicket.
> There are probably many ways to do that, and I and Edward will look into that
> more in detail tomorrow, but for instance;
>
> List<PaxTag> tags = getTags( SOME_WICKET_ID );
> ListView view = new ListView( models )
> {
>     public void populateItem( ListItem item )
>     {
>         PaxTag tag = item.getModelObject();
>         // The superclass handle the creation process.
>         createComponent( SOME_WICKET_ID, tag, item );
>     }
> };
>
> But, the PaxTag would just be a map object to the ContentSource, so would that
> mean the code could be;
>
> List<ContentSource> sources = getContentSources( SOME_WICKET_ID );
> ListView view = new ListView( models )
> {
>     public void populateItem( ListItem item )
>     {
>         ContentSource source = item.getModelObject();
>         source.createComponent( SOME_WICKET_ID, item );
>     }
> };
>
> At least it look better to me, but I want to see it in a larger action before
> having a final opinion about it.

Yeah, some things got easier to build more elegant and efficient in
Wicket 2.0, like building Javascript components where you need access
to the id/ component path etc., but other things got a little bit
harder. The latter is biting you. Rather then just arbitrarily
creating your components and keeping them around to attach them 'just
in time' you have to construct them properly in the hierarchy in one
pass now. In general, you can do all the stuff you did before, but you
have to work with factories more now. Just like the example you gave.
It's a little bit awkward at times, though otoh it forces you to think
better about when you create them and how you keep them and probably
prevents you from having a bunch of components lingering around in
memory you don't even use but plan to use later.

Imo, once you get used to it, working with callbacks/ factories like
that is actually nice. Much the same as it takes a bit for people to
get used to working in a 'pull' when with models and implementing
abstract methods for Wicket. It's a departure from typical
desktop-like programming, but a better fit for the request based
nature of web applications.

> Eelco, we have the impression that the stuff that is stored in the ListView
> model will be serialized, in which case the above can not work, and a PaxTag
> mapping or similar would be needed. Could you clarify a bit?

Yep. Keep in mind that Wicket doesn't have to serialize components at
all; it mostly depends on whether and how you do clustering (for
instance, Terracotta provides clustering but doesn't use serialization
for that) and what ISessionStore implementation you are using. But in
general, with the *possible* serialization in mind, and the level of
constant session memory your application is using, it is best to keep
'state' of components to the minimum. This generally can be summed up
with these two points:

1) Use detachable models, such as LoadableDetachableModel. The basic
idea behind these models is that you keep the minimal information
between requests (such as the id of a persistent object), and that
during a request, if/ when the model is accessed you inflate the model
(like load and populate the object from the database). When the
request is done, the model cleans up everything it doesn't need so
that the object(s) can be GC-ed and when it is serialized, e.g. for a
cluster sync, only the id needs to get sent over. Additionally, when
you're working with e.g. something like Hibernate, this patter is good
to keep out of trouble with lazy collections and friends, and it'll
ensure that you'll display fresh data on each request.

An example I like:

public class MyPanel extends Panel {

  @SpringBean private MyService service;

  public MyPanel(MarkupContainer parent, String id) {
    IModel theModel = new LoadableDetachableModel() {
      protected Object load() {
        return service.findAWholeBunchOfVeryCoolDomainObjects();
      }
    }
    ...
  }
}

Here, @SpringBean (from the wicket-spring project) will result in
service being assigned a proxy, which is serializable and very light
and just looks up the service when it is needed. The model uses that
service to return a bunch of objects, e.g. to be used in a dataview.
The load method will only be called when a component the model is
coupled to accesses the model. The result of that call will be cached
during the request (in case there are multiple invocations) and after
the request, it will be cleaned up again, so that only the class sig
remains as 'state'.

Btw, @SpringBean works really great, I'm totally hooked on it, even
though I've never been a Spring kiddie. How about an OSGi variant of
this. Any options/ ideas?

2) Be careful with instance variables and inner classes. Keep in mind
that e.g. an anonymous always keeps a reference to it's parent (like
the MyPanel instance for theModel), even if you don't actually access
it. The point here in relation to Pax Wicket and Wicket 1.3 vs 2.0 is
that the latter example you gave, where you just keep references to
factories (ContentSource) rather than the actual components is
probably much more efficient, or at least easier to tweak if you ever
need to.

And to conclude this email... please feel free to start discussions
about creational patterns, best practices etc with Wicket on the user
or dev list of Wicket.

Regards,

Eelco

_______________________________________________
general mailing list
general@lists.ops4j.org
http://lists.ops4j.org/mailman/listinfo/general

Reply via email to