JavaEE Pragmatic Introduction

1) Background:
Below steps demonstrate about creation of workable web application based on Java EE architecture. This application will be deployed on "Application Server" [JBoss].


2) Application Server: JBoss 
http://sourceforge.net/projects/jboss/files/JBoss/JBoss-5.0.1.GA/jboss-5.0.1.GA-jdk6.zip/download

- Getting Started:
i) Unzip jboss-5.0.1.GA-jdk6.zip to appropriate location (/user/local/ or c:/)
ii) check for run.bat (windows) or run.sh (unix/linux like systems) and execute it
[use -b option to run it with IP address or hostname, so that it can be accessed using IP or Hostname instead of localhost always]
./run.sh -b 0.0.0.0
iii) check for the runtime logs to see if the server started without any errors


3) UML Tools:
http://astah.net/download
http://argouml.tigris.org/


4) Basic Application Structure:
i) Create new Java project in eclipse [JavaEE_Sample]
        
ii) Add new [Source Folder] named : web
                 

iii) Add new [Folder] named : WEB-INF under web source folder [web/WEB-INF]
iv) Add new file web.xml under WEB-INF folder [web/WEB-INF/web.xml]
This is a application descriptor for web application which maintains operational relationship of web application.
[web.xml]

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
  version="2.4">

  <welcome-file-list>
     <welcome-file>index.html</welcome-file>
  </welcome-file-list>
    
</web-app>

v) Add new index.html file under web folder [web/index.html]

[index.html]
<html>
<body>
This is a sample web application. 
</body>
</html>


5) Deployment:
i) Save the project as war (web archive) file : myjavaee.war
(The war file is a zip file named as war so that Application Server can understand it as a web application)
ii) Copy the war file to the deploy folder of JBoss, which will deploy the web application
/JBossInstallation/server/default/deploy/myjavaee.war

iii) Start JBoss using run command 
/JBossInstallation/bin/run.sh (run.bat for windows)
iv) Confirm deployment by checking log file


6) Test confirmation:
i) Access the deployed web application using below context
http://localhost:8080/myjavaee
(8080 is default port where JBoss runs)
ii) Check output to see below message
=========================================================

Exception Handling (try...catch...finally) with User Defined Exception

- Exception is an Object in Java
- Throwable is Superclass of all exceptions
- Exceptions could be Checked or Un-Checked type
- Checked exceptions needs to fix at compile time, such as IOException, InterruptedException
(Compiler checks for everything except run-time exceptions which are called un-checked)
- Un-checked exceptions occurs at run-time, such as NullPointerException
(These exceptions needs to identified at development and UAT (User Acceptance Test) phase )
- Use try...catch...finally block to deal with exceptions of both types (checked and un-checked)
- There could be multiple "catch"blocks for one try block
- Multiple "catch" blocks are arranged in the order of specific to generic
For example, upper catch block should contain code specific error, such as IOException might be followed by generic exception such as Exception. (The Exception class us use to handle generic exception because it is Super-class of Checked and Un-checked exceptions, os it covers those error types)
- Error is beyond the application scope and mainly related to system, so it is advice not to catch error and let it handle by the system to fix the root cause, such as OutOfMemoryError. Error might lead to application might crash.  
- Error is an irrecoverable condition occurs at runtime.

try {

} catch (IOException ) {

} catch (Exception) {

}
- In case of java application main() function can not use with "throws", we have to handle all checked exceptions at main() level unlike other methods which could keep throwing exceptions to the caller using "throws"

-Exception Hierarchy: 

=======================================================
Example: To demonstrate different patterns of Exception usage
import java.util.HashMap;
import java.util.Map;
/**
 * Class defining user defined exception for authentication
 */
public class AuthenticationException extends Exception {  
     static Map errorMap = new HashMap();
     //static map of error code and description, 
     //can be created after reading properties file
     static {
          //Map of Error code to Error Description
          //Transfer below mapping to Properties file for Internationalization
          //of error message based on the User Locale
          errorMap.put("E7", "Authentication Failure");
          errorMap.put("E8", "User is locked after 3 wrong login attempts.");
     }    
     /**
      * Constructor to display specific message based on error code
      * @param errorCode to print related error description
      */
     public AuthenticationException(String errorCode) {
          System.out.println(errorCode + ":" + errorMap.get(errorCode));
     }    
     /**
      * Default constructor to display default message 
      * when no error code is specified
      */
     public AuthenticationException() {
          System.out.println("Default Error message");
     }
}
-------------------------------------------------

/**
 * Class to test exception handling
 *
 */
public class TestExceptions {
     public static void main(String[] args) {
          //1. calling method which throws InterruptedException 
          //which needs to be handled by caller using try ..catch
          try {
               foo1();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
          //2. no need to catch any exception, as foo2() is not 
          //throwing any exception unlike foo1()
          foo2();
          //3. calling method which throws User defined 
          //exception AuthenticationException
          try {
               foo3(false);
          } catch (AuthenticationException e) {
               e.printStackTrace();
          }
     }
     /**
      * Method to demonstrate throws in exception handling
      * @throws InterruptedException
      */
     public static void foo1() throws InterruptedException {
          Thread.sleep(1);
     }
     /**
      * Method to demonstrate, how to handle error at 
      * method level instead throwing them to caller
      */
     public static void foo2() {
          try {
               Thread.sleep(1);
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
     }
     /**
      * Method to demonstrate how to use User defined exceptions
      * @param success
      * @throws AuthenticationException
      */
     public static void foo3(boolean success) throws AuthenticationException {
          if (!success) {
               throw new AuthenticationException("E7");
          }
     }
}

Comparing primitive and reference types (using equals and hascode)

-Primitive variables can be compared by using == operator
-Objects type variables can be compared by overriding equals() and hashcode()
methods (if we do not override equals() and hashcode() methods, the program will result into unexpected output)
-For objects to be equal, their equals() method should return true and hashcode() method should return same hashcode.
===========================================================
Example: To demonstrate how to compare primitive and reference data types. For reference data types such as Car in below example, the equals() and hashcode() methods are overridden so that "deep comparison" is possible.
import java.util.HashSet;
import java.util.Set;
public class TestCompare {
     public static void main(String[] args) {
          int age = 20;// primitive
          //compare with == for primitive data types
          //check equality
          if (age == 20) {
               System.out.println("You are 20");
          }
          //Object type variable
          Car a = new Car();
          Car b = new Car();
          a.setModel("Mazda");
          a.setPrice(1000);         
          b.setModel("Mazda");
          b.setPrice(1000);         
          if(a.equals(b)) {
               System.out.println("Equal Car");
          } else {
               System.out.println("Not equal Car");
          }         
       //adding two objects a and b with same states
       //to Set will results into one unique object
       //only. Set calls Objects' equals() and hashcode()
       //methods to compare their contents
       Set<Car> carSet = new HashSet<Car>();
       carSet.add(a);
       carSet.add(b);
       System.out.println("Car Set size:" + carSet.size());
     }
}
Output:
You are 20
Equal Car
Car Set size : 1
--------------------------------------------------
public class Car {
     private String model;
     private double price;
     public double getPrice() {
          return price;
     }
     public void setPrice(double price) {
          this.price = price;
     }
     public String getModel() {
          return model;
     }
     public void setModel(String model) {
          this.model = model;
     }
     //method to compare state of this and other object
     //which is passed as a parameter
     //if all states are same between two objects then
     //this method will result true, else false
     @Override
     public boolean equals(Object b) {
       boolean result = false;
       if (b instanceof Car) {
         Car c = (Car) b;
         result = c.getModel().equalsIgnoreCase(getModel()) && 
                  c.getPrice() == getPrice();
       }
       return result;
     }
     //Require to override when overriding equals() method
     //so that two equals objects will return same hashcode
     //which will avoid duplicate elements in Hash 
     //like collections, such as HashSet
     @Override
     public int hashCode() {
          return (int)(price/10000)*7;
     }
}

Passing primitive and reference types method parameters

-Parameters are pass-as-copy for primitive and reference data type
-Object will be passed as copy of reference  
-While passing primitive type as a method parameter, java passes copy of the primitive type to the calling method, so that the original value will be kept different from the copy, which results into two separate variables with separate memory locations.
Examples: int, long, double as a method parameters

-While passing reference type as a method parameter, java passes copy of reference to the calling method (copy of reference but not copy of Object). So original reference variable and its copy are pointing to the same Object memory location. which results into two reference variables pointing to the same Object memory location. With this you can modify Object states using either of the references (original or copy).
Fig. 1: Memory map for primitive and reference data types
-------------------------------------------------------------------------------------------------------------------------
Example: To demonstrate how java passes parameters for primitive and reference data types.
public class TestParamPass {
  public static void main(String[] args) {
  int age = 20; //primitive data type
  Employee emp = new Employee(); //reference data type
  System.out.println("Original age: " + age);
  System.out.println("Original salary: " + emp.getSalary());
  processAge(age, emp);
  System.out.println("Updated age: " + age);
  System.out.println("Updated Salary: " + emp.getSalary());
 }

  //Method to process passed parameters

  private static void processAge(int ageParam, Employee empParam) {
   empParam.setSalary(2000);
   ageParam++;
  }
}
Output:
Original age: 20
Original salary: 0.0
Updated age: 20
Updated Salary: 2000.0
------------------------------------------------------------------------
public class Employee {
     double salary;
     public double getSalary() {
          return salary;
     }
     public void setSalary(double salary) {
          this.salary = salary;
     }
}

Static Methods and Variables

-Can be accessed at class level
-Does not require Class instance (aka Object) 
-Static variable keeps only one value during entire program execution,
 unlike Instance variable, which maintains separate values (state) per instance (Object) 
======================================================
Example: To demonstrate Static and Instance variables and methods

public class AccountHandler {
     public static double MAX_DEPOSIT_LIMIT = 1000000;         
     //Instance method to deposit specified amount to specified customer Id
     public void doDeposit(String customerId, double amount) {
          if (amount > MAX_DEPOSIT_LIMIT) {
               System.out.println("Can not process, exceeding limits, Amount: " + amount);
               return; //return to caller
          }
          System.out.println("Depositing amount " + amount + " for Customer Id : " + customerId);
     }
     //Static method to show customer's ß for the specified customer Id
     public static void showPortfolio(String customerId) {
          System.out.println("Showing Portfolio for Customer Id : " + customerId);
     }
}
---------------------------------------------------------------------------
public class TestStatic {
    public static void main(String[] args) {
          //check account deposit limits by accessing static MAX_DEPOSIT_LIMIT
          System.out.println("Allowable deposit limit : " + AccountHandler.MAX_DEPOSIT_LIMIT);
          AccountHandler handler = new AccountHandler();
          //calling instance method by using dot operator on instance of AccountHandler class
          handler.doDeposit("a007", 10000);
          //calling static method by using dot operator on AccountHandler class
          AccountHandler.showPortfolio("a007");
     }
}

Instance variables, Local variables and Method Parameters


Instance variables:
-are mainly use to store objects's state 
-visibility can be controlled by using appropriate scope (public, private, protected,default)
-lifetime is limited to containing object's lifetime

Local variables and Method parameters:
-are local to specific method 
-visibility can not be controlled its only visible inside the defined method
-lifetime is temporary and only limited to method scope
======================================================
Example: To demonstrate different types of variables
public class Customer {   
     private String lastName; //instance variable
     private String firstName; //instance variable
    
     public String getLastName() {
          return lastName;
     }
     public void setLastName(String lName) { //parameter 
          lastName = lName;
     }
     public String getFirstName() {
          return firstName;
     }
     public void setFirstName(String fName) {
          firstName = fName;
     }
     //Returns full name by concatenating Last and First name
     public String getFullName() {
          String fullName; //local variable
          fullName = getLastName() + " " + getFirstName();
          return fullName;
     }
}