In this lesson, we’ll get things rolling with our Weather Underground web application. You can see the final result here. Note that this is not a production ready application. For that, we would probably not use zip code for our cache name. Instead, we might use some derivation of Latitude and Longitude. Also, the display doesn’t work well at all in browsers on mobile devices. As I mentioned in a previous lesson, 80% of the time and work in a project is often taken to get the last 10% of the features done.
If you look at the source for the final page referenced above, you will see a stark beginning web page. It looks like this:
<title>Weather or Not Web Services</title>
<meta name=”viewport” content=”initial-scale=1, width=device-width”>
<link href=”https://cdnjs.cloudflare.com/ajax/libs/extjs/6.2.0/classic/theme-classic/resources/theme-classic-all.css” rel=”stylesheet” />
<link href=”css/main.css” rel=”stylesheet” type=”text/css”/>
For our web application, we’ll generate all of our html “on the fly”. This gives us incredible flexibility and allows us to load things asynchronously. And/or: we could load localized content since our content is loaded dynamically. So let’s get started with our new Netbeans project.
The NetBeans Project
You should create your own Netbeans project; but since this is an advance lesson, I’ll save you the steps and you can pull down the project from here.
Here’s a brief description of the project properties:
We need to create and parse JSON. Because we are using Tomcat, we need to pull down and add the javax.json-xxx library. Note that if you were to use Glassfish, this lib would automatically be included in Glassfish.
We also illustrate dynamic loading of html content by using a content.html file. This can be useful for localization. For example, you might decide to show your users a spanish version of your content and so you could dynamically load the same text but in Spanish. Therefore, all your users would hit just one page and it will load for you.
Project Flow and Design
As you recall from the requirements in a previous lesson, we want to create an application that will give us the following functionality:
- Content Caching
- Credential Hiding
- Responsive design so that a user doesn’t have to wait for the web services to load before they see something
The following is a “word picture” of how our code operates (Note: this architecture is the product of several developers working together over several years and a plethora of blog and reference articles and I can take little credit for it – except, perhaps, for the web services layer):
- By using a Content Delivery Network (“CDN”), users may be able to pull the large ExtJs library from their cache. This is particularly useful, though unfortunately rarely used, in corporate environments as well. You can see that in the …https://cdnjs.cloudflare.com/ajax/libs/extjs/6.2.0/ext-all.js resource. NOTE: you may want to use the debug library of this resource which is also available on the cdn.
- One of the things I love about ExtJs is that they allow you to nest components. This is super powerful for our responsive design. So the first thing we do is create our master container, the Viewport and style it (size, location, etc.). This is the container that loads all of the other components which we will display. As you can see in the code, this loads a Panel that just displays the Loading icon and text. However, in other situations, we may pull the most recent version of our cached content from the server and show that to the user while our web service runs. We would probably notify the user that the content may be stale and will be updated automatically once the backend sends the refresh to us.
- Still in our onReady function, we make the Data Request after we show the Loading stuff.
- The Data Request is a key component for our distributed architecture and it provides a number of key features:
- We can make our request to a variety of sources and return a variety of data. By passing in a config object, we just use this one variable which holds a number of parameters.
- We can use our config object to make the request to a static file on a file server that might return json data; or, we might make an actual web service call. This is super-helpful for development and can abstract away our web service as we continue with our front-end web development. For example, we might have a sample json file which we can use to finish our web design work that our JAVA developer will use as a template for his development. We are not blocked from moving ahead since we can just pass a flag in our config that tells the Data Request function to use the static file. Later, when we have the web services layer ready, we just change the flag. Cool.
- We might make a cross domain call and use JsonP and again, we can abstract that in this function.
- We can create some useful error and success messages and pass them back from here.
- In our Data Request function, we only make a web service call, to the weatherHandler web service we create in this project; that is, the code running in our Tomcat application server.
- We make the Data Request and even if it takes a while, the user can look at the content in the first panel displayed. However, once the Data Request returns, it process a Cleanup function which will process the success or failure of the data request and/or the data itself.
- If the request is successful, the Render function in the config we passed in will be called.
- For our demo, this Render function is the WeatherRenderer which will populate a new grid with the JSON data we got back from our web service. It’s important to note that when we get here, we know we have good json and that our request completed. We can also use components from the JSON to display outside the grid if we want. These are two great reasons to abstract the data call away from the display.
- Once the grid has completely loaded and rendered (still hidden); we then hide the previous grid (our Loading panel but could be stale cached data), and then show our populated grid. We also pull the content.html page and read it’s html content and append that to the page after the grid.
So in summary, we have a responsive design that is fully asynchronous and allows us to make multiple web service calls and aggregate data in the backend; without forcing the user to wait. We can have multiple components on a given page and each can be fully asynchronous providing a super responsive design for our users.
The Web Services
I won’t dig too deeply into the JAVA code; but an overview of what the code is doing is useful.
The code will first load its configuration data that includes the path to the logs folder and the Weather Underground API key. In this way, we can share code and check it into a code repository without displaying user credentials.
Sidebar: I am constantly amazed at how sloppy developers are with important credentials. The code source tree is typically full of user names and passwords and a simple text search will unveil them easily. It’s much better to store your credentials someplace apart from the code and secure it during both development and release. Plus, it makes it easy to change credentials for your app without needing to open the code.
The first thing we do is use the IP address from the caller’s web request header to determine their location city and zip.
We cache requests for one hour using the zip code and so the application will first check to see if there are data in the cache that can be served. If so, the app will pull the data from the cache and not make the second web request. This saves on our limited Weather Underground API calls.
If we don’t have data for that zip in our cache that is fresh, we make the Weather Underground API call and return those data. We also write the data to our cache.
Now, if the Weather Underground API were slower, we could use this same architecture to implement the following: show the swirly –> check the cache and if file present show it –> if file present and stale, make a new request –> once new request is completed, hide the stale data and show refreshed data. Our architecture would make this simple.
In this lesson, I attempted to tie everything together with a useful web application that illustrates the power of the various web components working in harmony to create a responsive web design.