Java HTML Report in a Few Lines of Code
A practical example of how to build real-world applications in Java and create a simple but useful front-end with basic HTML.
Join the DZone community and get the full member experience.
Join For FreeToday I’d like to show you a simple table HTML report created with only thirteen lines of source code, written in a single command line using the Java programming language. Let’s pretend the data provision service already exists. If we wanted to offer our users some simple (sequential) content filtering for a table with column sorting, our implementation will have to add a few extra lines of code. To optimize this filtering, we’ll need to dig deeper into the backend. The web component takes its data from an object of type Stream, and so the maximum volume of presented data is limited only by the capabilities of our web browser. For my data source I used a freely available list of hotels in CSV format and it shouldn’t matter that some of the information it contains isn’t up to date. Let’s take a look at the body of the doGet()
method of our trusty old Java servlet for those thirteen lines of code we mentioned. We’ll assemble the model of our table using the ReportBuilder class from the Ujorm framework.
xxxxxxxxxx
new ReportBuilder<Hotel>("Simple Hotel Report")
.add(hotel -> hotel.getName(), "Hotel", NAME).sortable(true)
.add(hotel -> hotel.getCity().getName(), "City", CITY).sortable()
.add(hotel -> hotel.getStreet(), "Street").sortable()
.add(hotel -> hotel.getPrice(), "Price").sortable()
.add(hotel -> hotel.getCurrency(), "Currency")
.add(hotel -> hotel.getPhone(), "Phone")
.add(hotel -> hotel.getStars(), "Stars").sortable()
.setFooter(e -> e.addText("Data source: ").addLinkedText(HOTELBASE, HOTELBASE))
.build(input, output, builder -> selectHotels(builder,
DEFAULT_ROW_LIMIT,
NAME.of(input),
CITY.of(input)));
Each call to the add()
method adds another column to our table. The first argument of this method contains the code for getting the contents of a table cell, the second contains the name of the column header. If we want to filter the column, we also pass a constant representing the HTTP parameter of the web page. To support sorting, we add a call to the sortable()
method, whose (optional) parameter determines the direction of sorting, but this is only for graphical representation of the data, the following method takes care of the actual sorting of the data. Due to licensing terms and conditions, we have to add a link to the original data project, inserted in the footer using the setFooter()
method. The title of the HTML page is generated implicitly from the text provided in the constructor of the builder, however, using the setHeader()
method, we can replace it with our own implementation. The build()
method then calls the data source method, with the attached code:
xxxxxxxxxx
private Stream<Hotel> selectHotels(GridBuilder<Hotel> builder,
int limit,
String namePattern,
String cityPattern) {
final String nameUp = namePattern.toUpperCase();
final String cityUp = cityPattern.toUpperCase();
return service.loadHotelStream()
.filter(t -> nameUp.isEmpty() || t.getName().toUpperCase().contains(nameUp))
.filter(t -> cityUp.isEmpty() || t.getCityName().toUpperCase().contains(cityUp))
.sorted(builder.getSortedColumn().getComparator(Hotel::getName))
.limit(Math.max(0, limit));
}
To ignore character case, we start by converting the values of the parameters to capital letters, but how we go about implementing an appropriate filter is up to us. If the data type of the column implements the Sortable
interface, we can sort using a comparer provided by the GridBuilder
object, otherwise we have to write the implementation ourselves. And, finally, we limit the number of rows to return only the top amount. With large amounts of data, it would be more appropriate to switch the last two lines, so as to sort only a smaller number of records. I’d also like to point out, that all our HTTP POST requests should be directed toward the servlet’s doGet()
method. That should be everything important, after running the project we should get a result similar to the one in the following image:
As the screenshot indicates, the table is automatically redrawn on any change of the text filter, and although the page also works in browsers without JavaScript support, we’ll have to confirm our filter values by pressing the Enter key. The AJAX behavior can also be suppressed programmatically – using the method setAjaxEnabled(false)
. All the parameters of the page’s form can be set using URL parameters, the ReportBuilder
object doesn’t save any values to the Session.
Conclusion
It’s true that the ReportBuilder
provides more than just the rendering of the table, instead it takes care of the whole page. The table itself is rendered using the GridBuilder
class, in this example we can see how such components could be assembled into a greater whole. The solution relies on objects from the Element class, as was mentioned in the last blog post.
To run the project, you’ll need JDK version 8 and a web browser with support for JavaScript Vanilla ES6, but the JavaScript used here doesn’t require any further libraries. The whole project is now freely available on GitHub. The project can be run in Windows using the run.cmd
script (on Linux using the run.sh
script). On first execution, the necessary libraries will be downloaded. Next time we’ll take a look at the possibility for cell formatting in this table.
Useful Links
- Project on GitHub
- JavaDoc for ReportBuilder a Element classes
- A Simple AJAX Website in Java (an
Element
class introduction)
Published at DZone with permission of Pavel Ponec. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments