Wicket Guard #4

Simple wrapper for creating bookmarkable page links

Lets say you want to create a parametrizable bookmarkable link like this:

<a href="/cityPage?city=london">London</a>

Creating a dynamic parametrized bookmarkable link needs the following items in wicket:

  • a wicket:id for the anchor’s href
  • a key for the parameter
  • the value for the key
  • a wicket:id for the displaying the text of the link
  • the actual text itself

Here is a simple wrapper method that can do all in one stroke:

	/**
	 * Usage:
	 *   createBookmarkablePageLink("linkWicketId", Page.class, "paramKey", $param.value, "textWicketId", $text);
	 */
	public static BookmarkablePageLink createBookmarkablePageLink(String _wicketId, Class _pageClass, String _paramKey, String _paramValue, String _wicketHrefTextId, String _hrefText) {
		PageParameters param = new PageParameters();
		param.add(_paramKey, _paramValue);
		BookmarkablePageLink link = new BookmarkablePageLink(_wicketId, _pageClass, param);
		link.add(new Label(_wicketHrefTextId, _hrefText));
		
		return link;
	}

Here is how the call would look for the above html:

createBookmarkablePageLink("cityLinkWicketId", CityPage.class "city", "london", "cityNameWicketId", "London");

And the corresponding wicket html:

<a wicket:id="cityLinkWicketId" href="#"><span wicket:id="cityNameWicketId">$someCityName</span></a>
Advertisements

Wicket Guard #3

ListView vs DataView/ListProvider

One thing to remember when using DataView instead of ListView is that the DataView does not have a setListProvider(), neither the ListProvider has a setList(). In other words, once these objects are initialized with the list, there is no way to set another new List object. ListView has a setList() which can be called for eg during a onSubmit() to update the list.

The correct way to handle that is, on refreshing, clear out the old items from the list and add new items. When the page/form is displayed again, the new values will be used.

For eg

  List list = new ArrayList();
  //list.add(...)
  DataView dv = new DataView("dataView", new ListProvider("listProvider", list));

  protected void onSubmit() {
    list.clear();
    list.add(...);
    //thats it, no need, (rather cannot) set the list to ListProvider again
  }

So when querying list from say Spring’s JdbcTemplate queryList() methods, be aware that it returns a new List object, which the ListProvider will not pickup. You can simply do a list.clear(), followed by list.addAll(newList);

Clean bowled!

Long long ago, C++ dinosaurs were roaming the software world. Then the Java-steroid came and destroyed almost all of it, with the remaining C++ became fossilized code and mutating silently into smaller species. Evolution continued with Servlets, JSP and a new thing called EJB. Everyone thought EJB was the greatest thing to happen and it really ended up being a “thing”. Programming in JSP was a pain. Then came Struts and it was good for a while. Then programming in Struts was a pain. Then sprang Spring which made everyone think “Why didn’t I think of it before?”. Yes – DI was the way to go; Of course all configurations must be in XML; Of course all states must be in XML. Along came Hibernate – Of course all DB tables, columns, attributes must be defined in XML; In the midst a new movie called JSF was released (working title was JuSt Forget). JSF is analogous to a Hollywood movie to me – JSF apps are nice to look at, rich interfaces, but try making one yourself. Spring core is too good at DI. Thats why there is only one other real competitor (Guice). If Spring MVC was too good, why would we have 30 other web frameworks? Programming in Spring MVC/SWF is becoming a pain because of lot of scaffolding.

And then I found Wicket. When I first read Peter Thomas’ “Spring MVC vs Wicket” and him favoring the latter I just did not believe him. How could anything be better than Spring MVC, injecting beans via Xml or using referenceData to populate the dropdowns? But then I started using Wicket once.

Since then I have been bowled over. Get it? Clean bowled? Get it? 🙂 Sorry I just could not resist comparing Wicket and Cricket terminologies.

Using mathematical induction, will Wicket be a pain in the next 2 years? I do not know. But for now Wicket seems to be very satisfactory to get my web applications done in less than 1/3rd of the time and absolutely having fun coding.

Wicket Guard

One of the cool things I like about Wicket is — its name! It reminds me of cricket, even if Google does not recognize it right away. Search for wicket in google and you do not come across cricket in the first page! (Source: Wicket In Action)

“Taking guard” is a cricket terminology where the batsman stands in the right place before the stumps (off stump guard, leg stump guard etc) before facing the ball. Its a very important part of strategy of playing the game.

So Wicket Guard is word play on that 😛

Wicket Guard #2

Here is a silly Wicket program I wrote. It continues to amaze me how Wicket makes complex stuff simple and simple stuff unbelievably simpler.

Imagine a totally bored Browser that wants to flip coins and display results. Sure you can do that in Servlet/JSP/Spring with meta refresh tag, querying the server every few seconds and redisplay the page. And good luck if you wanna try that with Ajax. But it becomes ridiculously simple with Wicket. The code literally took me less than 20 minutes and I am Wicket beginner (I have Swing background though).

A couple of gotchas:

  • In the FlipMyCoinPage.html, I had to use the style ul.list-style-type: none. With the default bullet type, wicket prints an empty bullet after every flip.
  • In FlipMyCoinPage.java, with Wicket 1.3.6, I was able to add the label with a wicket:id like “Flip coin:” (including the colon). When I recompiled with Wicket 1.4-rc4, there was a runtime error that colon is not allowed as part of id.
//FlipMyCoinPage.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.time.Duration;
import org.learnspace.core.AbstractModel;

public class FlipMyCoinPage extends WebPage {

	final List<IModel> flipperList = new ArrayList<IModel>();
	private int heads = 0;
	private int tails = 0;
	
	public FlipMyCoinPage() {
		super();
		final WebMarkupContainer section;
		section = new WebMarkupContainer("section");
		add(section);
		section.setOutputMarkupId(true);
		section.setOutputMarkupPlaceholderTag(true);
		
		final Label coinResult = new Label("coinResult", new Model<String>());
		RefreshingView coinFlipper = new RefreshingView("coinFlipper") {
			@Override
			protected Iterator getItemModels() {
				Model<Integer> m = new Model<Integer>((int) (Math.random() * 2));
				flipperList.add(m);
				if (m.getObject() == 0) heads++;
				else tails++;
				int total = heads + tails;
				String s = String.format("Tries = %d; Heads = %d (%5.2f%%); Tails = %d (%5.2f%%)", total, heads, (double) heads/total*100, tails, (double) tails/total*100);
				coinResult.setDefaultModelObject(s);
				return flipperList.iterator();
			}

			@Override
			protected void populateItem(Item _item) {
				add(new Label("Flip " + _item.getIndex(), new HeadOrTailModel(_item.getModel())));
			}
		};
		section.add(coinFlipper);
		section.add(coinResult);
		section.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(3)));
	}
	
	//
	class HeadOrTailModel extends AbstractModel {
		
		public HeadOrTailModel(IModel<Integer> _model) {
			super(_model);
		}
		
		public Object getObject() {  
			return ((Integer) getModelObject() == 0) ? "Heads" : "Tails";  
		}  
	}

}
//HeadOrTailModel uses this AbstractModel for brevity
//Based on Jeremey Thomson's blog
import org.apache.wicket.model.IModel;

public abstract class AbstractModel implements IModel {

	private final IModel nestedModel;
	
	public AbstractModel(IModel _model) {
		nestedModel = _model;
	}
	
	@Override
	public void setObject(Object object) {
		nestedModel.setObject(object);
	}
	
	public IModel getModel() {
		return nestedModel;
	}
	
	public Object getModelObject() {
		return nestedModel.getObject();
	}

	@Override
	public void detach() {
		nestedModel.detach();
	}
}

And here is the corresponding html.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" 
			xml:lang="en">
<head>
	<title>Coin Flipper Demo!</title>
	<style type="text/css">
		ul {
			font-family: tahoma;
			font-size: 9pt;
			list-style-type: none;
			color: black
		}
		
		span#result {
			color: lightgreen;
			font-family: consolas;
			font-size: 12pt;
			font-weight: bold;
			padding: 1em 1em 1em 1em;
			background-color: black
		}
	</style>
</head>
<body>
<div wicket:id="section">
<h3>A really bored browser is flipping a coin ...</h3>
<p>
<span id="result" wicket:id="coinResult"></span>
</p>
<p></p>
<ul>
 <li wicket:id="coinFlipper"></li>
</ul>
</div>
</body>
</html>

Wicket Guard #1

Wicket Guard #1 – Cannot use wicket:id elements in substituted (replaced) panels.

I was using a panel html, but wanted to have the flexibility of designing it in main page also. So I copy the panel’s contents in the Main page too just for designing. This panel content should eventually be replaced by Wicket at runtime.

Panel.html

<wicket:panel>
  <div id="panelContainer">
    <ul>
      <li wicket:id="element">...</li>
    </ul>
  </div>
</wicket:panel>

Main.html

<div id="panel" wicket:id="panel">
    <ul>
      <li wicket:id="element">...</li>
    </ul>
</div>

When I ran the above code, wicket complained that <div> element does not have a close tag. Wicket obviously replaces the contains within div#panel in the Main.html with the Panel.html contents. Then why would it complain? After a bit of digging, found out that the Main.html also contains a not-so-obvious <li wicket:id=”element”>. Wicket does not blindly replace the panel within div#panel, instead it errors out if the element within that has a wicket:id.

Corrected Main.html

<div id="panel" wicket:id="panel">
    <ul>
      <li>...</li>
    </ul>
</div>

So now I have the ability to design Main.html and still have the panel in a separate file.

Enter-prise Java or Enter-the-dragon Java?

Java frameworks have become penny a dozen with no end in sight of any java developer not dissatisfied with any given frameworks. Every other framework claims it is better than the other one, because its APIs provide much flexibility. The truth is no framework provides a complete solution.

Debates on decisions on which framework to use has pretty much become part of a new enterprise project.  JSF is pretty heavyweight? Can Spring’s  xml configuration pretty soon get out of control ? Is mixing @Annotations, column names, field lengths, constraints, primary key, foriegn key, join columns in the POJO a really good approach ?  (One of these days we shall have an annotation to have all the data within the pojo.  Everyone wants Ajax behaviour now. Is Tapestry worth it or will Tapestry 6 be a complete rewrite yet again ? May be just stick to servlet and JSP ? How about EJB3 and reliving its nightmares ? Flex anyone ?

Blogs and Forums are full of debates about Spring vs Seam, JSF vs SpringFaces, Struts vs Tapestry, Yin vs Yang frameworks. There are people who adore JSF and there are who abhor JSF. I dont think its anybodys fault. It probably has to do more with how the brains are wired. Left brained guys like JSF, while the right brained guys like Spring. Or vice-versa.

Two of the technologies I have been tracking very actively recently are Wicket and Groovy.

When I start writing code using Wicket, Im reminded of my Swing days – oh how nice for a change it is to write ONLY in Java? Instead of all the lame scriptlets of two line Java codes thrusted into html (JSP), opening curly braces in header.jsp and closing it in catch.jsp. Or XMLs containing Java like code (like ActionScript). Or XMLs defining flows and subflows with hard-to-follow ELs. Im realizing that JSP is really an insult to a good programmer’s intelligence and XML is an insult to human capacity to understand languages. Is XML the “human readable format for machines” ? Duh?

There are other component frameworks like Wicket, but Wicket’s simple, easy to understand API really is cool and intuitive. No WTextField or WLabel .. its simply TextField or Label. That simplicity makes a lot of difference. It just wires to the brain quickly. No xmls or logic in the views. Whew! Models and Nesting models take a bit to understand, but it can reduce cyclomatic code complexity quickly. With Model 2 architecture, most of the OO stuff in Java has been relegated to extending MyServiceImpl from AbstractServiceImpl and a few inheritances here and there. Wicket changes all that. It lets the HTML itself be designed with inheritance, encapsulate components and hide unwanted details. 

Groovy meanwhile is what can be termed as the “Missing Java Functions”.

I hope Wicket grows quicker and Groovy’s feature-set start attracting more developers. After all programming is an art and it is all about enjoying the art.