One of the projects I am currently working on is an eCommerce site based on WebSphere 7.0. Although I can’t go into too much detail about the project, we have been using beans (among other things) to tame the data layer, which can easily become unkept if not turn into a complete mess of code spaghetti!
JSP / JSTL code suffers from being poorly encapsulated, untestable and fragile. It isn’t really a good language (there are better) to be doing heavy lifting, the ideal is to have very lightweight JSP templates containing very minimal amounts of logic.
Some of the solutions to these problems can be to:
- Create custom tags, in JSTL and / or Java.
- Careful use of imports VS includes: includes are more performant, however, they also cause variables to be shared between templates making it hard to maintain.
- Do more heavy lifting for the display logic within action handlers.
In this post I will be stepping into the basics on how Java beans can be used to trim down the amount of logic in the JSP templates. By having a library of useful, tested functionality, we can significantly reduce the amount of code and bugs created when putting together JSP display logic.
Anatomy of a Basic Bean
To start with we will look at a basic bean, it can simply be used to encapsulate some existing data and provide methods to perform more complex queries on that data in a reusable and testable way.
For our example we are going to use the following simplified JSON example response, on which we will model our bean:
{ "Products": [ { "Name": "32\" WideScreen TV", "InStock": false }, { "Name": "40\" 4K TV", "InStock": true } ] }
The following is a shell of our bean, notably it extends java.io.Serializable but beyond that it is a plain object with a setter that we will use to pass the response data and some getters that we will use to provide a useful query interface:
package com.example; public class ProductViewResponseBean implements java.io.Serializable { public ProductViewResponseBean() { // Code here } public void setResponse(Map response) { // Code here } public List<Map> getInStockProducts() { // Code here } public List<Map> getOutOfStockProducts() { // Code here } public List<Map> getProducts() { // Code here } }
I haven’t filled in the implementation details for this code (I will go through implementing concise bean code in a follow up), but you can probably imagine what this will look like. Using this bean within our JSP templates is fairly straightforward:
<%-- Retrieve the response --%> <wcf:rest var="productViewResponse" url="..."/> <%-- Instantiate our new bean --%> <jsp:useBean id="productView" class="com.example.ProductViewResponseBean"> <jsp:setProperty name="productView" property="response" value="productViewResponse"/> </jsp:useBean> <%-- Utilise our query interface --%> <c:forEach var="product" items="${productView.outOfStockProducts}"> <%-- Doing stuff --%> </c:forEach>
In the follow up blog I’ll fill out the implementation details, and discuss how we can create a concise implementation and how that compares with the equivalent JSTL.
Cheers all!
Stuart