The focus of this blog is software engineering – as you can tell from that catchy tagline at the top of the page. Some of the topics covered will include system architecture, application design, java standard edition and java enterprise edition, and web application security.
My goal is to present content which can help fellow software engineers solve problems. In my experience, teaching someone a skill helps both the student and the teacher.
This post discusses the benefits of paginating and lazy-loading large datasets that are displayed to users as well as the benefits of leveraging 3rd party JSF2 UI component suites. I’ve developed a simple application to demonstrate the concept which you can download and run. It is a maven2 project which uses PrimeFaces, Spring Framework, Hibernate/JPA2, and Ehcache.
Often times your application must display a large data set to its users so they can operate on it. The users might need to create, update, and delete rows in this data set. The problem is these data sets are too large to display on a single web page in a friendly manner. If you tried to show all the data at once, the scroll bar on the web page would be longer than a freight train and the page would feel just as heavy.
The previous post on the JBoss Drools Rule Engine gave a high level overview of the benefits of using it in your web application. This post explores a concrete example. JPetstore is a simple shoppingcart application whose products are pets. This online petstore is included as a sample application with the Spring Framework bundle to highlight some of Spring’s capabilities. What follows is how I modified JPetstore to leverage the JBoss Drools Rule Engine 5.2 (the commercial version offered by Red Hat is called JBoss Rules) so JPetstore could have some of the features we commonly see offered by online retailers.
It is common to see online retailers give customers who enter a coupon code during checkout a special offer. Some examples are:
- Buy 3 goldfish, get the 4th free.
- Buy “camera model A” and get “tripod model B” for free
- 10% off your order cost when you enter offer code X
- All batteries 20% off when using promo code X
- $10 off any order totaling over $100
- Buy any 3 car care products, get a free microfiber towel.
- Free shipping using code X
Many offers of this type are valid for only a short period of time – a week, a weekend, or even a single day (Black Friday offers).
This functionality calls for using a Rule Engine.
A rule engine could also serve as a “recommendation engine” – it can be used to recommend or suggest additional products to the customer based on their past orders, their user profile, etc. For instance, if you purchased car wax, the system might recommend their bestselling microfiber towel or something specific to your car’s year/make/model.
JBoss Drools Expert (or JBoss Rules for the enterprise version of Drools supported by Red Hat) is a business rule engine. You may have heard of a Rule Engine in the past but were unsure of how it can benefit you and your application. In the following paragraphs, I will list some of the benefits of using a Rule Engine in a traditional web application, the different formats used to express rules in Drools, and a general overview of how Drools is used.
In the last post, I covered Magic Numbers and how they can be used along with file extensions to validate file uploads. What would happen if you did not restrict the file types you users can upload and picked the wrong location to save them on your server? What if a user uploaded a JSP file?
Many web applications allow their user’s to upload files on their computer to the application’s remote server. An example of this type of application is an image sharing service where you can upload and share your vacation photos. This type of application has no reason to accept MS Word documents, PDF files, or mp3 files. It makes sense to empower the application to reject undesirable file types.
So how do you prevent users from uploading PDF files, MS Word documents, etc to your image sharing service?
Most web applications allow a user to query a database, retrieve a local copy of the queried data, make changes to that local copy, and then finally send the updates and the unchanged values back to the database.
These are often described as CRUD (Create, Read, Update, Delete) applications. An example would be a simple web registration form which would request from the user their first name, last name, email address, password, and mailing list preferences in order to create a profile on the site. In this scenario, we’ll have a one to one mapping of the user table to the form on a web page. An example of each CRUD operation would be:
- Create – registering on the site
- Read – logging in and viewing your profile
- Update – changing your mailing list preferences
- Delete – requesting your account be closed. Many times data is not actually deleted from the database, but instead an update is executed to set the status to “inactive”.
In this user profile example, only one person is updating the data (since only one person knows the correct password needed to access the record) so the data in the database is the same between the Read and Update steps. However, there are some web applications where multiple users can modify the same data set concurrently. These applications can suffer from the “lost update” problem.
Lost Update Problem
To illustrate the lost update problem, consider a web application which allows salespeople to maintain a list of clients. This web application allows any salesperson to view a list of clients and then click on any one client to update that client’s information. The user must click the “Save” button to persist their changes to the database.
Most search results are returned to users in a paginated form. In other words, only X results are shown to the user on a single page and the user has a way to navigate to the next X results.
Let’s use Google as an example. By default, you are shown the first 10 best results matching your query. At the bottom of the page, there are numbered links representing the corresponding pages of the search results. Clicking on “3” gives you the 3rd page of results. With a page size of 10, the results shown are 21 -30.
Searching for “lucene” at Google, it responds with
“Results 1 – 10 of about 2,440,000 for lucene. (0.33 seconds)”
Imagine if Google did not use pagination and instead returned everything to you at once on a single page! That would be a very large page and take a very long time to load.
If you use Lucene, you too can present your search results in a paginated manner even though Lucene does not provide a direct way to do it in their API (2.4.1). Thanks to how Lucene is designed, it is very easy to implement.