Monday, December 03, 2012

Using JSTL and why I lie.

I cannot keep to a script to save my life.

So I keep talking about some better application but I've picked to go over JSTL first and we will move on to the other later.  Sorry I lied, but I think that getting some background on JSTL will help you out a bit.  Besides, you've got to know how to add tag libraries to your project!

Okay so in the last post I covered how to download the JSTL 1.2 (which is the current version) libraries.  These two JAR files provide a basic JSTL 1.2 implementation.  The JSTL 1.2 is a spec (I believe that it is JSR-52, but don't quote me on that, I didn't look it up) and there are maybe two or three different implementations of that spec.  All of them work pretty much the exact same as the others, so any implementation is going to be boss here.  The Apache Tomcat team has yet to build their own implementation so your going to have to seek outside sources for this.  I choose the Glassfish Project's implementation because I pretty much use Glassfish all the time.  I'm sure you could use Red Hat's implementation.

Anyway, getting off topic here.  You need these JARs to have JSTL.  JSP Standard Tag Library defines a set of tags that can be used in JSP pages to expose pretty freaking basic functionality that we've been beating around.  These tags, combined with EL (which I briefly talked about in this post) allow web developers to express page logic in JSP development.  This is the kind of logic like, having a particular piece of HTML repeat a set amount of times (if you were showing records or a list of things), turn on or off UI elements based on the status of your java beans or servlets (like if a shopping cart was empty), and a whole lot of other page related logic.  Using JSTL makes this easy for web developers because it is expressed as tags much like HTML, which is what web developers are more accustom to working with.  This avoids have scriptlets or other Java like stuff in pages (because remember, code in web pages is harder to maintain, than code in other places.)

So once you have the libraries it's time to decide where to put them.  With Tomcat and for that matter pretty much every single Java Web/Application server, you usually can put libraries in one of two locations.  The first is within your project so that the libraries are available to your application and only your application.  The second is in the server's classpath, this makes the libraries available to every application on your server, whether they need it or not.  Now I know some people would say that the choice is a no brainier  in the server's classpath, for the simple fact of not having a ton of copies of the same libraries on your server.  However, consider this, while the JSTL may not cause this, some class libraries or tag libraries may cause some applications to break.  So if you have multiple applications on your server, you could break one of them by having the server's classpath bring in changes that the application wasn't expecting.  Of course the converse is, very rarely do people have multiple applications per server (there are cases mind you), however, usually it goes down that each instance of Tomcat is a single application and a machine just runs multiple instances of Tomcat.  If that's the case, then there is very little advantage to the per application approach, or for that matter in the server classpath approach as both options are the same.

For now, I'm going to show you the per application approach.  I'll put up instructions if you want to go the per server approach.  The reason being is that most development boxes use the per application approach, for pretty obvious reasons.

Okay, enough blah, blah, blah.  Let's start an entire new web application.  Remember how to do that?  Here's that post.  You don't have to actually follow the step where you make a servlet.  I will call this project "ContactKeeper", guess what I have in mind for my next project to talk about.

Okay so you have a blank web project called contact keeper.  Let's move the JSTL JAR's into our project. According to the rules (the web container spec, I have no idea what JSR that is) we MUST put these files into the [project]/WEB-INF/lib folder.  Otherwise, the server is free to ignore the JAR completely, and most web containers WILL ignore JARs found outside of this folder.

As you can see, the Eclipse wizard automatically creates this folder (and also the META-INF folder which is where you put your Java code side libraries).

The WEB-INF/lib folder
One of the craziest things people new to Eclipse stress about is how the heck to copy files into a project.  I'll have to admit, coming from Netbeans, I found this to be a bit quirky to say the least.  Go ahead and select your lib folder there and right mouse click.  You will see an entry on the context menu called Import...  Select that and you get a dialog asking what kind of import you want to do.  For the longest time I thought that Archive File was the way to go, but no, the correct answer is File System.  (Reason being that I thought that is that JAR is short for Java Archive).

This is the correct answer.
Now go ahead and click Next, you will see a From Directory text box with a browse button beside it, just click on that browse button and move to the directory where you have the libraries stored.  Once there, click OK and you should now see everything populate in the dialog like this:

There now we are ready to import in the JAR files.
Now everything just seems so logical once you figure that part out.  Check the files that you want to import, which are the two files that I have in the directory.  Double check to make sure that you are importing these files into [project name]/WebContent/WEB-INF/lib.  Once you have done so, click finish and the files will be imported into your project.  Yes that means that if you delete the source files from the Download directory, you will still have a copy of the files in your local project.  You should be able to now expand the lib folder and see the two JARs there.

Now you are ready to create your first JSP using the new JSTL tag library.  Let's create a Java bean called PeopleList first, I'm going to put it into the package, "com.blogger.contacts.beans".  To create a bean refer to this post.  In this bean we are going to create a collection list of Strings.  To do so add this code for a field.

private List peopleList;

You should get a wavy line under List.  You want to import the java.util.List class into your bean, which you can do using the quick fix.  The java.util.List is considered a "Collection".  I won't really get too deep into what that means, but is allows you to group a lot of similar things together in a way that is much better than arrays.  I really recommend that you use collections, unless you are really on a memory strap budget, or you just want a really simple structure without all the fancy frills of collections.  Collections do come with a bit of overhead in return for ease.

Go ahead and create a getter for this field, we're going to make it read-only for the time being.  Now the last thing we need to do is actually fill this list with some data so that we can use it.  We will do that in the constructor.  Now List is an abstract class, we need to add a concrete class before we can use the list.  For simplicity we are just going to use ArrayList as our concrete class.

Just as an aside here:  Abstract classes are there because they expose a common interface.  All lists allow you to add items, remove items, clear the list, see how big the list is, and so forth.  A concrete class deals with the actual implementation of that interface.  An ArrayList is basically a regular Java array storage with all the methods that List exposes bolted on.  As a counter example, LinkedList is not implemented as a regular Java array, instead it is indeed a linked up listing of actual objects.  The difference is, an ArrayList is harder to sort and insert in the middle of, because a temporary Java array has to be created to sort things, or to shuffle items down the in the array.  A LinkedList is much faster at those things, but takes more memory to just keep the structure, an ArrayList would use more memory if you were constantly shuffling things around, but uses less memory if the data just sits there most of the time.  There are all kinds of abstract and concrete classes in the Collections library, that represent all kinds of different data models.  Some models are better suited for different applications, which is literally a whole year's course of college to explain, so if you really want to know more about data structures, there is no shortage of books and opinions out there for your to read up on, but it's W-A-Y out of scope here.

Ahem, so let's add this code to our constructor.


this.peopleList = new ArrayList();
this.peopleList.add("John");
this.peopleList.add("Bill");
this.peopleList.add("Frank");
this.peopleList.add("Betty");
this.peopleList.add("Mary");
this.peopleList.add("Jill");

This code should be pretty clear here.  Basically, we make our peopleList concrete so that we can use it.  Then we start adding some names to the list.  The final bit of code for your bean should look like this:

package com.blogger.contacts.beans;

import java.util.ArrayList;
import java.util.List;

public class PeopleList {

 private List<String> peopleList;
 
 public PeopleList() {
  this.peopleList = new ArrayList<String>();
  this.peopleList.add("John");
  this.peopleList.add("Bill");
  this.peopleList.add("Frank");
  this.peopleList.add("Betty");
  this.peopleList.add("Mary");
  this.peopleList.add("Jill");
 }

 public List<String> getPeopleList() {
  return peopleList;
 }

}

Now we are going to create a simple JSP page that will use this bean.  So go ahead and create a JSP page (named index.jsp, obviously), but this time on the second step use the full-out JSP 2.0 XML style.  This should be the last entry in the dialog box.

You will see near the top of the newly created page the jsp:root element.  This is the core element of every JSP page using the 2.0 standard.  Basically, this tells the JSP compiler that you are using the new syntax over the old stuff.  In that jsp:root element we need to add the namespace of our tag library to the page so that the JSP compiler imports those tags for use in this page.  Your jsp:root element should look like this:



As you can see I've added the xmlns:c stuff.  This means that anything prefixed with c will be using JSTL core tag library as opposed to the jsp built in library.  Autocomplete and what-not, will work for you on the c namespace just as it has for you on the jsp namespace.  Now go ahead and make your JSP page look like the following, I'll explain later:


<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" version="2.0">
 <jsp:directive.page contentType="text/html; charset=UTF-8" 
  pageEncoding="UTF-8" session="false"/>
 <jsp:output doctype-root-element="html"
  doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
  omit-xml-declaration="true" />
<jsp:useBean id="databean" class="com.blogger.contacts.beans.PeopleList" type="com.blogger.contacts.beans.PeopleList"></jsp:useBean>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Insert title here</title>
</head>
<body>
 <c:forEach var="i" items="${databean.peopleList}">
  <c:out value="${i}"></c:out>< br />
 </c:forEach>
</body>
</html>
</jsp:root>

Okay a lot going on here. First you notice the jsp:useBean tag that brings the bean into the page so that we can use it.  The next thing is this new c:forEach tag!  Remember that the c means that this tag comes from the JSTL core tag library.  The JSTL core forEach tag allows you to iterate through an array or Collection.  For each item found in the array or Collection, the code between the open and close forEach tag is repeated.

You will notice a "var" attribute.  Basically, when we find an item in the collection, that item that is currently selected becomes a value known as "i"  in this case, you could have called it something more logical.  The next attribute is the "items" attribute.  This is either the Collection or array that you want the forEach tag to run through, you'll notice that I've used EL.  You have to.  The EL returns databean.peopleList, which is our collection's getter method.  You use EL here because the JSTL doesn't allow you to use another tag (like jsp:getProperty) in the attributes.  This is why I said earlier that EL is not exactly like a replacement for jsp:getProperty, it has it's own engine and everything.  That's why EL can figure out that we need the getter method here.

Okay so moving on is the next tag, c:out.  This one is pretty simple, it basically take an expression and outputs the result.  If the result of the expression isn't a String object, then the toString() method is called.  EL again is used in the "value" attribute.  The reason being is that we need to resolve the expression "i".  If we just typed the letter i, the the output would be the literal letter i.  I put a BR tag right after that so that each entry appears on a line.  We close our c:forEach tag.  Let's run this program and see what happens!

Output of our new web application
Ta-da as you can see, each name in the Collection is placed onto the web page.  Now you can see why JSTL is really freaking important.  Trying to do that same thing would have required a scriptlet, which would have really tied the Java bean code to the web page code.  If someone came in and changed the Java bean code, we would have had to update our page code as well.  At least here, we've separated the two enough that non-major changes will require no changes to the web page.  You can easily change the code to be a List if you wanted and no changes to the web code would be needed.

There are a lot more tags in the code JSTL and there are more sections than just the core to JSTL.  I'll get to those as I go, but for now, you can start to get the idea of where I'm heading with this.

Cheers!

No comments: