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:
- Form Components: TextField, Button
- Processing the submitted input
- Validation of user input
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 firstname.lastname@example.org.