NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed. (sponsored)
In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.
Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.
Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Welcome back to my ever-expanding Wicket series. For you new-comers, here is the entire
series up to this point listed. If you haven't, please read them up to this point - they
are chronological in order. By the way; I plan to only maintain the list of articles on
the first article, so go there for the complete list!
Server-Side State Revisited; Bookmarkable Links (This Article)
My last Wicket article discussed the basic link component, and how you could use it
to respond to user events. The link component was the first event-handling component
we worked with directly. It's certainly very neat, but it was also drastically different
from what you typically
would be used to from a Servlet/JSP/Struts/etc. approach. I was purposefully quiet about
Wicket and the more traditional world of links that don't rely on server-side state;
what Wicket calls 'bookmarkable' links. A 'bookmarkable' link is a link that is not reliant
on any server-side state to work. I did this to make sure I put you in a different mind set
about Wicket that I could not get into for quite a while.
Before I describe bookmarkable links, however, let's back up a bit and understand a little about the ecosystem
of a server-side component model and the client-side result. In our last example,
we added a link component, and that link component would somehow magically be able to process
the link click from the user. Then I made the point that the link component, by default, would
return the user back to the same page - this is just something Wicket does. All of that is really
cool, but it's not something we can just expect to always work. For instance, spending a little
time thinking about this, let's imagine for a moment that the user's session has expired on our
server, or perhaps the server restarted and didn't save the session data. At this point in both cases
the user's session will no longer be available. What happens then, if the user clicks the link
at this time? After all, there *is no link component* in their session anymore, so we can't
go handling the event properly, and the link will fail. I have emulated this by turning off
session persistence on my tomcat instance, and restarting it while my browser had our page loaded.
Here is what I see:
By default, this is the page that Wicket will show if the user makes a request for some state-relevant
action to occur (such as this link being pushed) and the session state doesn't match what the
client state says it should match. This is where having Wicket manage all of the URLs comes in to
play. Wicket can supply various key bits of tracking information into the URLs so that as it needs
to process events and user behavior, if anything should not match up on the server, it can flag the
error for the user. This same infrastructure is also how Wicket handles the 'dreaded back button
problem' (which I mentioned in the first article). I should point out that the above screen, like
all of the other error/warning/surprise condition pages is completely configurable (but that's not
part of today's topic).
Not to get on too much of a tangent, but one of the key differences of Wicket is the default approach
it takes to web applications in Java. Most MVC frameworks are built to act as an adapter to servlets -
effectively becoming what I like to call servlets++. In other words, they still handle events directly
from the servlet, but they try to make a point to disconnect the controller from the view, and usually
provide some affordances as far as pre/post processing, and form binding (and some of these frameworks,
such as Spring MVC do an exceedingly good job at it). All that being said, they are based in the
philosophy/assumption that your website will be 'stateless' in nature, and if you want it to be
'stateful', you need to do some extra work/lifting. Any of you who have tried to write a bullet-proof
wizard in Struts for instance, know that there are some hoops you have to go through to ensure the
user can't totally corrupt their wizard data by doing something unexpected, such as going back in
the wizard via their browser instead of through your carefully controlled back buttons.
Now, don't get me wrong, some of these MVC frameworks provide affordances to make stateful processes
such as wizards easier, but in the end they are tailored much better for stateless sites.
Wicket, on the other hand, makes the assumption that your web application will be stateful, and
then provides affordances to use it in a stateless site. This means that Wicket is exceedingly good
at the stateful site approach, and then can do stateless sites too. It turns out, since stateless
websites are easier in the sense they require less plumbing, Wicket works *just fine* for stateless
sites, and allow you to do some pretty nifty things that are otherwise just not worth the trouble.
In any case, they key point above is that the link component is a stateful component that handles
events from the user, but it is not your only option. Wicket's
wicket.markup.html.link.BookmarkablePageLink
is a special type of component that, unlike it's
wicket.markup.html.link.Link
counterpart,
doesn't handle the event from the user, but instead renders a URL that Wicket is made to be
especially aware of - a link to a Page.
Pages in Wicket are the closest analogy to something like a Servlet. They handle the top-level request
from the user. The distinction is that pages in Wicket can handle multiple requests as they 'evolve'
with user behavior. So, for instance, in the previous tip our page had a link on it. The user clicked
that link. At that time, via Wicket, the page was told
of the event, and the page delegated it to the link. The link then processed the event using our 'handle'
method, and then finally the page was re-rendered. A stateless application in the Wicket sense is one
where the page never has any events sent to it, and as such doesn't change based on user behavior. The
page at that point simply becomes a smart way to handle component rendering, but doesn't use
any of the benefits of Wicket's server-side model.
Bookmarkable page links are links back into Wicket that will build a page for the given page type if
no page is available.
To exercise this new kind of link, we need to add a new page to our application. Here is the
new page's Java code:
This is a very basic page - the point isn't to put anything new on the page though, but to have a
different page to which we can link.
The next step is to link to this other page from our
AlohaPage
- first we update the
component model:
package com.javalobby.tnt.wicket.aloha;
import java.util.Date;
import wicket.markup.html.WebPage;
import wicket.markup.html.basic.Label;
import wicket.markup.html.link.*;
publicclass AlohaPage extends WebPage {
public AlohaPage() {
// A Title for our page
final Date firstVisitTime = new Date();
add(new Label("pageTitle", "Aloha - The Time is: " + firstVisitTime));
add(new Link("dateLink") {
@Override publicvoid onClick() {
System.out.println(
"The user clicked the link at: " +
firstVisitTime +
"\nThe time now is :" +
new Date());
}
});
// our new bookmarkable link.
add(new BookmarkablePageLink("page2Link", Page2.class));
add(new PersonPanel("personPanel"));
}
}
Next, we need to update the markup to add the link:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.sourceforge.net/"
xml:lang="en"
lang="en">
<head>
<title wicket:id="pageTitle">[Page Title]</title>
</head>
<body onload="fromAlohaPage();">
<h1>This is the BEGINNING of the Aloha Page</h1>
<a href="#" wicket:id="dateLink">Click me!</a>
<!-- Our new page link -->
<a href="#" wicket:id="page2Link">Go to Page 2</a>
<div wicket:id="personPanel"></div>
<h1>This is the END of the Aloha Page</h1>
</body>
</html>
Last, we just need to test it. When I bring the application up now, I am presented with this
page:
If I click the link, this is what I'll see:
If you're playing along, did you notice the link in the address bar? It should be something like this:
http://localhost:8080/jlwicket/app?bookmarkablePage=com.javalobby.tnt.wicket.aloha.Page2
Some developers may be concerned about the verbosity of this URL (shows a lot about the underlying
application) - Wicket 1.1 has an alias system that helps you obfuscate this - and Wicket 1.2 will drastically
enhance the support - I'll probably defer until Wicket 1.2 to actually talk about how all of that works however.
This URL is something that Wicket will recognize as not having pre-defined server-side state, and
Wicket can build a new page component model for this request (in the same way that it builds one
for the homepage when we first hit our web application).
Because these special kind of 'stateless' page links are so common, Wicket provides a markup convenience
that prevents you from having to stuff them into your component model (like I did above for 'AlohaPage').
In the markup for AlohaPage (AlohaPage.html) we can use a special
wicket:link
tag, and
some 'static html' naming conventions to get Wicket to auto-generate a bookmarkable link for us:
So, first we remove the link back out of the
AlohaPage
:
package com.javalobby.tnt.wicket.aloha;
import java.util.Date;
import wicket.markup.html.WebPage;
import wicket.markup.html.basic.Label;
import wicket.markup.html.link.*;
publicclass AlohaPage extends WebPage {
public AlohaPage() {
// A Title for our page
final Date firstVisitTime = new Date();
add(new Label("pageTitle", "Aloha - The Time is: " + firstVisitTime));
add(new Link("dateLink") {
@Override publicvoid onClick() {
System.out.println(
"The user clicked the link at: " +
firstVisitTime +
"\nThe time now is :" +
new Date());
}
});
add(new PersonPanel("personPanel"));
}
}
Then we simply modify our anchor tag to use the naming convention, and we add the wicket link:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.sourceforge.net/"
xml:lang="en"
lang="en">
<head>
<title wicket:id="pageTitle">[Page Title]</title>
</head>
<body onload="fromAlohaPage();">
<h1>This is the BEGINNING of the Aloha Page</h1>
<a href="#" wicket:id="dateLink">Click me!</a>
<wicket:link><a href="Page2.html">Go to Page 2</a></wicket:link>
<!--
The new panel. Notice that it's just an empty tag that
will be filled in by the panel when it is asked to render.
-->
<div wicket:id="personPanel"></div>
<h1>This is the END of the Aloha Page</h1>
</body>
</html>
Note that I just referred to
Page2.html
in the 'href' - Wicket will look
in the same package as the page the link is on for the other page -
if it is in a different package we'd need to type the fully qualified package name.
Amazingly, this link will even work for someone previewing the page!
That's the basics of bookmarkable links. Thanks for tuning in! Be sure to check out the next post
in this series, as I elaborate on some of the more complex features of bookmarking to pages:
Page Parameters
.
Re: Wicket: Server-Side State Revisited; Bookmarkable Links
For completeness sake: the
Wicket wiki
can be found at: http://wicket.sourceforge.net/wiki (this will redirect you to another website, where we don't have the performance problems we had on Sourceforge.net).
Re: Wicket: Server-Side State Revisited; Bookmarkable Links
The improvements which RJ is referring to in Wicket 1.2 are quite comprehensive. You can "mount" bookmarkable pages (or whole packages of them at once) on any path in your web application. URLs that Wicket generates to mounted pages are completely free of Wicket URL encoding artifacts.
Wicket: Server-Side State Revisited; Bookmarkable Links
At 4:53 PM on Jan 13, 2006, R.J. Lorimer wrote:
Fresh Jobs for Developers Post a job opportunity
Welcome back to my ever-expanding Wicket series. For you new-comers, here is the entire series up to this point listed. If you haven't, please read them up to this point - they are chronological in order. By the way; I plan to only maintain the list of articles on the first article, so go there for the complete list!
My last Wicket article discussed the basic link component, and how you could use it to respond to user events. The link component was the first event-handling component we worked with directly. It's certainly very neat, but it was also drastically different from what you typically would be used to from a Servlet/JSP/Struts/etc. approach. I was purposefully quiet about Wicket and the more traditional world of links that don't rely on server-side state; what Wicket calls 'bookmarkable' links. A 'bookmarkable' link is a link that is not reliant on any server-side state to work. I did this to make sure I put you in a different mind set about Wicket that I could not get into for quite a while.
Before I describe bookmarkable links, however, let's back up a bit and understand a little about the ecosystem of a server-side component model and the client-side result. In our last example, we added a link component, and that link component would somehow magically be able to process the link click from the user. Then I made the point that the link component, by default, would return the user back to the same page - this is just something Wicket does. All of that is really cool, but it's not something we can just expect to always work. For instance, spending a little time thinking about this, let's imagine for a moment that the user's session has expired on our server, or perhaps the server restarted and didn't save the session data. At this point in both cases the user's session will no longer be available. What happens then, if the user clicks the link at this time? After all, there *is no link component* in their session anymore, so we can't go handling the event properly, and the link will fail. I have emulated this by turning off session persistence on my tomcat instance, and restarting it while my browser had our page loaded. Here is what I see:
By default, this is the page that Wicket will show if the user makes a request for some state-relevant action to occur (such as this link being pushed) and the session state doesn't match what the client state says it should match. This is where having Wicket manage all of the URLs comes in to play. Wicket can supply various key bits of tracking information into the URLs so that as it needs to process events and user behavior, if anything should not match up on the server, it can flag the error for the user. This same infrastructure is also how Wicket handles the 'dreaded back button problem' (which I mentioned in the first article). I should point out that the above screen, like all of the other error/warning/surprise condition pages is completely configurable (but that's not part of today's topic).
Not to get on too much of a tangent, but one of the key differences of Wicket is the default approach it takes to web applications in Java. Most MVC frameworks are built to act as an adapter to servlets - effectively becoming what I like to call servlets++. In other words, they still handle events directly from the servlet, but they try to make a point to disconnect the controller from the view, and usually provide some affordances as far as pre/post processing, and form binding (and some of these frameworks, such as Spring MVC do an exceedingly good job at it). All that being said, they are based in the philosophy/assumption that your website will be 'stateless' in nature, and if you want it to be 'stateful', you need to do some extra work/lifting. Any of you who have tried to write a bullet-proof wizard in Struts for instance, know that there are some hoops you have to go through to ensure the user can't totally corrupt their wizard data by doing something unexpected, such as going back in the wizard via their browser instead of through your carefully controlled back buttons.
Now, don't get me wrong, some of these MVC frameworks provide affordances to make stateful processes such as wizards easier, but in the end they are tailored much better for stateless sites.
Wicket, on the other hand, makes the assumption that your web application will be stateful, and then provides affordances to use it in a stateless site. This means that Wicket is exceedingly good at the stateful site approach, and then can do stateless sites too. It turns out, since stateless websites are easier in the sense they require less plumbing, Wicket works *just fine* for stateless sites, and allow you to do some pretty nifty things that are otherwise just not worth the trouble.
In any case, they key point above is that the link component is a stateful component that handles events from the user, but it is not your only option. Wicket's
wicket.markup.html.link.BookmarkablePageLinkis a special type of component that, unlike it'swicket.markup.html.link.Linkcounterpart, doesn't handle the event from the user, but instead renders a URL that Wicket is made to be especially aware of - a link to a Page.Pages in Wicket are the closest analogy to something like a Servlet. They handle the top-level request from the user. The distinction is that pages in Wicket can handle multiple requests as they 'evolve' with user behavior. So, for instance, in the previous tip our page had a link on it. The user clicked that link. At that time, via Wicket, the page was told of the event, and the page delegated it to the link. The link then processed the event using our 'handle' method, and then finally the page was re-rendered. A stateless application in the Wicket sense is one where the page never has any events sent to it, and as such doesn't change based on user behavior. The page at that point simply becomes a smart way to handle component rendering, but doesn't use any of the benefits of Wicket's server-side model.
Bookmarkable page links are links back into Wicket that will build a page for the given page type if no page is available.
To exercise this new kind of link, we need to add a new page to our application. Here is the new page's Java code:
package com.javalobby.tnt.wicket.aloha; import wicket.markup.html.WebPage; import wicket.markup.html.basic.Label; public class Page2 extends WebPage { public Page2() { add(new Label("pageTitle", "Welcome to Page 2")); } }Here is the associated markup:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.sourceforge.net/" xml:lang="en" lang="en"> <head> <title>Page 2</title> </head> <body> <h1 wicket:id="pageTitle"></h1> </body> </html>This is a very basic page - the point isn't to put anything new on the page though, but to have a different page to which we can link.
The next step is to link to this other page from our
AlohaPage- first we update the component model:package com.javalobby.tnt.wicket.aloha; import java.util.Date; import wicket.markup.html.WebPage; import wicket.markup.html.basic.Label; import wicket.markup.html.link.*; public class AlohaPage extends WebPage { public AlohaPage() { // A Title for our page final Date firstVisitTime = new Date(); add(new Label("pageTitle", "Aloha - The Time is: " + firstVisitTime)); add(new Link("dateLink") { @Override public void onClick() { System.out.println( "The user clicked the link at: " + firstVisitTime + "\nThe time now is :" + new Date()); } }); // our new bookmarkable link. add(new BookmarkablePageLink("page2Link", Page2.class)); add(new PersonPanel("personPanel")); } }Next, we need to update the markup to add the link:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.sourceforge.net/" xml:lang="en" lang="en"> <head> <title wicket:id="pageTitle">[Page Title]</title> </head> <body onload="fromAlohaPage();"> <h1>This is the BEGINNING of the Aloha Page</h1> <a href="#" wicket:id="dateLink">Click me!</a> <!-- Our new page link --> <a href="#" wicket:id="page2Link">Go to Page 2</a> <div wicket:id="personPanel"></div> <h1>This is the END of the Aloha Page</h1> </body> </html>Last, we just need to test it. When I bring the application up now, I am presented with this page:
If I click the link, this is what I'll see:
If you're playing along, did you notice the link in the address bar? It should be something like this: http://localhost:8080/jlwicket/app?bookmarkablePage=com.javalobby.tnt.wicket.aloha.Page2 Some developers may be concerned about the verbosity of this URL (shows a lot about the underlying application) - Wicket 1.1 has an alias system that helps you obfuscate this - and Wicket 1.2 will drastically enhance the support - I'll probably defer until Wicket 1.2 to actually talk about how all of that works however.
This URL is something that Wicket will recognize as not having pre-defined server-side state, and Wicket can build a new page component model for this request (in the same way that it builds one for the homepage when we first hit our web application).
Because these special kind of 'stateless' page links are so common, Wicket provides a markup convenience that prevents you from having to stuff them into your component model (like I did above for 'AlohaPage'). In the markup for AlohaPage (AlohaPage.html) we can use a special
wicket:linktag, and some 'static html' naming conventions to get Wicket to auto-generate a bookmarkable link for us:So, first we remove the link back out of the
AlohaPage:package com.javalobby.tnt.wicket.aloha; import java.util.Date; import wicket.markup.html.WebPage; import wicket.markup.html.basic.Label; import wicket.markup.html.link.*; public class AlohaPage extends WebPage { public AlohaPage() { // A Title for our page final Date firstVisitTime = new Date(); add(new Label("pageTitle", "Aloha - The Time is: " + firstVisitTime)); add(new Link("dateLink") { @Override public void onClick() { System.out.println( "The user clicked the link at: " + firstVisitTime + "\nThe time now is :" + new Date()); } }); add(new PersonPanel("personPanel")); } }Then we simply modify our anchor tag to use the naming convention, and we add the wicket link:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.sourceforge.net/" xml:lang="en" lang="en"> <head> <title wicket:id="pageTitle">[Page Title]</title> </head> <body onload="fromAlohaPage();"> <h1>This is the BEGINNING of the Aloha Page</h1> <a href="#" wicket:id="dateLink">Click me!</a> <wicket:link><a href="Page2.html">Go to Page 2</a></wicket:link> <!-- The new panel. Notice that it's just an empty tag that will be filled in by the panel when it is asked to render. --> <div wicket:id="personPanel"></div> <h1>This is the END of the Aloha Page</h1> </body> </html>Note that I just referred to
Page2.htmlin the 'href' - Wicket will look in the same package as the page the link is on for the other page - if it is in a different package we'd need to type the fully qualified package name. Amazingly, this link will even work for someone previewing the page!That's the basics of bookmarkable links. Thanks for tuning in! Be sure to check out the next post in this series, as I elaborate on some of the more complex features of bookmarking to pages: Page Parameters .
Until next time,
R.J. Lorimer
Contributing Editor -rj -at- javalobby.orgAuthor -http://www.coffee-bytes.comSoftware Consultant -http://www.numbersix.com4 replies so far (
Post your own)
Re: Wicket: Server-Side State Revisited; Bookmarkable Links
Thanks for yet another article on Wicket!I've put a link to this article on Wicket's WIKI front page. If there is an easier link to the whole series, please update.
Re: Wicket: Server-Side State Revisited; Bookmarkable Links
For completeness sake: the Wicket wiki can be found at: http://wicket.sourceforge.net/wiki (this will redirect you to another website, where we don't have the performance problems we had on Sourceforge.net).Re: Wicket: Server-Side State Revisited; Bookmarkable Links
The improvements which RJ is referring to in Wicket 1.2 are quite comprehensive. You can "mount" bookmarkable pages (or whole packages of them at once) on any path in your web application. URLs that Wicket generates to mounted pages are completely free of Wicket URL encoding artifacts.Also, the URL format itself has also been made considerably more brief and it has been namespaced to avoid possible query parameter naming collisions. You can read some of the details here: http://jroller.com/page/JonathanLocke?entry=wicket_parameters_refactor
And hopefully in a more friendly walkthrough in some future RJ article!
Re: Wicket: Server-Side State Revisited; Bookmarkable Links
Oops. Obviously, I mean more friendly than my blog post, not more friendly than the above article, which is quite nice. Thanks RJ!