Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Finally! A Web App (Part 6, Finale)

DZone's Guide to

Finally! A Web App (Part 6, Finale)

Witness the final steps of creating a Java web app. This article walks you through the last bit of fine-tuning and housekeeping for our Shape Calculator.

· Java Zone
Free Resource

Learn how our document data model can map directly to how you program your app, and native database features like secondary indexes, geospatial and text search give you full access to your data. Brought to you in partnership with MongoDB.

Today we will finish (for now) our most recent iteration of our Shape Calculator component (or service, if you will). We have been on a long journey to this point.  Once we are done, we will move onto:

  • SOAP services.

  • REST services.

  • Web application clients for both of the service types

  • Securing the services.

Review

In the previous articles, we built the Spring MVC application and exposed most of the operations of the Shape Calculator. We are only missing one major task — adding a <form> so we can create new Calculation Requests. We also need to add a button so the application will actually perform all of the requested calculations. And finally, we need to clean up the code a bit.

Latest Code

In our journey, we have kept the Shape Calculator as a seperate Eclipse project.  In turn, other projects (the command-line apps, and this web-enabled app) depend on the Shape Calculator.

Go here for the web app project code. And here is the latest code for our component or service, that is used by the above web app.

Add Button and Code Clean-Up

Let's get the easy stuff out of the way first.  The previous article went into some detail what was required to add button to the JSPs. We're just going to repeat that here.

JSP Changes

First, we add the following button to the results.jsp:

<div class="container">
    <form:form action="runpendingnostop" method="post" commandName="runPendingNoStopForm">
        <table style="width: 650px" class="table table-striped">
            <tr>
                <td align="center">
                    <input type="submit" value="Run All Pending Requests" />
                </td>
            </tr>
        </table>
    </form:form>
</div>

Controller Changes

Then we add the following to the Controller:

    @RequestMapping(value="/runpendingnostop",method=RequestMethod.POST)
    public ModelAndView runpendingnostop() {

        System.err.println("\n\n\nINSIDE Controller runpending()\n\n\n");

        this.calculator.runAllPendingRequestsNoStopOnError();

        List<CalculationResult> calculatedResults = this.calculator.getAllCalculatedResults();

        if (null==calculatedResults || calculatedResults.isEmpty()) {
            return new ModelAndView("/results","message", "There are NO Results");
        }

        return new ModelAndView("/results","calculatedResults",calculatedResults);

    }


Test Setup

Since we are not yet able to add new Calculation Requests via our web app, we need another way. Take a look at previous articles where I used the command-line application we built to add the desired information, so we can then test this web app.

The test setup goes as such:

  1. Via command line app: Request a few calculations — these will become Pending Requests.

  2. Via command line app: Run the calcuations — this will create the Calculated Results (and empty the Pending Requests).

  3. Via command line app: Request another set of calculations.

Test Run

  1. Via this web app, select to view Results, you should see the first list of Calculated Results.

  2. Click the new "Run All Pending Requests" button.

  3. Observe that the original Calculated Results list grows to include the new batch of Pending Requests.

Here is my first batch of Pending Requests that were run (command-line) and are now Calculated Results:

Image title

And here is the updated list once I queued more requests (command-line) and clicked the new "Run..." button:

Image title

Code Clean Up

We have the following duplicated in several of the JSPs.  We want to locate them in a single place:

<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/bootstrap.min.css" />
<script src="${pageContext.request.contextPath}/resources/js/jquery-2.2.4.min.js"></script>
<script src="${pageContext.request.contextPath}/resources/js/bootstrap.min.js"></script>

Place the above in a new ${project base dir}/WebContent/WEB-INF/pages/common.jsp.

Then change the <head></head> area of each of the pages (index,pending,results,newreq) so that there are only two lines: The reference to the common.jsp, and the title of that page. Example:

<head>

<%@ include file="common.jsp"%>

<title>View Pending Requests</title>

</head>


Time to Work on Creating New Request Forms

Our final task is to add this feature, so we can add new Calulation Requests, just like we can do with our command-line application.

Let's think about how we want this Create Request submission <form> to work...

It could be like so (below), but that's pretty lame.

Image title

At minimum, it is error-prone. Entering the wrong text will cause errors. And it is time-consuming, having to type all that. We can do better. 

As a minimum requirement, selecting the Shape Name and the Calculation Type should be drop-down lists, that each contain only the allowable values.

newreq.jsp

Let's begin with that requirement - open the newreq.jsp, and add this:

    <div class="container">
        <form:form action="newreq" method="post" commandName="calcRequestForm">
            <table style="width: 650px" class="table table-striped">
                <tr>
                    <td>Shape:</td>
                    <td><form:select path="shapeName" items="${shapeList}" /></td>
                </tr>
                <tr>
                    <td>Type:</td>
                    <td><form:select path="calcType" items="${calcTypeList}" /></td>
                </tr>
                <tr>
                    <td>Dim:</td>
                    <td><form:input path="dimension" /></td>
                </tr>
                <tr>
                    <td colspan="2" align="center"><input type="submit"
                        value="Request" /></td>
                </tr>
            </table>
        </form:form>
    </div>

Remember to add this:

 <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> 

RequestResponseController

There are several ways to accomplish dealing with a form that contains some drop-down lists. Here is just one way.

I chose not to use that way. One thing I decided not to deal with was a drop-down that had no value selected.  So, really, the only possible user-entry error to deal with is the "dimension" value.

There are two possible errors:

  1. A negative dimension.

  2. A non-numeric dimension.

I handled each differently, if only just to show different ways of doing things.

And that brings us to exception-handling.

Exception Handling

There are many good articles on handling errors inside Spring MVC application. It can get pretty elaborate. One key idea is to keep exception-handling separate from business logic.

For our purposes with this application, we didn't go crazy. We kept it simple. I added just three exception handler methods and placed them in the controller. In a more complex web application, with multiple controllers, we wouldn't necessarily do that.

Like I said, you can get elaborate. But these three served our purposes well-enough.

  • There is a BindException handler — this will occur if a user enters a non-numeric dimension.

  • There is (our own custom) CreateException handler — this can occur anytime the Shape Calculator's queueCalculationRequest() hiccups, and one certain occurrence is if the user enters a negative dimension.

  • And finally, there is a catch-all Exception handler — complete with its own error.jsp.

You can view all the code via the links at the end of this article.

Here are some screenshots of good requests and bad requests.

Image title

Image title

I left the Exception class in the error message in case there might be another type of error. I didn't want any exceptions thrown during the queueCalculationRequest() to be handled generically and the user land on error.jsp. And that way, we can hope to continue displaying the <form> so the user can re-try.

Image title


Conclusion

There are many improvements and different ways of doing this web application (as well as the underlying Shape Calculator service/component). For example, the entire implementation employs a heavy use of @Autowired, and assumes that everything (such as the database) will be running. Using @Autowired is cool and seems simple, but with a large, complex application, with dependent projects, it might get out of hand.

But the application as-is works well enough for our purposes. (Your boss got tired of waiting for you and said "we need to deliver SOMETHING".)  

We have concluded with this iteration of our Shape Calculater with a simple web application.

Next Steps

We are going to move on and explore being able to expose the Shape Calculator as a SOAP web service.

Latest Code

You can obtain the latest web app project code from here. And the latest code for the underlying Shape Calculator service project is here.

Stay tuned for the next article!  We begin our web service.

Discover when your data grows or your application performance demands increase, MongoDB Atlas allows you to scale out your deployment with an automated sharding process that ensures zero application downtime. Brought to you in partnership with MongoDB.

Topics:
jsp ,spring mvc ,java ,button

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}