Developing Great Software
Wednesday, April 29, 2009
With Oracle's acquisition of Sun Microsystems the big question in my mind and those of many dedicated Netbeans users is what will happen to the Netbeans IDE platform? Will we ever see a release of Netbeans v7? While the release of Netbeans v6.7 is highly anticipated, its development was begun under the auspices of Sun, who throughout the years has steadfastly committed itself to the platform. Will Oracle follow suit and provide the level of human, financial and organizational capital that will be required to take Netbeans to its next generation? I guess we will have to wait and see but I think you can guess what I am hoping.
Sunday, April 5, 2009
[***Note This is the second and final article in this series and requires that you have completed the exercises in the first article in this series. If you haven't already, please do so now before preceding with the exercises in this article.] This is the second and final article in this series of using JPA/Hibernate and Wicket repeating views. This article will cover the remaining tasks that will allow us to render the the data from the Customer table in a tabular view to the browser using Apache Wicket repeating views and models. Wicket's Repeating Views Wicket's repeating views allow you to render data from a collection of objects, such as a List
It is a model that can be serialized to the page store without its data; its reference to its data is declared as transient. . HTML tables can be used to display the information in the browser where each row in the table represents one item in the List collection and columns in the table represent each List item's fields.
The markup we want to generate for this exercise is an HTML table with the following elements:
IDataProvier is really nothing more than a wrapper around a collection. It It implements IModel and IDetachable.
LoadableDetachableModel calls its load method when the view component it is attached to needs access to its data. This allows clients, which implement this method, to load the data it wraps from any data source, a database for instance.
We will see an example of using the LoadableDetachableModel later in the exercise when we implement the code for the view.
The DataView is a repeating view component. It makes it very simple to populate a repeating view from a database. DataView's are constructed as follows:
Both constructors take an id of String as their first parameter. Its value must be set to the wicket:id attribute of the HTML tag we are attaching the DataView component to.
Both constructors take an IDataProvider as their second parameter. The IDataProvider acts as an interface between the database and the Dataview.
itemsPerPage, an int, can be passed as a third parameter and is used when implementing pagination.
For this article, we will use the first constructor, which takes only two parameters, an id and an IDataprovider.
The IDataProvider Interface - a wrapper around data
extends IDetachable and publishes three methods that must be implemented:
Implementing an IDataProvider
Below is the implementation of IDataProvieder that will be used by our DataView component:
Let's discuss each of the methods in our implementation of IDataProvider:
There are a few things to notice in the above code:
Here is the complete code for HomePage.java:
Add some styling to our page
Lets add some styling to our page:
Here is the complete markup for HomePage.html. Notice how each of the wicket:id attribute values match the id values we passed to our DataView and four Labels :
- A table header with header columns for each of the columns from the Customer table that we want to display. For our exercise, we will display the Customer ID, Customer Discount Code, Customer Zip, and Customer Name columns from the Customer table.
- A table row for each of the Customer entities returned when we query the Customer table for its contents. The cells in these rows will contain data from their corresponding fields in the Customer entity objects that are returned when we query the Customer table. Their corresponding fields are customerId, discountCode, zip, and name.
- T getObject() - returns and object of type T.
- void setObject(T object) - set the model data to object of type T.
- void detach() - detaches the model data and is called after rendering has completed.
- protected DataView(String id, IDataProvider
- protected DataView(String id, IDataProvider
dataProvider, int itemsPerPage)
- iterator(int first, int count) - Gets an iterator for the subset of total data.
- model(T object - Callback used by the consumer of this data provider to wrap the object retrieved from the iterator(int, int) with a model (usually a detachable one).
- size() - Gets the total number of items in the collection represented by the DataProvider.
- iterator calls the CustomerJpaController's findCustomerEntities method with 2 parameters, count and first and will return an Iterator for the list of Customer objects that the findCustomerEntities method returns.
- size calls the CustomerJpaController's getCustomerCount method to get the count of Customers and returns the result.
- model creates and returns an anonymous LoadableDetachableModel
object which wraps our Customer entity object which will be detached after rendering has completed.
- detach has an empty implementation because we do not have any models directly associated with our implementation of IDataProvider that need to be detached.
We are attaching the DataView to an HTML element whose wicket:id is rows. We will discuss the HomePage.html markup later.
- populateItem will be called by the DataView component for each Customer object provided by customerDataProvider.
The field in the Customer object is identified by the id we pass to each Label's constructor. We are using a CompoundPropertyModel to bind the fields in the the Customer object to the four Label components.
- Because there is a 1 to many relationship between the Customer and the DiscountCode entity objects, we must use discountCode.discountCode to reference the discountCode field in the DiscountCode entity associated with the Custmoer entity.
- Right click the Web Pages node in the Projects pane and select New | Other which will open the New File window.
- Select Web from the Categories pane and select Cascading Style Sheet from the File Types pane and click Next.
- Enter style for the CSS File Name and click Finish which will open the style.css file in the editor.
- Fully expand the Source Packages node in the Projects pane and double click the CustomerJpaController node. This will open the file in the editor.
- Locate the
findCustomerEntities(boolean all, int maxResults, int firstResult) method and add order by o.customerId to the JPA query string.
- We create a Wicket DataView to render repeating data in an HTML table to the browser.
- We implement an instance of IDataProvider to act as an interface between the database and the DataView.
- Our implementation of IDataProvider's model method creates and returns a LoadableDetachable model.
- We assign a CompoundPropertyModel to the view, wrapping the Customer object.
- We create four Label components. Each is bound to a field in the Customer object. The field in the Customer object is identified by the id we pass to each Label's constructor.
- We modified our JPA query to return our Customer entities in customerId order.