David's Blog

Deliberate Practice is Overrated

In the past few years, an idea has grown in popularity among software developers: That "Deliberate Practice", that is practice only for the sake of practice, is the best way to improve your programming abilities. Code retreats, for example, formalize this very strictly: Every 45 minutes, you delete all the code. While code retreats are fun and you can indeed learn a lot there, I still think that this idea of "Deliberate Practice in Software Development" is overrated.

When people argue that software developers should do deliberate practice, they usually say something like "Good musicians don't just play beautiful music every day. They spend hours practicing scales." But can you really compare music to software development? I think not. And yet I have not seen a single empirical study backing that deliberate practice makes you a better developer.

I know one example does not prove anything, but here's how I try to improve my skills: I pick an interesting project and work on it. For weeks or months. And I try to ship something to the public at the end - Usually I decide upfront what I want to ship. And because it's a side project anyway and there is no schedule pressure, I try to do really good work.

Working on a project for several weeks or months has some advantages to doing a Kata and then deleting the code. For example, I have to live with the decisions I made earlier. I have to refactor as I learn, and I have to grow an architecture. I tried learning clojure just by doing the examples from the book. For weeks, I just didn't get it. Then I decided to start a project using clojure. Now I see progress in my learning every day I work on the project.

I said before that you can not compare practice in music to practice in software development. This is because musicians practice mechanical skills. This is compared to us developers learning to touch-type or learning the keyboard shortcuts of our IDEs. Of course we should practice these mechanical skills! And of course we should learn to recognize patterns and read code! But that does not mean that you have to deliberately practice programming itself:

There's a difference between what we do as software engineers and what a violinist (or anything else that requires physical practice would do). A violinist spends hours practicing methodically because they are teaching their brain very specific patterns of how to interact with an instrument.

Practicing software engineering also involves learning patterns. The more projects you do, the more you will learn (hopefully) about what works and what doesn't.
DXM on stackexchange programmers

It is said that it takes 10,000 hours to become an expert, although it might be more like ten years. But this does not necessarily mean that you have to do deliberate practice the whole time. Craftsmen usually learn on the job. They learn to create beautiful things while creating beautiful things. If software is a craft - and I really believe it is - we should create beautiful things (and maybe try to ship them) and learn as much as we can in the process.

I think, at least in this respect, programming has some things in common with photography. In photography, there is no sense in deliberately practicing something. Just go out often and try to shoot beautiful pictures. If the light is bad, you'll automatically practice available light. If your subjects are moving fast - action pictures. And so on. So, in closing, I want to quote Mike Spinak, a greate nature photographer:

If you want to learn how to spot meter, you don’t need to sit in your living room and take practice shots spot metered on the door, the wall, the window, the carpet, etc. If you want to learn macro photography, you don’t need to take practice shots of pawns on a chessboard. If you want to learn off-camera flash photography, you don’t need to take practice shots of your bored son sitting on a stool with his hands in his lap, staring vacantly. Nothing is stopping you from doing real photography – i.e., trying to make worthwhile photos – and learning your spot metering, macro skills, flash techniques, etc., in real photography situations, instead.

If you want to better your photography, then treat every shutter actuation as an opportunity to make something significant. Treat it that way by making your best effort. Learn by actually doing, not by setting unnecessary, artificial boundaries, and then hollowly going through the motions.
Practice makes practice

You might also be interested in...

Posting Type: 

Leiningen repl java.lang.ClassNotFoundException: org.codehaus.jackson.JsonFactory

In some cases, "lein repl" will fail with "java.lang.ClassNotFoundException: org.codehaus.jackson.JsonFactory". I have solved this problem, at least for my project. Read here why.

As I wrote before, I am currently learning clojure, and so I implement a simple web applicatoin. I build and run this application using Leiningen. There I encountered a problem: When I run

> lein clean
> lein run

...and then try to launch a repl, it fails with

> lein repl
Compiling newsreader.server
Exception in thread "main" java.lang.ExceptionInInitializerError, compiling:(clutch.clj:1)
        ... A very long stack trace ...
Caused by: java.lang.ClassNotFoundException: org.codehaus.jackson.JsonFactory
        at java.net.URLClassLoader$1.run(Unknown Source)
        ... more stack trace elements ...

This seems to be caused by a known problem in leinignen. Anyway, I want to run the server AND the REPL. I recognized that, when I run

> lein clean
> lein repl

the REPL will work fine, but the server won't start anymore. The solution - at least in my case - is quite simple: Start the server from the REPL:

> lein repl
Compiling newsreader.server
    ... more output from the REPL ...
newsreader.server=> (-main)
Starting server...
2012-11-14 09:44:25.918:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
Server started on port [8080].
You can view the site at http://localhost:8080
#<Server Server@f6dd4>
newsreader.server=> 2012-11-14 09:44:25.919:INFO::jetty-6.1.25
2012-11-14 09:44:25.938:INFO::Started SocketConnector@0.0.0.0:8080

newsreader.server=> (+ 2 3)
5
newsreader.server=>

And this works really well for me. Now, if only SublimeREPL would already work with leiningen2...

You might also be interested in...

Posting Type: 

OpenID in a clojure web application using openid4java

In the last couple of weeks I have been trying to learn clojure. I startet to implement a simple web application so I have a playground where I can try things (It doesn't really do anything at the moment, but I'll write about it in a later post). I use the noir web framework to write this web application. In this web app I wanted to use OpenID, so I can log in with my google account.

I came across clj-openid by Steve Lindsay, but it still looks a kinda incomplete. I also found friend by Chas Emerick, but it seems to do everything which is too much for me. I decided to try openid4java, which I know from writing gclimbing.com. I know friend uses openid4java too, but I wanted to use it directly - at least for now.

I probably wrote some suboptimal - or even ugly - clojure code along the way. Please contact me if you have any suggestions what I could do better!

I first added openid4java-consumer 0.9.5 as a dependency to project.clj (0.9.6 does not have a jar on maven central, so I use 0.9.5 for now):

(defproject newsreader "0.1.0-SNAPSHOT"
            :dependencies [[org.clojure/clojure "1.4.0"]
                           [noir "1.3.0-beta3"]
                           [org.openid4java/openid4java-consumer "0.9.5"]]
            :main newsreader.server)

Then I created two helper functions, one which starts the OpenID request (redirect->openid) and one to process the response (verify):

openid.clj

(ns newsreader.openid.openid
  (:require [noir.request]
            [noir.session :as session]))

(def ^:private consumerManager (org.openid4java.consumer.ConsumerManager.))

(defn redirect->openid [oidUrl returnUrl]
    (let [discoveries (.discover consumerManager oidUrl)
          discovered (.associate consumerManager discoveries)
          authRequest (.authenticate consumerManager discovered returnUrl)]

    	(session/put! :newsreader-oid-discovered discovered)
        (.getDestinationUrl authRequest true)))

(defn verify []
    (let [request (noir.request/ring-request)
          openidRequest (into {} (for [[k v] (:params request)] [(name k) v]))
          responseParameters (org.openid4java.message.ParameterList. openidRequest)
          discovered (session/get :newsreader-oid-discovered)
          receivingUrl (str (name (:scheme request)) "://"
                            ((:headers request) "host")
                            (:uri request)
                            "?" (:query-string request))
          verification (.verify consumerManager receivingUrl responseParameters 
                                                discovered)
          verified (.getVerifiedId verification)]

        (session/remove! :newsreader-oid-discovered)
        verified))

Using the code is quite simple: Redirect to the return value of redirect->openid (this is what the /login page does). Use verfiy in the OpenID response page (/openid-return). The result of verify is an Identifier - It should be used to uniquely identify the user.

login.clj

(ns newsreader.views.login
  (:require [newsreader.views.common :as common] 
            [newsreader.openid.openid :as openid]
            [noir.request]
            [noir.session :as session])
  (:use [noir.core :only [defpage]] 
  	    [hiccup.core :only [html]]))

(defpage "/login" []
        (ring.util.response/redirect 
            (openid/redirect->openid "https://www.google.com/accounts/o8/id"
                                     "http://localhost:8080/openid-return")))

(defpage "/openid-return" {openidns "openid.ns" openidmode "openid.mode"}
    (str "now verified: " (openid/verify)))

Integrating openid4java was pretty easy. The resulting code (in openid.clj) does not look especially nice, but it's only a single file with 2 functions so I can live with that. Maybe I'll try friend in a later version, but for now I think I am fine with this code.

Posting Type: 

JSXP Tutorial videos

I have just finished some tutorial videos for the jsxp Web Framework.

The first video shows how to set up an eclipse project so you can use jsxp:

The second video shows how to use variables and element templates:

In the third video you'll learn how to use element templates to display repeating data:

And the third video shows how you can add third party components (or your own components) to your pages:

Posting Type: 

Wicket Screencast 03: Repeating Views

Wicket Screencast 03 - Repeating Views

This screencast is part of a series about apache wicket. You can find the whole series and additional information on the Wicket Newsletter Screencast page. In this episode you'll learn the basics about repeating views in Wicket:

  • RepeatingView: The simplest repeater component
  • ListView: For displaying Lists of Data
  • DataView: For displaying all kinds of data
  • Pagination

Transcript

Welcome to the third episode of my wicket screencast. Today's topic is "repeating stuff". We will display lists of data using ListView, RepeatingView and DataView. I will also show you how to use pagination. My name is david, you can find out all about me on my blog, davidtanzer.net, or you can follow me on Twitter, my name there is @dtanzer.

I have changed the application a little bit since the application a little bit since the last episode. For example, I have created a page class called "ListNewsletters" and added the imports we'll need later, so you don't have to watch me type import statements (which is rather boring). This HTML file ("ListNewsletters.html") was already part of the project skeleton. It is a mockup of the newsletters list. But you can see, this mockup does not only contain the newsletters list. It also contains some text that should only show when there are no newsletters available, the so called "blank slate".

This [blank slate] is here because an empty list does not look good. You should always display some blank slate instead of an empty list when there is no data to display. At the moment, both the blank slate and the actual content will show at the same time, but I want to change that now.

The blank slate should only show up when there are no newsletters, so we need the newsletter repository. For the repository, we need the size, which is the number of available newsletters. The blank slate and the content will be "WebMarkupContainer"s. WebMarkupContainer is a wicket component that does nothing. It is just a representation of some HTML in the page class.

I have already added the WebMarkupContainer for the blank slate, which only shows when the size is 0. And now I add another WebMarkupContainer for the content, which only shows when the size is not 0. Now I can compile and run the application, and after gradle has started the web server we should see that only the blank slate shows, and the list has disappeared.

The blank slate contains a link to the "create newsletter" form. This link in the mockup directly references CreateNewsletter.html, so it does not work yet, because it should not link directly to the static page but instead to the wicket page. For this we simply use "wicket:link" and add the correct path, and now wicket knows how to create the link so it references the "create newsletter" page.

When I restart the server I can click the link to create a new newsletter. After I have created the newsletter, the blank slate will disappear and the list of newsletters will show. This list of newsletters will, of course, still be empty, because we have not created any code to show the list yet.

Before I'll populate the data I will start with a simpler example. I will create an unordered list which should contain the names of all newsletters. To create this I use the wicket component "RepeatingView". A RepeatingView lets you add an arbitrary number of other components, so we add a new label for every newsletter we know. I got the list of newsletters from the repository, and to get this list I have to specify two parameters: The first newsletter we want to get and the number of newsletters. We just want to get the first 100 newsletters in this case. Don't worry about the literal numbers, I will refactor this later anyway.

I iterate over all these newsletters with a foreach loop, and for every newsletter entity I add a label that shows the name of the newsletter. I don't use a literal wicket:id here, I use "newChildId", a method from RepeatingView to get an id that represents the next child of the repeating view. Not the page shows an unordered list with one entry. This entry shows the name of the newsletter we created earlier.

There is a better way to display lists of stuff in wicket: The ListView. ListView takes a java.util.List, iterates over it and calls a method for every item. I create an anonymous inner class of ListView and I have to override the method "populateItem". The ListView will create a ListItem object for every item in the newsletter list and will call populateItem for every ListItem. In populateItem I get the newsletter entity from the list item and I add a label to the list item. The label contains the name of the newsletter. For this label I need an id. I use the id "name, there is no method "newChildId" anymore. The list allows us to specify how it will be rendered in the HTML file, so I add a span with the wicket:id "name" there.

When I reload the page, you won't notice any difference at first, because we show almost the same HTML code. But when I inspect the page you can see that the "li" tag contains a "span" tag, so we really show the ListView now and not the RepeatingView anymore.

But there's still a problem with this code: Actually we don't want to show a list, we want to show the content of the repository! We only got the list because we received the first 100 items from the repository. What we really want to do is display some arbitrary data, and this arbitrary data is the whole content of our repository.

To do this, we create a DataView. The DataView does not display the content of a list, it gets its data to display from a DataProvider. I have to creat a class "NewsletterDataProvider", and this class has to implement the interface "IDataProvider". This interface defines four methods: "detach", "size", "iterator" and "model".

We don't need "detach" right now. The "size" method should return the number of items that can be displayed, and the "iterator" method should return an Iterator for a range of items. The range is specified by the index of the first item and the maximum number of items in the range. The last method we have to implement is "model", which creates a "IModel" for a given object. Notice that I didn't change the populateItem method from the ListView to the DataView. I just changed the type of the parameter from ListItem to Item, but everything else can stay the same.

Again, when I run the application now we should not see much of a change, because we render the same HTML as before. Now this list works pretty well, but we don't want to show an unordered list, we want to show the table from our mockup. We can just change the design of our data view without changing any java code at all. We simply re-assign the wicket ids, and that's it.

Now when we reload the application in the browser, we will see that the unordered list is gone, and that the table works. Now I add some more newsletters so you can see how a longer list looks like.

This list could become pretty long, so I want to add pagination here. To do this, we need another placeholder in the HTML with a wicket:id where we can show a PagingNavigator component. The PagingNavigator component is a wicket component that adds pagination to any other component that implements "IPageable" (the DataView does this). We want the data view to display only 5 items at a time. I specify this by adding another constructor parameter, and I add a PagingNavigator to the page. The PagingNavigator has to know the list, and that's it, now we have paging functionality.

The pager does not look very pretty, but you can change this with some simple CSS rules.

Now you should know how to display repeating data using DataView, ListView and RepeatingView. In the next episode we will refactor the application. I will show you how to move some aspects out of the page classes to achieve a better separation of concerns. If you have any further questions, please contact me, my email address is business@davidtanzer.net, and my name is David.

You might also be interested in...

Posting Type: 

3...2...1... Launch

This blog posting is part of the Freelancer to entrepreneur series.

Yesterday we activated the first users at zensmb.com. And then... not much happened. But I think that was to be expected. But let's go back to the start.

In July, just about three months ago, I posted Freelancer to entrepreneur - Week 1. I had just started working on a product. Three weeks later, our landing page went online: zensmb.com. I started using it immediatley for my own invoices. Then, just about a month ago, I started telling people about it per email. Some of them registered for the beta test. And some others registered after following our google ads.

And now we activated the first users. We have been navigating in the dark for much too long. We built much more than a MVP, and we hope that this was not a mistake. Still, activating those users was hard. I was afraid. What if all the feedback was negative? What if everything crashed? Still, we had to do it. So, yesterday evening, our first couple of users received their registration keys.

Then nothing happend. But then, this morning, I received two support emails. One customer asked what a specific field in our registration form meant. The other email was a stack trace. A stack trace! First I panicked. Then I saw that it was a minor problem. I fixed it and I also changed the wording of our registration form.

Now everything is running again. We are still waiting for some real feedback. In the mean time I will keep improving some minor things. And later I will start to implement the next big feature - A feature that I have been missing all the time since I was using the service for my own stuff.

Only time will tell if zenSMB will be a success. But the last three and a half month were a great time for me. So far, this was absolutely worth it.

Discuss on Hacker News

Posting Type: 

Wicket Screencast 02 - Forms

This screencast is part of a series about apache wicket. You can find the whole series and additional information on the Wicket Newsletter Screencast page. In this episode you'll learn the basics about user input in Wicket:

  • Forms
  • Form Components: TextField, Button
  • Processing the submitted input
  • Validation of user input

Transcript

Hi and welcome to the second episode of the wicket screen cast! Today I will show you how to process user input with apache wicket: We will implement the "Create Newsletter" form you already saw in the first episode. My name is David Tanzer, you can find out more about me on my home page davidtanzer.net and you can follow me on twitter, my handle there is @dtanzer. Now, let's get started!

I have made some minor changes to the project skeleton. For example, I have moved one HTML file that we have not used yet and I have made some minor changes to a class from the business logic: NewsletterRepository. You can download the newest version of the project skeleton at davidtanzer.net/wicketsc.

But now let's get started with this episode. In this episode we need access to the backend, and I want to access the backend using dependency injection. For this I want to use Google Guice, you can, of course, use Spring Framework or any other DI container if you want.

For using Guice I need to register the GuiceComponentInjector, this is a class that bridges the gap between Apache Wicket and Guice. This component injector needs a module - This is something Guice-specific. The Module is a Java Class which configures the dependency injection. I have already created such a module, it's called "NewsletterModule" in our case. My NewsletterModule needs a database path, this is where the database files will be stored. I want them to be stored in the root of the web application, so I call getServletContext().getRealPath(...).

Now DI is set up and we can start implementing the CreateNewsletter form where we will need the NewsletterRepository from the backend. The first thing I want to do is, I want to show the correct number of existing newsletters in the "create newsletter"-page. As you probably remember from the last episode, we used the hard coded value "5" back then. But now we want to get the real value from the database.

For this we need the "NewsletterRepository". This is a class from our backend which is responsible for managing all the newsletters. We want Guice to give us an instance of this repository, so we simply annotate a private variable with "@Inject", and Guice will take care of setting the right instance when the page class is created.

Now we can set the value of our "numNewslettersModel" to the correct value. We have to change the data type because the repository returns a "long" value in its "size()" method. Now we can build and run the application and we should already see the correct number, which is "0" in our case because we have not created any newsletters yet. We can only test this later when we have the code to create newsletters. For now it will stay 0.

Now we can finally start the main part of this episode: We can implement the "create newsletter" form. For this we have to change the HTML file slightly because we have to assign wicket ids to all the parts of the form that will be components. We assign a wicket:id to the form itself, to the text field and the button. The text field will be responsible for reading the user input and the button component will process the "onSubmit" event of the form.

In this case, the form would not necessarily need to be a component, but it's a good idea to create a component on the Java side anyway because it will help with testing later. But this is a topic of a later episode. Let's start with importing the 3 component classes we need right now: Form, TextField and Button.

First I create the form. The form needs a generic parameter. In this case we don't care about it so we can use void here. You could use this generic parameter to assign a model to the form. The next component I create is the TextField. The TextField again has a generic parameter, but in this case, we need it. I use "String" as the generic parameter because the type of the model of the TextField is String. This means that the text field will be used to read String input from the user.

I create the Button as an anonymous inner class because the button will process the "onSubmit" event of the form, so it has to override the method "onSubmit". You can see that I have added the TextField and the Button to the newsletterForm, not to "this" [the page]. This is because the component hierarchy in the Java code has to match the component hierarchy in the HTML exactly. We would get a runtime error if I had added the text field or the button to "this" instead of the form.

I continue by createing a model for the text field. I again use a PropertyModel and I reference another property of the page itself: "newsletterName". Now I can implement the "onSubmit" method. What I want to do is I want to here is: I want to add a new newsletter and the redirect to the CreateNewsletter page to make sure the page is re-loaded. So I create a new NewsletterEntity, and here I can use the private variable from before, which will be set by the PropertyModel of the text field.

As I said before, in this case we would not necessarily need the form component, because we implement "onSubmit" here in the button. In a form like this, with only one button, we could also implement "onSubmit" in the form, then we would not need the button component. In a form with multiple buttons you need the button components in any case.

Submitting the form does not work yet, because I used a wrong name for the property in the PropertyModel. As you already know from last week, the PropertyModel gets 2 constructor parameters: An object and a name of a property. I searches a property with the given name in the given object. What I did is, I did not pass the name of the property ("newsletterName") but the varialbe itself, which is null at this point (and not a valid property name in any case). After I fix this error, submitting the form works.

Now the form is already working. I can enter a newsletter name in the text field, click the submit button, and a newsletter is created and saved to the database. But there is a problem right now: I could leave the text field empty and click the button, and a newsletter with no name would be created. So we need to validate the input from the user.

To display the result of the validation, I add a feedback panel to the page. In the HTML code I just need a placeholder, in this case a "div", and I have given it the id "feedback". In the java code I have created a FeedbackPanel component. I want to make the text field required, so I call the method "setRequired(true)" on the text field. Now it should not be possible anymore to leave it blank. Submitting an empty name produces an error message now, so this is already working.

But we can do better. I want all newsletter names to have at least 3 characters. For this I use the StringValidator, which provides all kinds of string validation. In this case we want to use the "minimumLength" validator, but I could add as much validators as I want to a component. I could even implement my own validator. But this is an advanced topic and I will not cover it in this screen cast.

This was the second episode of this screen cast about Apache Wicket. Now you know the basics about processing user input, forms and form components. In the next episode I will show you how to display repeating data when we will develop a list of existing newsletters. My name is David, if you have any further questions, please contact me! My email address is business@davidtanzer.net.

Posting Type: 

ScrumBut... and the long run

Last week, I wrote about ScrumBut. I wrote that you don't need to fully implement Scrum before you can start to do good work. That you can start with improving little things. On the other hand, Mike Vizdos wrote Modifying Scrum – You THINK you know better.... There he writes that "Modifying Scrum is a bad idea.". So, who is right? Or, could we both be right? I think we can...

You have probably heard this - Maybe from Management: "We do scrum here. But (all tasks need to be tracked with $EXPENSIVE_TOOL | the daily scrum has to be at 9am sharp | no, your team can not have a company credit card | we will schedule "high priority" work at any time, not during sprint planning | you have to work in 12 week sprints | your are not allowed to discuss $TOPIC during retrospectives | we need the TPS reports ready on friday). This will not work in the long run.

Last week my focus was on quick improvements. I wrote:

What might help is trying to change the organization your team has to work in. You can convince your managers that your team needs a full time ScrumMaster. You can start to educate people in you organization about scrum. And this will (probably) work. But only in the long run.

The long run is important too. Sure, you should try to do good work now. But you should also try to change what is not working - Even if it takes some time.

Because, if you don't try to change these things - or if your organization prevents this change at all cost - the whole Scrum thing will look like a farce. Your team will become cynical. They will start using words like "ScrumBut" (Or, as a co-worker once suggested, "Srum" - It's a little bit like scrum, but not quite). The team will no longer believe that it is empowered. That they are allowed and encouraged to change.

And things will start to get worse from there. The teams might stop trying to change things. They might stop trying to improve. They might even stop trying to do good work. And then a vicious circle starts, because Management will conclude that scrum does not work. That more control is needed. A second TPS report on Wednesday.

So, yes, try to do good work with what you have. But never stop trying to change what you have - even if it will take some time.

You might be also interested in...
Learn more about how I can help you save money and earn money by improving your agile software development process.

Posting Type: 

Wicket Screencast 01 - The basics

Wicket Screencast - The basics

This screencast is part of a series about apache wicket. You can find the whole series and additional information on the Wicket Newsletter Screencast page. In this episode I cover the basics of apache wicket:

  • How the project is set up
  • The application class
  • Wicket pages, separation of design and code
  • Simple components and models

Transcript

Hello, welcome to this screencast about Apache Wicket. Today I will show you the basics of wicket, that is pages, components and models. My name is David. I work as a consultant and trainer, and you can find out more about me and read my blog at davidtanzer.net.

Let's get started! As you can see, I use Sublime Text for all my editing [For this screencast. Most of the time I use an IDE. But this screencast should not be about the IDE, it should be about wicket]. You can, of course, use eclipse or any other IDE. I use gradle to build the project and later to run the web application.

I have created a skeleton project which pretty much follows the standard gradle or maven layout. We have a source directory which has two sections: "main" and "test". The main section contains three actual source folders: "java", "resources" and "webapp". The "webapp" source folder only contains the "web.xml" deployment descriptor that I have already created.

First let's have a look at the build file. I use the java plugin because, well, it's a java project. And the jetty plugin because I will use the jetty web server to run the web application. I have also included the sublime text plugin because I use the Sublime Text editor. You can use, for example, the eclipse plugin if you want to use eclipse. This project already has several dependencies. We need "wicket-core" and later "wicket-guice", both in the latest version. For the backend we need JPA and a database. Later we'll also need JUnit to test everything. The rest of the build file is not that important. It's a little bit of book keeping and configuration for the sublime text plugin.

Let's go back to the web.xml deployment descriptor. As you can see I have configured the wicket filter to be applied to every URL pattern, so all the URLs are passed through the wicket filter and are part of the wicket application. The wicket filter needs an application class name. The application class is the main entry point of your application. So, let's create the application class.

As you can see here in the deployment descriptor, I want to name my application class "NewsletterApplication", and it has to be in the package "net.davidtanzer.wicket.newsletter". So, let's first create the file and create the class in the correct package. The class must extend the wicket "WebApplication" class, so let's add that. Add the import too. This is something where and IDE will probably help you a lot.

WebApplication is an abstract class and we need to implement a method that returns the home page [of the application]. For this we need to import the page class. The method that returns the home page is called "getHomePage". And we don't need it yet, so we return null. Let's build everything so we see if everything works. It seems like I got the import wrong here, of course, I have to import the "Page" class, not "WebPage". But now everything should compile and for now we are finished with the application class.

The fact that there is a method "getHomePage" and something like a page class already hints us to an important concept of wicket: Wicket has pages. A page is something that is served to the user's browser - A html page. And anther important concept in wicket is a strict separation of design and code. The design is done in simple, standards compliant HTML files. I have prepared one such file. It only contains a form to create new newsletters and it has not any program logic yet. The form is not very pretty (yet), and we will also not implement it today, this is what we'll do in the next episode. Today we only want to add a simple "Label" component to the page.

As I said, the design is strictly separated from the code, and the code is a simple java class that extends "WebPage". We will now create th code for this HTML file, for "CreateNewsletter.html". The way wicket finds the code is by looking at the name of the file. The HTML file and the Java class have to be in the same package and have to have the same name. So we create the java class in the package "net.davidtanzer.wicket.newsletter.web.admin" and we save it as "CreateNewsletter.java".

What's left now is: We have to extend the WebPage" class. The fact that [this class] is a WebPage and is called CreateNewsletter tells wicket that it should load "CreateNewsletter.html" when the page is served. The class WebPage is a subclass of the Page class we used earlier in the application, so we could use this class as the home page. We probably don't want to do this because this is an administration page.

The WebPage class is a special form of pages for serving HTML pages. Most of the time it's the only page class you need. Later we will subclass this page class ourselves to add some projct specific functionality.

As I said before, we do not want to use the administration page as the homepage of your application. But we want to be able to access it anyway, so we want to mount it. That is, we want to create a special URL, "admin/add", where we can find this page. After that, when everything compiles again, we can start the server and access this URL. It should show the administration page. It will show the "add newsletter" form.

I start the server with "gradle jettyRun". When you start it for the first time it will take some time to get up and running, but now it's there and we can access the page.

As you can see, the newsletter form that we looked at before is now running in our wicket application. This brings us to another important concept of wicket: Component orientation. Everything you see on the page, the textfield, the button, can be a component. A component is some part of the HTML which you can access and modify in the code later. Now we want to create a very simple component: A label, which shows the number of newsletters.

For this we create a "span" HTML tag and assign a special ID - the "wicket:id" "numNewsletters". What we have to do now is we have to add this component to our page and we will do this in the constructor of our page. I want to add a "Label" component so first I create a new "Label" object. Every wicket component expects a "wicket:id" as it's first constructor parameter. This wicket id is how the component finds the markup (the HTML tag where the component should be rendered) in the HTML file. To make sure the page class finds the component I have to add the label [to the page object - "this"].

This would already work, but the label does not know what text to show yet. So, let's first add some static text. This is a rather boring use case, because we could have added the static text directly in the HTML file. This is just to show you that the label will display the text. Now the label shows up in the page.

What we really want to do here is display some information from our domain model. For this we can use the "Model" that almost every wicket component supports. The label not only shows static text, what it really does is to take some value from a model [and display it]. A model is anything that implements the wicket "IModel" interface. We use the PropertyModel which is very handy. The property model tells wicket "Take the given object - this - and search for a property - called numNewslettersModel in our case". We have already created a private variable "numNewslettersModel". Wicket will use reflection to read the value of this variable and display the value in the web page.

This value, 5, is still static, but you can imagine that you can use models and PropertyModel to access data from your domain. We will do this later in this screen cast series.

So, those were the basics of apache wicket. We talked about pages, components and models. And we created a simple label that wrote some text to the screen. In the next episode I will show you how to process user input. We will talk about forms and form components.

This screencast only covers the basics of apache wicket, if you want to know more, just drop me an email! My address is business@davidtanzer.net. Then we can talk about how we can work together.

Posting Type: 

Wicket Screen Cast

01 - The basics

In this episode I cover the basics of apache wicket:

  • How the project is set up
  • The application class
  • Wicket pages, separation of design and code
  • Simple components and models

Read the transcript here: 01 - The basics - Transcript
Download the project skeleton here: 01-wicket-newsletter-base-version.zip

02 - Forms and user input

In this episode you'll learn the basics about user input in Wicket:

  • Forms
  • Form Components: TextField, Button
  • Processing the submitted input
  • Validation of user input

Read the transcript here: 02 - Forms and user input - Transcript
Download the project skeleton here: 02-wicket-newsletter-before-form-episode.zip

03 - Repeating Views

  • RepeatingView: The simplest repeater component
  • ListView: For displaying Lists of Data
  • DataView: For displaying all kinds of data
  • Pagination

Read the transcript here: 03 - Repeating Views - Transcript

Posting Type: 

Pages

My name is David Tanzer and I have been working as an independent software consultant since 2006. I help my clients to develop software right and to develop the right software by providing training, coaching and consultanting for teams and individuals.

Learn more...

Subscribe to RSS - David's Blog