Hello again all,

 

Thanks very much for all of your advice.  I think I'm starting to grasp how models should be used now.  Just a couple of follow up questions:

 

Model for ListChoice selections:

I am now using a LoadableDetachableModel for pulling the list of snippets on each page load.  However, I still use the following to track which entry in the ListChoice is selected:

 

public HtmlSnippetDemo()

{

      ...

      frmEdit.setModel(new CompoundPropertyModel(selectedSnippetModel));

      frmEdit.add(new ListChoice("selectSnippets", new SnippetListModel(),

            new ChoiceRenderer("name", "datastoreId")));

      ...

}

 

private static final class SelectedSnippetModel implements Serializable

{

      public HtmlSnippet selectSnippets = null;

}

 

Should I make the SelectedSnippetModel detachable as well?  Even though I use the ChoiceRenderer to tell the ListChoice to just use the datastoreId for selection-tracking, it still seems to return an HtmlSnippet instance.  I already have a detachable SnippetModel I’m using for the editor panel, but it is read-only.  I would need one that works with setObject to use with the ListChoice, right?

 

Adding/Setting Attributes on Components:

The TextField component does not have a setReadonly method but it does have a setEnabled method.  Is there a simple way to add the readonly attribute to the markup rendered by the component? If I use setEnabled, the browser does not allow the user to select or copy the text in the rendered <input/> element.

 

Thanks again!

Karl

 

 

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Eelco Hillenius
Sent:
Wednesday, June 07, 2006 11:02 AM
To: wicket-user@lists.sourceforge.net
Subject: Re: [Wicket-user] Wicket Newbie Best Practices Questions

 

In general, I think your code looks fine. It looks like how you would

write things if it were a Swing app.

 

A possible improvement is to rely more on the request-response nature

of Wicket. In desktop applications, you are generally in charge of

letting dependent components know some state has changed, and you

typically construct a network of property listeners to propogate such

changes. You can do the same with Wicket, but alternatively you can

make use of the knowledge that when a request comes in, the whole set

of components will be visited (for rendering), including the models

etc. If you use that knowledge, you can invert the strategy from

pushing changes to interested listeners, to models just pulling the

their state just in time.

 

For example, instead of:

 

private final ArrayList<String> listSnippetIds = new ArrayList<String>();

 

private void updateSnippetList() {

         listSnippetIds.clear();

         JpoxDataAccess da = new JpoxDataAccess();

         for (Object objCurSnippet : da.getBoExtent(HtmlSnippet.class))

               listSnippetIds.add(((HtmlSnippet)

objCurSnippet).getDatastoreId());

}

 

you could have a model like this:

 

private static final class SnippetListModel extends LoadableDetachableModel {

  protected abstract Object load() {

       List<HtmlSnippet> list = new ArrayList<HtmlSnippet>()

       JpoxDataAccess da = new JpoxDataAccess();

       for (Object objCurSnippet : da.getBoExtent(HtmlSnippet.class)) {

               list.add((HtmlSnippet) objCurSnippet);

       }

       return list;

  }

}

 

frmEdit.add(new ListChoice("selectSnippets", new SnippetListModel()));

 

 

You don't need the instance variable snippet ids then. Also you can

work with the complete objects instead of id's while even being more

efficient then before. This is because LoadableDetachableModel is a

detachable model, meaning that on first use it will be attached (in

this case will have the effect that method 'load' is called, and the

result of load is set as a temporary, transient value of the model)

and after the request is done, the model will be detached (in this

will have the effect that the temporary var - the result of load - is

set to null again, so that next time getObject is called, the model

will be attached again first).

 

So what we achieved here is that you always work with the objects as

fresh as they get, while nothing is stored as page state except for

the model instance itself; during a request the snippets are loaded

from the database, and at the end of the request, the snippets are

removed again.

 

Another thing we achieved here is that we now have a completely

standalone model. As there is no dependency with the page, you could

reuse this model anywhere you need a list of snippets. There are

endless variations of course, including having full-fledged models

that take parameters for filtering, sorting etc.

 

A similar thing can be said about the snippetBeingEdited variable.

Everyone should be very careful with storing persistent objects (JDO,

Hibernate, EJB objects) as page state. In most cases you shouldn't do

that, as it'll give you problems with lazy collections, the

persistence engine's session (like Hibernate's Session) they are

supposed to be part of, the transaction they might take part of, etc.

It is much better to use detachable models here too. So typically, you

would have a model that stores the id of the persistent object you

want to use, and when attached, you would load that object, and when

detached you would release it again. A specialization of

LoadableDetachableModel could work here, or e.g. extend

AbstractReadOnlyDetachableModel. Typically - e.g. with Hibernate - if

you share objects in the same session/ transaction they will be hold

in a session cache, so unless you get your objects using queries your

persistence engine don't know how to cache, using seperate detachable

models for such database objects is efficient enough.

 

Finally, about using annonymous classes. Typically, this is a

tradeoff. Annonynmous classes make for a very compact writing style,

and in cases like writing links and buttons etc where you just

implement the event handler, using annonymous classes usually makes

the code better readable and quicker to write. The other side however

is that explicit classes are easier to refactor. Also, if you start

writing them as static or top level classes, only to revert to

non-static private classes (which can use member variables of the

parent classes) when it really makes sense, you'll have a much clearer

idea of what will be component state (and thus be stored in the

session) and what not.

 

Hope this helps,

 

Eelco

 

 

> I know it's a lot of code, but I would greatly appreciate it if someone here

> could skim through it and point out anything I'm doing that will bite me in

> the ass later on down the road.  In particular, I wonder about:

>

> Do people generally just use anonymous inner classes for Button event

> handling or write fully-subclassed private inner classes?

> To track the current state of things, I use a non-final HtmlSnippet member

> variable and a separate model class for the entered values.  Does this

> dual-set up make sense?

> In order for my Panel to notify the enclosing WebPage instance that the

> database has been updated, I wrote a simple listener for the Panel.  Is

> there a way to do this that makes more sense since I have both the list of

> objects and the editor on the same page?

 

 

_______________________________________________

Wicket-user mailing list

Wicket-user@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/wicket-user

 

--

No virus found in this incoming message.

Checked by AVG Free Edition.

Version: 7.1.394 / Virus Database: 268.8.3/358 - Release Date: 6/7/2006

 

_______________________________________________
Wicket-user mailing list
Wicket-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wicket-user

Reply via email to