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