Tuesday, January 31, 2012

Selenium

What if you wanted to write Unit Tests for testing the UI? You want your test code to open a browser, go to your URL, click buttons and check values.

Enter Selenium.

Selenium is an open source project for automating UI testing.

Let us write a JUnit test which uses Selenium to test the UI for the JSON example project we created in the earlier post.

First, we need to download the selenium.jar.

Update your ivy.xml to create a dependency on Selenium, like this:

(Note - due to the way my internal repository is setup, I had to explicitly declare dependencies on other jars on which Selenium depends - you might not have to do this if you are pointing to the Maven central repository).

 <ivy-module version="2.0">  
   <info organisation="org.confucius" module="helloworld"/>  
   <dependencies>  
           <dependency org="commons-logging" name="commons-logging" rev="1.1.1"/>  
           <dependency org="org.apache.httpcomponents" name="httpcore" rev="4.2-alpha2"/>            
           <dependency org="org.apache.httpcomponents" name="httpclient" rev="4.2-alpha1"/>             
           <dependency org="org.apache.commons" name="commons-exec" rev="1.1"/>        
           <dependency org="com.google.guava" name="guava" rev="r09"/>  
           <dependency org="org.seleniumhq.selenium" name="selenium-api" rev="2.17.0"/>  
           <dependency org="org.seleniumhq.selenium" name="selenium-remote-driver" rev="2.17.0"/>  
           <dependency org="org.seleniumhq.selenium" name="selenium-firefox-driver" rev="2.17.0"/>  
           <dependency org="org.seleniumhq.selenium" name="selenium-java" rev="2.16.1"/>            
           <dependency org="junit" name="junit" rev="4.10"/>            
           <dependency org="org.json" name="json" rev="20090211"/>  
     <dependency org="javax.servlet" name="servlet-api" rev="2.5"/>  
     <dependency org="javax.servlet" name="jsp-api" rev="2.0"/>  
     <dependency org="jstl" name="jstl" rev="1.2"/>  
         <dependency org="log4j" name="log4j" rev="1.2.16"/>   
   </dependencies>  
 </ivy-module>  


Run the Ant resolve target to download all the jars.

Next, we need to update Eclipse Classpath to include these jars.

Go to Project->Properties->Java Build Path ->Add Jars
and add all the newly downloaded jars.

We also need to update the Classpath for Ant.

Update your build.xml to include the new jars, like this:
 <project name="HelloWorld" xmlns:ivy="antlib:org.apache.ivy.ant" >  
   
   <target name="resolve" description="--> retrieve dependencies with ivy">  
     <ivy:retrieve />  
   </target>  
   
      <target name="init" depends="resolve">  
           <mkdir dir="classes"/>  
           <mkdir dir="target"/>  
      </target>  
   
      <path id="build.classpath">  
       <pathelement location="lib/commons-logging-1.1.1.jar"/>  
       <pathelement location="lib/httpcore-4.2-alpha2.jar"/>  
       <pathelement location="lib/httpclient-4.2-alpha1.jar"/>  
       <pathelement location="lib/commons-exec-1.1.jar"/>  
       <pathelement location="lib/guava-r09.jar"/>  
       <pathelement location="lib/selenium-api-2.17.0.jar"/>  
       <pathelement location="lib/selenium-firefox-driver-2.17.0.jar"/>  
       <pathelement location="lib/selenium-java-2.16.1.jar"/>  
       <pathelement location="lib/selenium-remote-driver-2.17.0.jar"/>  
       <pathelement location="lib/junit-4.10.jar"/>  
       <pathelement location="lib/json-20090211.jar"/>  
       <pathelement location="lib/servlet-api-2.5.jar"/>  
       <pathelement location="lib/jsp-api-2.0.jar"/>  
       <pathelement location="lib/log4j-1.2.16.jar"/>  
      </path>  
   
      <target name="compile" depends="init">  
           <javac srcdir="." destdir="classes">  
                <classpath refid="build.classpath"/>  
           </javac>  
      </target>  
   
      <path id="test.classpath">  
       <pathelement location="classes"/>  
       <pathelement location="lib/junit-4.10.jar"/>  
       <pathelement location="lib/selenium-api-2.17.0.jar"/>  
       <pathelement location="lib/selenium-firefox-driver-2.17.0.jar"/>  
       <pathelement location="lib/selenium-java-2.16.1.jar"/>  
       <pathelement location="lib/selenium-remote-driver-2.17.0.jar"/>  
       <pathelement location="lib/guava-r09.jar"/>  
       <pathelement location="lib/commons-exec-1.1.jar"/>  
       <pathelement location="lib/httpclient-4.2-alpha1.jar"/>  
       <pathelement location="lib/httpcore-4.2-alpha2.jar"/>  
       <pathelement location="lib/commons-logging-1.1.1.jar"/>  
      </path>  
   
      <target name="test" depends="compile" >  
           <junit failureproperty="junit.failure">  
                <test name="org.confucius.TestCalculator"/>  
                <classpath refid="test.classpath"/>  
                <formatter type="plain" usefile="false" />  
           </junit>  
           <fail if="junit.failure" message="Unit test(s) failed. See reports!"/>  
      </target>  
        
      <target name="dist" depends="test">  
           <war destfile="target/HelloWorld.war" webxml="web.xml">  
                 <classes dir="classes"/>  
                 <lib dir="lib">  
                      <exclude name="jsp-api*.jar"/>  
                      <exclude name="servlet-api*.jar"/>  
                 </lib>       
                 <fileset dir="web-content"/>  
                 <webinf dir="WEB-INF"/>  
           </war>  
           <echo>Build executed at ${TIME_NOW}</echo>  
      </target>  
   
      <tstamp>   
           <format property="TIME_NOW" pattern="hh:mm:ss aa MM/dd/yyyy"/>   
      </tstamp>   
        
 </project>  


We also need to give an "id" to the button in HelloWorld.jsp, like this:
  <html>   
    <head>   
                 <script src="../js/jquery-1.7.1.min.js"></script>   
            <script type="text/javascript">   
         function getMusicSchool()   
            {   
              // Create AJAX object   
              var xmlhttp;   
                 
              if (window.XMLHttpRequest)   
               xmlhttp=new XMLHttpRequest(); // IE7+, Firefox, Chrome, Opera, Safari   
              else   
               xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); // IE6, IE5   
     
              // Associate a method for AJAX response   
              xmlhttp.onreadystatechange=function()   
               {   
               if (xmlhttp.readyState==4 && xmlhttp.status==200) // Successful response   
                         getJSONObject(xmlhttp.responseText);  
               }   
                  
              // Send AJAX request   
              xmlhttp.open("GET","http://localhost:8080/HelloWorld/music-school",true);   
              xmlhttp.send();             
            }   
           
         function getJSONObject(jsonStr)  
              {  
              if (null != jsonStr && 0 != jsonStr.length)  
                   {  
                alert(jsonStr)  
                            try  
                                 {  
                                 jsonObj = $.parseJSON( jsonStr );  
                                 displatStr = jsonObj.name + ", located at " + jsonObj.address + " teaches " + jsonObj.instruments.length + " instruments, including " + jsonObj.instruments[1] + ".";   
                     alert(displatStr);  
                                 }  
                            catch(e)  
                                 {  
                     alert(e.toString());  
                                 }   
                     
                   }  
              }  
            </script>      
    </head>   
    <body>   
       <form>   
         <button id="musicButton" type="button" onclick="getMusicSchool()">Show Music School</button>   
       </form>   
    </body>   
  </html>   



Now let us write a Junit test and use Selenium to test the UI.

In your /test/org/confucius folder, create a class TestHelloWorldUI.java, like this:
 package org.confucius;  
   
 import org.openqa.selenium.Alert;  
 import org.openqa.selenium.By;  
 import org.openqa.selenium.WebDriver;  
 import org.openqa.selenium.WebElement;  
 import org.openqa.selenium.firefox.FirefoxDriver;  
   
 import junit.framework.TestCase;  
   
 public class TestHelloWorldUI extends TestCase {  
        
      public void testMusicSchool(){  
     WebDriver driver = new FirefoxDriver();  
     driver.get("http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp");  
     WebElement element = driver.findElement(By.id("musicButton"));  
     element.click();  
   
     Alert jsonAlert = driver.switchTo().alert();  
     String jsonText = jsonAlert.getText();  
     String expectedJSONString = new String("{\"address\":\"9000 Cliff Drive, Santa Cruz, California\",\"name\":\"Beethoven Music School\",\"instruments\":[\"Piano\",\"Guitar\",\"Trumpet\",\"Violin\"]}");  
     assertTrue(jsonText.trim().equals(expectedJSONString.trim()));  
     jsonAlert.accept();  
   
     Alert javascriptAlert = driver.switchTo().alert();  
     String javascriptText = javascriptAlert.getText();  
     String expectedJavascriptString = new String("Beethoven Music School, located at 9000 Cliff Drive, Santa Cruz, California teaches 4 instruments, including Guitar.");  
     assertTrue(javascriptText.trim().equals(expectedJavascriptString.trim()));  
     javascriptAlert.accept();  
       
     driver.close();  
      }  
        
 }  
   


Note that we are testing in the Firefox browser.

In the above test:
- We open a browser
- Go to http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp
- Click on the musicButton
- Check the text in the alert boxes which popup
- Close the browser

If you run this JUnit test, you will see the Browser popup and Selenium clicking around.

Ant 'n JUnit

Instead of running JUnit manually from Eclipse, it is better to make it part of the Ant build.

This automatically ensures that all the code is tested each time it is built.

Ant comes with a JUnit task - all we have to do is use it.

Update your build.xml, to create a new 'test' target. Like this:
 <project name="HelloWorld" xmlns:ivy="antlib:org.apache.ivy.ant" >  

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve />
</target>

<target name="init" depends="resolve">
<mkdir dir="classes"/>
<mkdir dir="target"/>
</target>

<path id="build.classpath">
<pathelement location="lib/junit-4.10.jar"/>
<pathelement location="lib/json-20090211.jar"/>
<pathelement location="lib/servlet-api-2.5.jar"/>
<pathelement location="lib/jsp-api-2.0.jar"/>
<pathelement location="lib/log4j-1.2.16.jar"/>
</path>

<target name="compile" depends="init">
<javac srcdir="." destdir="classes">
<classpath refid="build.classpath"/>
</javac>
</target>

<path id="test.classpath">
<pathelement location="classes"/>
<pathelement location="lib/junit-4.10.jar"/>
</path>

<target name="test" depends="compile" >
<junit failureproperty="junit.failure">
<test name="org.confucius.TestCalculator"/>
<classpath refid="test.classpath"/>
<formatter type="plain" usefile="false" />
</junit>
<fail if="junit.failure" message="Unit test(s) failed. See reports!"/>
</target>

<target name="dist" depends="test">
<war destfile="target/HelloWorld.war" webxml="web.xml">
<classes dir="classes"/>
<lib dir="lib">
<exclude name="jsp-api*.jar"/>
<exclude name="servlet-api*.jar"/>
</lib>
<fileset dir="web-content"/>
<webinf dir="WEB-INF"/>
</war>
<echo>Build executed at ${TIME_NOW}</echo>
</target>

<tstamp>
<format property="TIME_NOW" pattern="hh:mm:ss aa MM/dd/yyyy"/>
</tstamp>

</project>


We have made our new 'test' target depend on 'compile'.
And we have made the 'dist' target depend on 'test'.

The junit task's 'failureproperty' records if any of the tests failed.
If so the 'fail' task is triggered, which will halt the build process.

If you run the Ant 'dist' task now, you will see the JUnit tests being run.

TDD with JUnit - Implementation

Let us now implement Calculator.java, so it does the addition.

First we do the obvious, and return the sum of the two numbers.
Like this:
 package org.confucius;  

public class Calculator implements BasicCalculator{

public int add(int a, int b) throws Exception {
return a + b;
}
}



If you run the Junit tests, the first two tests will pass and the third (huge values) will fail.

So we update our Calculator implementation, to use BigDecimal.
Like this:
 package org.confucius;  

import java.math.BigDecimal;

public class Calculator implements BasicCalculator{

public int add(int a, int b) throws Exception {
BigDecimal A = new BigDecimal(a);
BigDecimal B = new BigDecimal(b);
BigDecimal biggestInt = new BigDecimal(Integer.MAX_VALUE);

BigDecimal SUM = A.add(B);

if (SUM.compareTo(biggestInt) == 1)
throw new Exception();
else
return a + b;
}
}



Now if you run the JUnit tests, all 3 of them will pass.

Is this the best implementation of Calculator?

If there were more tests in the suite, maybe it would have broken. We would have then had to figure out a different implementation.

Or maybe in a few months someone will have a better idea than using BigDecimal. Something which runs faster. The code can be refactored at that point too.

Either way, TDD will ensure the integrity of our code.

TDD with JUnit : Running Tests

To run the tests, R-click on the TestCalculator.java file in Eclipse Navigator panel.

Select Run As--> JUnit Test

A new "Junit" panel will open and you will see the results of your test run.

All the 3 tests will fail, as expected, because we have not yet implemented Calculator.java

TDD with JUnit : Writing Tests

First we create a "shell" implementation of our interface.

We create a class which implements the BasicCalculator interface, but doesn't really do anything at this point.

Create a class Calculator.java in your /src/org/confucius, like this:
 package org.confucius;  

public class Calculator implements BasicCalculator{

public int add(int a, int b) throws Exception {
return 0;
}
}


Now to write the tests.

Create a folder called 'test' in your HelloWorld project, at the same level as 'src'.
JUnit tests are always written in the /test folder by convention.

Now we need to tell Eclipse to consider this as a Java source folder. While our test code is not part of the application, Eclipse needs to treat it like Source code so that it can compile it.

To do this, R-click on your HelloWorld project, select New-->Source Folder, and give the folder name 'test'.

In the test folder, create subfolders org/confucius.

The package names for JUnit tests will always mirror the packages in the /src folder.

In /test/org/confucius, create a class TestCalculator.java, like this:
 package org.confucius;  

import junit.framework.TestCase;

public class TestCalculator extends TestCase {
public void testAddPositive(){
int a = 2;
int b = 3;
try {
BasicCalculator cal = new Calculator();
int sum = cal.add(a, b);
assertEquals(sum, 5);
}
catch (Exception e){
assertTrue(false);
}
}

public void testAddNegative(){
int a = -2;
int b = 3;
try {
BasicCalculator cal = new Calculator();
int sum = cal.add(a, b);
assertEquals(sum, 1);
}
catch (Exception e){
assertTrue(false);
}
}

public void testAddHuge(){
int a = 1000000000;
int b = 2000000000;
try {
BasicCalculator cal = new Calculator();
cal.add(a, b);
assertTrue(false);
}
catch (Exception e){
}
}

}



Let us understand this class.

It extends the JUnit TestCase class - this makes it a JUnit Test class.

All its methods start with the prefix 'test' - this is what tells the JUnit engine which methods to run as part of its test suite.

We have written 3 unit tests - first tests addition of positive numbers, second tests negative numbers and third tests numbers whose sums are out of range of int.

Note that for the third test, the test passes if an Exception is thrown. And fails if an Exception is not thrown. Because we want the Calculator to throw an Exception if the sum exceeds the maximum possible value of int.

We have written 3 unit tests. Ideally, we should write as many tests as possible to cover the full range of possibilities.

NOTE THAT we still haven't implemented the Calculator.java! We have written all our Tests before implementing Calculator.java - this is TEST DRIVEN DEVELOPMENT!

TDD with JUnit: Installing JUnit

First we need to download the junit.jar.

Update your ivy.xml, so it looks like this:
 <ivy-module version="2.0">  
<info organisation="org.confucius" module="helloworld"/>
<dependencies>
<dependency org="junit" name="junit" rev="4.10"/>
<dependency org="org.json" name="json" rev="20090211"/>
<dependency org="javax.servlet" name="servlet-api" rev="2.5"/>
<dependency org="javax.servlet" name="jsp-api" rev="2.0"/>
<dependency org="jstl" name="jstl" rev="1.2"/>
<dependency org="log4j" name="log4j" rev="1.2.16"/>
</dependencies>
</ivy-module>


Now run the Ant 'resolve' target to download the juit.jar to your /lib folder.

Next, we need to add the junit.jar to our Eclipse Classpath.

Go to Project->Properties->Java Build Path->Libraries->Add Jars
and add the junit.jar

We also need to update the Ant Classpath.
Update your build.xml, like this:
 <project name="HelloWorld" xmlns:ivy="antlib:org.apache.ivy.ant" >  

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve />
</target>

<target name="init" depends="resolve">
<mkdir dir="classes"/>
<mkdir dir="target"/>
</target>

<target name="compile" depends="init">
<javac srcdir="." destdir="classes">
<classpath>
<pathelement location="lib/junit-4.10.jar"/>
<pathelement location="lib/json-20090211.jar"/>
<pathelement location="lib/servlet-api-2.5.jar"/>
<pathelement location="lib/jsp-api-2.0.jar"/>
<pathelement location="lib/log4j-1.2.16.jar"/>
</classpath>
</javac>
</target>

<target name="dist" depends="compile">
<war destfile="target/HelloWorld.war" webxml="web.xml">
<classes dir="classes"/>
<lib dir="lib">
<exclude name="jsp-api*.jar"/>
<exclude name="servlet-api*.jar"/>
</lib>
<fileset dir="web-content"/>
<webinf dir="WEB-INF"/>
</war>
<echo>Build executed at ${TIME_NOW}</echo>
</target>

<tstamp>
<format property="TIME_NOW" pattern="hh:mm:ss aa MM/dd/yyyy"/>
</tstamp>

</project>


We are all set to write Junit tests.

TDD with JUnit : Interface definition

Using TDD, let us write a very basic Calculator, which has only one method "add".

We will use JUnit, an industry standard unit testing framework, to write the tests.

The first thing is to define the interface.

Create an interface called BasicCalculator in your src/org/confucius folder.
It looks like this:

 package org.confucius;  

public interface BasicCalculator {
public int add (int a, int b) throws Exception;
}



The 'add' method finds the sum of two integers.
It throws an Exception if there is any problem.

Monday, January 30, 2012

Test Driven Development - TDD

Typically, software gets written and then QC tries to figure out how to test it.

Better way is to write the tests first and the software afterwards.

To do this, it is necessary to first fully define all the interfaces of the software.
QC then writes all the tests against the interface. By all, we mean ALL! The tests should be comprehensive.

Once the tests are all ready, the software is written. Needless to say, all the tests fail initially - because the interface has not been implemented yet.

As more and more of the software gets written, more and more tests start to pass.

When all the tests pass, it means the software is ready-ready.

Furthermore, if any code needs to be refactored in the future, the unit tests will automatically ensure the code integrity.

Unit testing

"Unit test" is a misnoner :(

When people think of unit testing, they think it tests the "smallest" unit of your program -- whatever they mean by that.

Truth is that you can test anything in a "Unit" test - you can test the biggest, highest level method on your program. You can test module integration, database transactions, input parsers, loggers, etc.

"Unit" means that you are testing ONE thing - whatever that one thing might be. Secondly, a Unit test must be INDEPENDENT of other Unit tests. If there are two unit tests A & B, neither of them should have any effect on the other. Whether I run B after A, or A after B, whether one fails or succeeds -- nothing will affect the results of the other.

For this, each unit test should create its own Initial state so that it becomes isolated from the unit tests before it.

This is what ensures that when you have 1000s of unit tests, if unit test# 537 fails, you know immediately what in your program has a problem. Because test # 537 is testing something very specific, and it is not dependent on the results of the other 536 tests that ran before it.

(Ideally, it should clean up its state when it ends so that it does not affect the tests after it - but strictly, this is not necessary because the next test is responsible for its own state initialization.)

The more the unit tests, the better the program gets tested. Even more importantly, you can refactor your code with confidence. Leave it to the unit tests to ensure code integrity.

HTTPS

By default, we have used HTTP to access our application from the browser.

HTTP transfers data as plain text. To make it more secure, we can use HTTPS.

To do this, we need to:
1. Use a SSL certificate
2. Configure Tomcat to use HTTPS

In real world, you get a SSL certificate from an issuing authority like VeriSign.

In our example, we will generate our own certificate.

HTTPS itself does not care who generated the certificate. It is for the user of the application to choose whether to accept the certificate. Most browsers are, by default, configured to accept certificates only from official authorities, like Verisign. If they see a certificate whose authority they do not recognize - they either do not connect to the website, or most likely, they ask the user what to do.

To generate your own certificate that Tomcat can use:
- Open a command prompt
- cd to your home directory
- Give the following command:

 C:\Documents and Settings\LavanniM>keytool -genkey -alias tomcat -keyalg RSA  


It will ask you several questions.
Specify a password value of "changeit".

Now that we have our certificate created, let us configure Tomcat to use HTTPS.

Open the /config/server.xml file in your Tomcat 7 installation.

Comment out:
   <Connector port="8080" protocol="HTTP/1.1"   
connectionTimeout="20000"
redirectPort="8443" />


Uncomment:

   <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />


Note that the HTTPS server runs on port 8443.

Now if you restart Tomcat, and try to access http://localhost:8080 - you will get a "Unable to connect" error.

If instead you point to https://localhost:8443, you will be able to access Tomcat.

Note: For some reason, the Tomcat Monitor utility runs into trouble with starting Tomcat on HTTPS. So start Tomcat from command line by going to the /bin directory and running Tomcat7.exe

You can now run HelloWorld by going to:
https://localhost:8443/HelloWorld/jsp/HelloWorld.jsp

All exchange between browser and server will now be encrypted, hence more secure.

If you try to run the JSON example from the previous post, note that you will need to update the HelloWorld.jsp to use https in its AJAX call.

Like this:

  <html>   
<head>
<script src="../js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
function getMusicSchool()
{
// Create AJAX object
var xmlhttp;

if (window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest(); // IE7+, Firefox, Chrome, Opera, Safari
else
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); // IE6, IE5

// Associate a method for AJAX response
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200) // Successful response
getJSONObject(xmlhttp.responseText);
}

// Send AJAX request
xmlhttp.open("GET","https://localhost:8443/HelloWorld/music-school",true);
xmlhttp.send();
}

function getJSONObject(jsonStr)
{
if (null != jsonStr && 0 != jsonStr.length)
{
alert(jsonStr)
try
{
jsonObj = $.parseJSON( jsonStr );
displatStr = jsonObj.name + ", located at " + jsonObj.address + " teaches " + jsonObj.instruments.length + " instruments, including " + jsonObj.instruments[1] + ".";
alert(displatStr);
}
catch(e)
{
alert(e.toString());
}

}
}
</script>
</head>
<body>
<form>
<button type="button" onclick="getMusicSchool()">Show Music School</button>
</form>
</body>
</html>


REMEMBER TO REVERT BACK to HTTP port 8080 when you are done!!!

Wednesday, January 25, 2012

JSON example

Let us transfer a simple object from Java to Javascript using JSON.
We will:
- Create a Java object
- Convert it to a JSON string
- Transfer the JSON string to Javascript
- Unmarshal the JSON string to a javascript object
- Display the javascript object

First we will need a JSON library to help us stringify our Java object.

Update your ivy.xml to get the jason.jar, like this:

 <ivy-module version="2.0">  
<info organisation="org.confucius" module="helloworld"/>
<dependencies>
<dependency org="org.json" name="json" rev="20090211"/>
<dependency org="javax.servlet" name="servlet-api" rev="2.5"/>
<dependency org="javax.servlet" name="jsp-api" rev="2.0"/>
<dependency org="jstl" name="jstl" rev="1.2"/>
<dependency org="log4j" name="log4j" rev="1.2.16"/>
</dependencies>
</ivy-module>


Now execute the 'resolve' target in your Ant build.xml to download the json.jar to your /lib folder.

In Eclipse, go to Project->Properties->Java Build Path->Libraries->Add Jars
Add the json.jar so Eclipse includes it in its CLASSPATH.

Also, update your Ant build.xml to include the json.jar in its CLASSPATH. Like this:
 <project name="HelloWorld" xmlns:ivy="antlib:org.apache.ivy.ant" >  

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve />
</target>

<target name="init" depends="resolve">
<mkdir dir="classes"/>
<mkdir dir="target"/>
</target>

<target name="compile" depends="init">
<javac srcdir="." destdir="classes">
<classpath>
<pathelement location="lib/json-20090211.jar"/>
<pathelement location="lib/servlet-api-2.5.jar"/>
<pathelement location="lib/jsp-api-2.0.jar"/>
<pathelement location="lib/log4j-1.2.16.jar"/>
</classpath>
</javac>
</target>

<target name="dist" depends="compile">
<war destfile="target/HelloWorld.war" webxml="web.xml">
<classes dir="classes"/>
<lib dir="lib">
<exclude name="jsp-api*.jar"/>
</lib>
<fileset dir="web-content"/>
<webinf dir="WEB-INF"/>
</war>
<echo>Build executed at ${TIME_NOW}</echo>
</target>

<tstamp>
<format property="TIME_NOW" pattern="hh:mm:ss aa MM/dd/yyyy"/>
</tstamp>

</project>


Now let us create a Java class in org.confucius called MusicSchool.java.
It looks like this:

 package org.confucius;  

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class MusicSchool {
private String name;
private String address;
private List<String> instruments;

public MusicSchool(){
name = new String("Beethoven Music School");
address = new String("9000 Cliff Drive, Santa Cruz, California");
instruments = new ArrayList<String>();
instruments.add("Piano");
instruments.add("Guitar");
instruments.add("Trumpet");
instruments.add("Violin");
}

public String getJSON() {
JSONObject jsonObj = new JSONObject();

try {
jsonObj.put("name", name);
jsonObj.put("address", address);
jsonObj.put("instruments", new JSONArray(instruments));
return jsonObj.toString();

} catch (JSONException e) {
return (e.toString());
}
}

}



It contains two string fields, 'name' and 'address' which holds the name and address of the music school.

It also has a field 'instruments' which is a list of the different instruments taught at the school.

It has a constructor which creates a default school (Beethoven Music School).

And, most importantly, it has a method getJSON() which converts the object to a JSON string.

We will now update HelloWorld.java servlet to return this MusicSchool object.
It looks like this:

 package org.confucius;  

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MusicSchool musicSchool = new MusicSchool();
response.getWriter().println(musicSchool.getJSON());

}

}


Next, we will update HelloWorld.jsp to make an AJAX call and get this MusicSchool object as a JSON string.
It looks like this:

Most of this code is standard AJAX code which we saw in the earlier AJAX post.

  <html>   
<head>
<script src="../js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
function getMusicSchool()
{
// Create AJAX object
var xmlhttp;

if (window.XMLHttpRequest)
xmlhttp=new XMLHttpRequest(); // IE7+, Firefox, Chrome, Opera, Safari
else
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); // IE6, IE5

// Associate a method for AJAX response
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200) // Successful response
getJSONObject(xmlhttp.responseText);
}

// Send AJAX request
xmlhttp.open("GET","http://localhost:8080/HelloWorld/music-school",true);
xmlhttp.send();
}

function getJSONObject(jsonStr)
{
if (null != jsonStr && 0 != jsonStr.length)
{
alert(jsonStr)
try
{
jsonObj = $.parseJSON( jsonStr );
displatStr = jsonObj.name + ", located at " + jsonObj.address + " teaches " + jsonObj.instruments.length + " instruments, including " + jsonObj.instruments[1] + ".";
alert(displatStr);
}
catch(e)
{
alert(e.toString());
}

}
}
</script>
</head>
<body>
<form>
<button type="button" onclick="getMusicSchool()">Show Music School</button>
</form>
</body>
</html>



The new function is getJSONObject().

This function uses the JQuery JSON library to unmarshal the JSON string into a javascript object. It then displays first the raw JSON string, and then the javascript object.

Update your web.xml to direct /music-school URLs to HelloWorld.java servlet.
Like this:
 <web-app>   
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.confucius.HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/music-school</url-pattern>
</servlet-mapping>

</web-app>




If you build and deploy HelloWorld.war, and browse to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will be able to see both the JSON string and the Javascript presentation.

JSON has provided us with a standardized format for transferring Java objects.

JSON

JSON = Javascript Object Notation

JSON is a convention for representing objects as Strings.

For example, a JSON string:
{"firstName":"Andrew","lastName":"Weber"}

represents a object whose firstName field has the value "Andrew" and the lastName field has the value "Weber".

We can specify Lists as well. So:
{"firstName":"Andrew","lastName":"Weber", "children":["Donna","Carol","Tyler"]}

represents the same object, with an additional specification for a field "children" which is a List and has the elements "Donna", "Carol" and "Tyler".

JSON has conventions for specifying maps as well, and you can have JSON objects inside other JSON objects.

So why is all this useful??!

Often you need to pass a Java object to the View (jsp) where a javascript will present the object.

It is very easy to "stringify" the Java object into JSON and pass it to the javascript. The javascript can then unmarshal the JSON string into a JAVASCRIPT object and use it.

Each side, Java and javascript, get to work with their native objects - and JSON provides a way to squirrel objects back and forth between the two.

There are standard JSON libraries already available, both in Java and javascript, which make it a breeze to stringify and unmarshal objects.

The other alternative to JSON is using XML to transfer objects. But JSON is way more lightweight and better suited for transferring tiny objects. XML is better when large amount of data needs to be transferred, for example transferring large number of records from a database.

Tuesday, January 24, 2012

Filter Chains

You can specify multiple filters to be called before a Servlet executes.
The filters are then called one after another as a chain.

After any filter executes, it must pass the control to the next filter in the chain by calling chain.doFilter().

If it does not call chain.doFilter(), the execution will end at that point and the Servlet will never be executed.

The Servlet is the last link in the chain, so it will only be executed when the last filter in the chain calls chain.doFilter()

The exact sequence in which the filters get chained follows rules specified in the Servlet specification. So if your filters are order sensitive, you should make sure you have chained them the right way.

Let us see an example, by adding a second filter to our previous example.

Create a new filter class called SecurityFilter.java in org.confucius.
This filter will assign an "access" level to the request depending on which IP address the request came from.

Here is what it looks like:
 package org.confucius;  

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class SecurityFilter implements Filter {

@Override
public void init(FilterConfig arg0) throws ServletException {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

if (request.getRemoteAddr().equalsIgnoreCase("121.23.132.12"))
request.setAttribute("access", "PRIVILEGED");
else
request.setAttribute("access", "REGULAR");

chain.doFilter(request, response);
}

@Override
public void destroy() {
}

}



Let us update the web.xml to use this filter, for _any_ URL:
 <web-app>   
<filter>
<filter-name>security</filter-name>
<filter-class>org.confucius.SecurityFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>security</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>empty_input</filter-name>
<filter-class>org.confucius.InputCheckFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>empty_input</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.confucius.HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>

</web-app>



Let us also update our Confirm.jsp so we can see that the access is set correctly:
 <html>   
<head>
<%@ page import="org.confucius.User" %>
</head>
<body>
<% User user = (User) request.getAttribute("user"); %>
Confirmation: Registration accepted for <%out.println(user.getFirstName() + " " + user.getLastName());%>
<br/>
Access Level: <% out.println(request.getAttribute("access"));%>
</body>
</html>


If you now build and deploy HelloWorld.war and browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will see the access level along with the confirmation.

Filters

Filters are special classes which are called before the Servlet executes.
They are used to do some preliminary work before the Servlet executes.

For example, in our User.java, one of the validations we do is to check for empty input.

This validation is necessary for all forms - so why not put it in a "common" class which is called before processing any form?

This class can be implemented as a filter.

Let us write our first filter, which will validate form input for empty values.

In your org.confucius, create a new class called InputCheckFilter.java which implements the javax.servlet.Filter interface.

It will look like this:
 package org.confucius;  

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class InputCheckFilter implements Filter {

@Override
public void init(FilterConfig arg0) throws ServletException {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

// Verifies input
Enumeration parameters = request.getParameterNames();
while (parameters.hasMoreElements()){
String parameter = (String) parameters.nextElement();
String value = request.getParameter(parameter);

if (value == null || value.length() == 0){
response.getOutputStream().print("Please enter values for all inputs!");
return;
}
}

chain.doFilter(request, response);

}

@Override
public void destroy() {

}

}



The filter checks all the parameters. If any parameter is not specified, it returns an error message. Otherwise, it continues the "filter chain" - we will learn more about the filter chain later.

For now, understand that the "chain.dofilter()" call passes the control to the Servlet.

Note that in the above code, the chain.dofilter() will not get called if any parameter is missing.

Let us now update out web.xml to specify that this filter should be used for all requests directed to the /register URL. Like this:
 <web-app>   
<filter>
<filter-name>empty_input</filter-name>
<filter-class>org.confucius.InputCheckFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>empty_input</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.confucius.HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>

</web-app>



Finally, let us clean up the User.java validation so it does not have to do the empty parameter check.

Our User.java now looks like this:
 package org.confucius;  

import java.util.regex.Pattern;

public class User {
private String firstName = null;
private String lastName = null;

public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public Boolean validate(){
if (Pattern.matches("[a-zA-Z]+", firstName)
&& Pattern.matches("[a-zA-Z]+", lastName)){
return true;
}
else{
return false;
}
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}


}



We can also update our Error.jsp to make it more specific, since the user validation now checks only for numbers in names.

Your Error.jsp will look like this:
 <html>   
<head>
</head>
<body>
Error! You entered names with numbers in them.
</body>
</html>




If you build and deploy HelloWorld.war, and point your browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will see the filter in action if you do not specify a value for both parameters.

NOTE: The filter is totally reusable. You can associate it with any number of URLs in web.xml and it will do its job of checking the request parameters.

Passing Model to View

Typically, the View always needs access to the Model.

For example, in our Confirm.jsp we may want to print out the User's first and last name.

The Controller can pass the Model to the View using request attributes.

Update your HelloWorld.java as shown below:
package org.confucius;

 package org.confucius;  

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

User user = new User(request.getParameter("firstName"), request.getParameter("lastName"));

String view = null;
if (user.validate()){
view = "/jsp/Confirm.jsp";
}
else{
view = "/jsp/Error.jsp";
}

request.setAttribute("user", user);
getServletConfig().getServletContext().getRequestDispatcher(view).forward(request,response);

}

}

We are now passing the User by setting it as an attribute.

Update your Confirm.jsp as follows:
 <html>   
<head>
<%@ page import="org.confucius.User" %>
</head>
<body>
<% User user = (User) request.getAttribute("user"); %>
Confirmation: Registration accepted for <%out.println(user.getFirstName() + " " + user.getLastName());%>
</body>
</html>

Here we get the User from the attribute, and print out its first and last name.

If build and deploy HelloWorld.war, and point your browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will be able to see the Users first and last name in the confirmation message.

MVC

MVC = Model-View-Controller

MVC is one of the most common model for web applications. All it says is that your code must be separated into 3 logical entities: the Model, View and Controller.

We will see this with an example. For now, here is a high level idea:

Model: This is the class in which data is stored
View: This is the JSP that gets displayed to the user
Controller: This is the class which accepts user requests, does some logic (which may involve loading/querying the model) and then chooses which View to display.

Now for the example.
In our previous post, we used a form to send some data to the application.

The HelloWorld.java servlet responded to the request, handled the data (firstName/lastName) and returned a response.

It did all 3 jobs - it acted as the Model, View and Controller.

Let us now separate these functions out.

We will start by writing a class which will handle the data. This is our 'Model'.

Create a class User.java in org.confucius, like this:
 package org.confucius;  

import java.util.regex.Pattern;

public class User {
private String firstName = null;
private String lastName = null;

public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public Boolean validate(){
if (firstName != null
&& lastName != null
&& firstName.length() != 0
&& lastName.length() != 0
&& Pattern.matches("[a-zA-Z]+", firstName)
&& Pattern.matches("[a-zA-Z]+", lastName)){
return true;
}
else{
return false;
}
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}


}



This class can store the firstName and lastName and validate them.
Our Model is now ready.

Next, we will create two JSP views - one for displaying a Confirmation and the other for displaying an Error.

In your /jsp folder, create a Confirm.jsp like this:
 <html>   
<head>
</head>
<body>
Confirmation: Registration accepted.
</body>
</html>


In your /jsp folder, create a Error.jsp like this:
 <html>   
<head>
</head>
<body>
Error! You entered blank or names with numbers in them.
</body>
</html>


Our Views are now ready.

Let us now update our HelloWorld.java to become the Controller.
It will look like this:
 package org.confucius;  

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

User user = new User(request.getParameter("firstName"), request.getParameter("lastName"));

String view = null;
if (user.validate()){
view = "/jsp/Confirm.jsp";
}
else{
view = "/jsp/Error.jsp";
}

getServletConfig().getServletContext().getRequestDispatcher(view).forward(request,response);

}

}


You can see that our Controller only manages the request. It lets the Model handle the data, and the Views display the response.

If you build and deploy HelloWorld.war, then point your browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will be able to play with the app.

Congratulations! You just wrote your first MVC style web application.

Monday, January 23, 2012

Forms

Forms are the backbone of the Web UI, so let us make sure we understand them.

Forms allow the web application to take user input - really that is ALL that forms do.
They take user input and pass it to the web application.

Let us create a form which lets the users register their first and last names.

Write your HelloWorld.jsp to create the form, like this:
 <html>   
<head>
</head>
<body>
<form method=post action="/HelloWorld/register">
First Name: <input type=text name=firstName>
<br/>
Last Name: <input type=text name=lastName>
<br/>
<input type=submit value="Register">
</form>
</body>
</html>


This form has two 'text' input fields to allow the user to enter first and last name.

It has a submit button which allows the form to pass the information back to the application.

Its 'action' tells the form that data should be sent to the /HelloWorld/register URL.

It also tells the form to use the 'POST' method, as opposed to the GET method.
In very brief, the POST method will put the data in the BODY of the HTTP request.
The GET method would have put it as part of the URL.

The principle is that POST is used for sending data to the server. In return a confirmation is expected.
GET is used for passing parameters to the server. In return the requested resource is expected - it can be a file, image, video, ... even the results of a computation can be considered a resource.

A POST should never be cached or bookmarked, whereas a GET can be cached and bookmarked.

Let us now update our web.xml to direct the /register URL to HelloWorld servlet:
 <web-app>   
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.confucius.HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>

</web-app>



Let us now update our HelloWorld.java servlet to handle this request:
 package org.confucius;  

import java.io.IOException;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {
String firstName = null;
String lastName = null;

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

firstName = request.getParameter("firstName");
lastName = request.getParameter("lastName");

if (firstName != null
&& lastName != null
&& firstName.length() != 0
&& lastName.length() != 0
&& Pattern.matches("[a-zA-Z]+", firstName)
&& Pattern.matches("[a-zA-Z]+", lastName)){

response.getWriter().write("Accepted: " + firstName + " " + lastName);
}
else{
response.getWriter().write("Error! You entered blank or names with numbers in them.");
}

}

}


Our servlet extracts the first and last names and does a series of checks on them, like checking for numbers in the names. It then accepts or rejects the request.

If you now build and deploy HelloWorld.war, then point your browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will be able to play with the form input.

What we just did:
- Created a very basic form for accepting user inputs
- Connected the form to a Servlet
- Processed the form input in the Servlet
- Returned a message back to the user

This pattern of form usage is very fundamental to the web. So much that it has its own name - the MVC model, which we will understand next.

Wednesday, January 18, 2012

JSP - Bean

Remember how we created a Stateful application?
(see this post)

We used cookies and hashtables to maintain session state.

We can do that easier by using JSP beans.

Using a JSP bean, we leave it to JSP container to create instances of objects and maintain their state (and eventually destroy the object, when appropriate).

Let us create a JSP bean which counts how many times a visitor visits a page within a session.

A JSP Bean is a POJO.

Create a VisitCount.java POJO in your org.confucius folder which looks like this:
 package org.confucius;  
   
 public class VisitCount {  
      private int count = 0;  
   
      public int getCount() {  
           count++;  
           return count;  
      }  
   
 }  
   


It has a single property 'count' which gets updated each time getCount() is called.

Declare this POJO as a JSP Bean in your HelloWorld.jsp and use it to count visits.

Your HelloWorld.jsp will look like this:
 <html>   
        <head>   
        </head>   
        <body>   
           <jsp:useBean id="counter" class="org.confucius.VisitCount" scope="session" />  
           You have visited <%out.println(counter.getCount());%> times.  
    </body>   
 </html>   


The jsp:useBean declares a Bean called 'counter', maps it to the VisitCount class, and declares it to be of 'Session' scope.

This means that we want the JSP container to maintain the state of the Bean for the duration of the Session.

The second line calls the getCount() method of the Bean to print out the number of visits.

If you build and deploy HelloWorld.war, and point your browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will see the visit count. Each time you refresh the page, the count will increment. The JSP container creates an instance of the Bean and maintains its state for the duration of the session.

If you close your browser, the session ends and the JSP container will destroy the Bean.

If you reopen your browser and revisit the page, the JSP container will create a new instance of the Bean for the new session. You will see that the counter has been reset.

We have used JSP Bean to maintain state. We did not have to maintain cookies and hashtables ourselves.

Nice.

Saturday, January 14, 2012

POJOs, Frameworks and Beans

POJO = Plain Old Java Object

While the acronym is catchy, there is nothing 'Plain' or 'Old' about POJOs.

A POJO is a regular Java class, which can contain complex methods and fields.
It can implement interfaces and extend classes.

So what makes it 'Plain'?

To understand that, we need to understand Frameworks and Beans .. and Containers.

A Framework is a formalized program (whether it is implemented as a jar or a standalone server or something else is not relevant) which allows you to accomplish certain tasks.

For example, Spring is an IoC/DI (Inversion of Control/Dependency Injection) framework.
Hibernate is a ORM (Object Relational Mapping) Framework.
HornetQ is a Messaging Framework.
J2EE itself is a Framework for writing Web Applications.
JSP is a templating Framework.
Struts is a MVC (Model-View-Controller) Framework.

All Frameworks are formal solutions to specific programming problems.
They define a formal API on how to use them - configurations, interfaces, classes, etc

The runtime avatar of a Framework is called a 'Container'.

So your web application can be said to be running inside the Tomcat container, your page templates are handled by the JSP container, your persistence is happening inside the Hibernate container, etc.

Often, to make use of a Container, you have to write Java classes which implement or extend certain specific, framework defined, interfaces or classes.

The Container is able to load these classes that you wrote and do certain things with them.
For example, Hibernate container can persist your Objects, JSP container can render your HTML files, JUnit container can run your unit tests, etc.

These classes that you write, that can be loaded by the container are called BEANS of that container.

Typically, a container will MANAGE the LIFECYCLE of its Beans - i.e. it will create the objects, call its methods, pass it around, and even destroy it when done. So a Bean is just an instance of the class, but one that is managed by the container.

Now coming back to POJOs:

Earlier frameworks typically required that Bean classes implement or extend certain specific Framework specified interfaces and classses.

This was a problem because when a newer version of the framework was released, the interfaces and classes needed to be updated.

To solve this problem, Frameworks now no longer require that Bean classes implement specific interfaces or extend specific classes.

They can be regular Java classes. The container loads them and uses Reflection to read them. This has turned out to be a big windfall for framework users, sparing them from having to update Bean classes with each new release.

These Bean classes, which are not required to implement or extend Framework- specific interfaces and classes, are called POJOs.

POJOs are, thus, regular Java classes - and nothing from the Framework "leaks" into them.

Let us see an example. We will compare a JUnit Bean, which is not a POJO - with a Hibernate Bean, which IS a POJO.

Here is the JUnit bean. You can see that it extends the JUnit specified class TestCase.
Hence it is not a POJO.
 import junit.framework.*; 

public class TestMath extends TestCase {

public void testAdd() {

int num1 = 3;

int num2 = 2;

int total = 5;

int sum = 0;

sum = Math.add(num1, num2);

assertEquals(sum, total);

}

}



On the other hand, here is a Hibernate Bean. You can see that it does not implement, nor extend any Hibernate specific interfaces or classes. In fact, there is nothing here to tell that it has anything to do with Hibernate. This is a POJO.

 package sample;

public class Artist {

String firstName;

String lastName;

long id;

public Artist () {super(); }

public Artist (String first, String last) {

firstName = first;

lastName = last;

}

public String getLastName() { return lastName; }

public String getFirstName() { return firstName; }

public void setFirstName( String name) { firstName = name; }

public void setLastName( String name) { lastName = name; }

public long getId() { return id; }

public void setId(long l) {id = l; }

public String toString() {return firstName + " " + lastName + id;}

}

Friday, January 13, 2012

JSTL Example - loops

We will create a simple loop using JSTL for printing out a list of names.

First, we need need the jstl.jar, so make an entry for it in your ivy.xml
 <ivy-module version="2.0">  
<info organisation="org.confucius" module="helloworld"/>
<dependencies>
<dependency org="javax.servlet" name="servlet-api" rev="2.5"/>
<dependency org="javax.servlet" name="jsp-api" rev="2.0"/>
<dependency org="jstl" name="jstl" rev="1.2"/>
<dependency org="log4j" name="log4j" rev="1.2.16"/>
</dependencies>
</ivy-module>


Run the Ant 'resolve' target to download the jstl.jar to your /lib directory.

Next, we should include jstl.jar in Eclipse classpath.

In Eclipse, go to Project->Properties->Java Build Path->Add Jars
and add the jstl.jar

We are now ready to use JSTL.

Type (or copy-paste) the following in your HelloWorld.jsp:
 <html>   
<head>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
</head>
<body>
<table>
<c:forTokens var="poet" delims="," items="Anna, Brian, Cathy, Dan, Erica">
<tr>
<td>${poet}</td>
</tr>
</c:forTokens>
</table>
</body>
</html>


In this, we have used JSTL "forTokens" custom tag to loop through a sequence of names. We then output the names in a HTML table.

If you build and deploy HelloWorld.jar, then browse to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

You will see the list of names show up.

In this example, the names have been hard coded as a comma separated string. Realistically, the could have come from a SQL query.

JSTL

JSTL = JSP Server Tag Library

This is a custom tag library which comes standard with JSP. It contains useful custom tags for doing various things like:
- creating logic (if/else)
- loops (foreach)
- formatting
- SQL
- XML
etc

To use JSTL in your JSP, use the following taglib declaration:
 <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>  


"c" is the conventional prefix for jstl "core" tags.
"fmt" is for format tags, "sql" for SQL tags, "x" for XML tags, etc

JSTL support is provided by jstl.jar which comes standard with Tomcat and most Java Web Servers.

Custom Tags Vs HTML Tags

Custom Tags can only be seen in the jsp template.
When the HTML page gets rendered, Custom Tags generate HTML tags.
You will not see any Custom Tags in the final HTML page.

Thursday, January 12, 2012

Writing a Custom Tag

Writing a Custom Tag involves two things:
1. A Java class which implements the Tag interface
2. A TLD (Tag Library Descriptor) file, which is an XML file, that describes the tag.

Let us create a Custom Tag for the datepicker.

First we need the jsp-api.jar, so let us update our Ivy.xml to get it for us.
Update your ivy.xml so it looks like this:
 <ivy-module version="2.0">  
<info organisation="org.confucius" module="helloworld"/>
<dependencies>
<dependency org="javax.servlet" name="servlet-api" rev="2.5"/>
<dependency org="javax.servlet" name="jsp-api" rev="2.0"/>
<dependency org="log4j" name="log4j" rev="1.2.16"/>
</dependencies>
</ivy-module>


Now run the 'resolve' task in your ant build.xml to retrieve the jsp-api.jar library.
You should see this jar in your /lib folder.

Next, go to Eclipse: Project-->Properties-->Java Build Path-->Add Jars to add the jsp-api.jar

This will include the jsp-api.jar to your Eclipse classpath.

We also need to add jsp-api.jar to the classpath of your build.xml so Ant can find it.

Update your build.xml to look like this:
 <project name="HelloWorld" xmlns:ivy="antlib:org.apache.ivy.ant" >  

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve />
</target>

<target name="init" depends="resolve">
<mkdir dir="classes"/>
<mkdir dir="target"/>
</target>

<target name="compile" depends="init">
<javac srcdir="." destdir="classes">
<classpath>
<pathelement location="lib/servlet-api-2.5.jar"/>
<pathelement location="lib/jsp-api-2.0.jar"/>
<pathelement location="lib/log4j-1.2.16.jar"/>
</classpath>
</javac>
</target>

<target name="dist" depends="compile">
<war destfile="target/HelloWorld.war" webxml="web.xml">
<classes dir="classes"/>
<lib dir="lib">
<exclude name="jsp-api*.jar"/>
</lib>
<fileset dir="web-content"/>
</war>
<echo>Build executed at ${TIME_NOW}</echo>
</target>

<tstamp>
<format property="TIME_NOW" pattern="hh:mm:ss aa MM/dd/yyyy"/>
</tstamp>

</project>


NOTE: We have excluded the jsp-api.jar from the war (see the 'dist' target) because Tomcat already ships with this jar.

Let us now create the Java class to support our Custom Tag.

In your /src/org/confucius folder, create a class DateTag.java which implements the Tag interface.

We will create two variables 'id' and 'label'.
We will modify only the doStartTag() method to generate the javascript.

Your DateTag.java should look like this:
 package org.confucius;  

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;

public class DateTag implements Tag {

private PageContext pc = null;
private Tag parent = null;
private String id = null;
private String label = null;

public String getLabel() {
return label;
}

public void setLabel(String label) {
this.label = label;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public void setPageContext(PageContext p) {
pc = p;
}

public void setParent(Tag t) {
parent = t;
}

public Tag getParent() {
return parent;
}

public int doStartTag() throws JspException {
try {

if(id == null || label == null) {
pc.getOut().write("Error: id and label must be specified for tag confucius:datetag");
} else {
pc.getOut().write("<p>" + label + ": <input id=\"" + id + "\" type=\"text\"></p>");
pc.getOut().write("<script>");
pc.getOut().write("$(function() {");
pc.getOut().write("$(\"#" + id + "\").datepicker();");
pc.getOut().write("});");
pc.getOut().write("</script>");
}
} catch(IOException e) {
throw new JspTagException("An IOException occurred.");
}
return SKIP_BODY;
}

public int doEndTag() throws JspException {
return EVAL_PAGE;
}

public void release() {
pc = null;
parent = null;
id = null;
label = null;
}

}



Let us now write the Tag Library Descriptor (TLD) so we can start using this tag in our jsp.

In your HelloWorld project create a folder WEB-INF (at the same level as src, lib, classes, web-content)

Inside WEB-INF create a folder 'tlds'

In /tlds, create a file ConfuciusTags.tld (it is just a XML file with .tld extension).

Declare the datetag by typing (or copy-pasting) the following in your ConfuciusTags.tld file:
 <?xml version="1.0" encoding="ISO-8859-1" ?>  
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>ConfuciusTags</shortname>
<uri>http://www.confucius.org</uri>
<info>Confucius Tags Library</info>

<tag>
<name>datetag</name>
<tagclass>org.confucius.DateTag</tagclass>
<bodycontent>empty</bodycontent>
<info>Date Picker</info>

<attribute>
<name>id</name>
<required>true</required>
</attribute>
<attribute>
<name>label</name>
<required>true</required>
</attribute>
</tag>
</taglib>


Your custom tag is ready for use.

Update your HelloWorld.jsp to use this tag.
We will use the tag 3 times to demonstarte its reusability.

You will need to include the ConfuciusTags.tld in your .

So your HelloWorld.jsp will look like this:
 <html>   
<head>
<link type="text/css" rel="Stylesheet" href="../css/jquery-ui-1.8.17.custom.css"/>
<script src="../js/jquery-1.7.1.min.js"></script>
<script src="../js/jquery-ui-1.8.16.custom.min.js"></script>
<script src="../js/jquery.ui.core.js"></script>
<script src="../js/jquery.ui.datepicker.js"></script>
<%@ taglib uri="/WEB-INF/tlds/ConfuciusTags.tld" prefix="confucius" %>
</head>
<body>
<confucius:datetag id="birthdate" label="Enter your birthday"/>
<confucius:datetag id="graduationdate" label="Enter your graduation day"/>
<confucius:datetag id="weddingdate" label="Enter your wedding day"/>
</body>
</html>


Here we have specified "/WEB-INF/tlds/ConfuciusTags.tld" as the uri for the taglib library. This is considered an absolute path by the JSP container.

We could have also set it to "http://www.confucius.org". In this case, the JSP container would look for it in the CLASSPATH. It would find the first TLD in the CLASSPATH whose uri matches "http://www.confucius.org".

Finally, we will need to update our build.xml to copy the ConfuciusTags.tld to WEB-INF.

Your build.xml will now look like this (notice the 'webinf' task in the 'dist' target)
 <project name="HelloWorld" xmlns:ivy="antlib:org.apache.ivy.ant" >  

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve />
</target>

<target name="init" depends="resolve">
<mkdir dir="classes"/>
<mkdir dir="target"/>
</target>

<target name="compile" depends="init">
<javac srcdir="." destdir="classes">
<classpath>
<pathelement location="lib/servlet-api-2.5.jar"/>
<pathelement location="lib/jsp-api-2.0.jar"/>
<pathelement location="lib/log4j-1.2.16.jar"/>
</classpath>
</javac>
</target>

<target name="dist" depends="compile">
<war destfile="target/HelloWorld.war" webxml="web.xml">
<classes dir="classes"/>
<lib dir="lib">
<exclude name="jsp-api*.jar"/>
</lib>
<fileset dir="web-content"/>
<webinf dir="WEB-INF"/>
</war>
<echo>Build executed at ${TIME_NOW}</echo>
</target>

<tstamp>
<format property="TIME_NOW" pattern="hh:mm:ss aa MM/dd/yyyy"/>
</tstamp>

</project>


If you now build and deploy HelloWorld, and browse to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will see three fields which give the datepicker calendar popup.

The Custom Tag has given you a clean, readable and reusable way to use datepicker.
No scary javascript in template :)