12/30/2008

sendError / setStatus

The HttpServletResponse interface has fields as status codes.
e.g.
404 : SC_NOT_FOUND 
500 : SC_INTERNAL_SERVER_ERROR 

It is recommended to use status codes for the sendError method and sendStatus method.

sendError(int sc) 
Returns an error response to the client using a specified status code.

sendError(int sc, String msg) 
Returns an error response with a message.

setStatus(int sc) 
Set the status code for the response.
e.g.
SC_OK (200) 
SC_MOVED_TEMPORARILY (302)

You should use the sendError method for an error response.

HttpServletResponse

The HttpServletResponse interface extends the ServletResponse interface.

Getting a PrintWriter object for output
PrintWriter getWriter()
javax.servlet.ServletResponse has this method.

Character encording
void setCharacterEncoding(String charset)
    Invoke it before the getWriter.
    Invoke it before the response is committed.
void setContentType(String type)
    Invoke it before the getWriter
    Invoke it before the response is committed.
javax.servlet.ServletResponse has these methods.

Redirect
void sendRedirect(String location)
Specify the relative path. If the relative path starts with "/", it's relative to the container root.
    e.g.    /scwcd/Test
    e.g.    Test
The sendRedirect method returns a response to the client, and then redirects it to "location".
You cannot use request attributes.
If you want to redirect a response to other domain, specify "location" like "http://...".

URL rewriting
String encodeUrl(String url)
String encodeRedirectURL(String url)
URL rewriting is for creating a session for a browser that doesn't support cookies.
These methods are used for "location" for the sendRedirect method.

<Sample>
import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.http.*;

public class Test extends HttpServlet {
    public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        if (req.getParameter("information").equals("")) {
            res.sendRedirect("/scwcd/index.html");
        } else {
            PrintWriter out = res.getWriter();
            out.println("<html><body>");
            out.println(req.getParameter("information"));
            out.println("</body></html>");
        }
    }
}

index.html
...
<form action="/scwcd/Test" method="post">
<input type="text" name="information" size="30" maxlength="15" /><br />
<input type="submit" value="Send"/>
</form>
...

<Result>
What you put will be displayed. If you don't put anything in the form, nothing can be displayed.

HttpServletRequest

The HttpServletRequest interface extends the ServletRequest interface.

Character encoding for a request
void setCharacterEncoding(String env) 
javax.servlet.ServletRequest has this method.

Getting a parameter
String getParameter(String name) 
Map getParameterMap() 
Enumeration getParameterNames() 
String[] getParameterValues(String name) 
javax.servlet.ServletRequest has these methods

Getting headers
String getHeader(String name) 
Enumeration getHeaderNames() 
Enumeration getHeaders(String name) 

About request attributes
Object getAttribute(String name) 
Enumeration getAttributeNames() 
void setAttribute(String name, Object o)
javax.servlet.ServletRequest has these methods

GET / POST

HTTP GET
You can use a hyper link for a GET request.
You can add parameters as query information.

HTTP POST
Parameters are contained within the body.
It is said that HTTP POST is safer than HTTP GET.

Transfering a request from a HTML file to a Servlet

Hyper link(GET)
<a href="/scwcd/Test?information=Hello everyone">Test</a>
The result will be "Hello everyone"

Using a form (GET)
<form action="/scwcd/Test">
<input type="text" name="information" size="30" maxlength="15" /><br />
<input type="submit" value="Send"/>
</form>
The method attribute of a form is "get" by default.
What you put in the form will be displayed in a Servlet.

In the example below, a doGet method is not defined in a Servlet, but a service method and a doPost method is defined.
In this case, the doPost metod works because every request goes through a service method.
The overridden service method calls the doPost method, so Test.java works.

Test.java
import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.*;
import javax.servlet.http.*;

public class Test extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) {
        try {
            doPost((HttpServletRequest)req, (HttpServletResponse)res);
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

        PrintWriter out = res.getWriter();
        out.println("<html><body>");
        out.println(req.getParameter("information"));
        out.println("</body></html>");
    }
}

12/29/2008

HttpServlet

A Servlet extends the javax.servlet.http.HttpServlet class.
In a Servlet, you can override doXxxx methods.
<Sample (JDK5.0+Tomcat5.5)>
Directory

scwcd
    + WEB-INF
        + src
            + sample
        + classes
             + sample
        web.xml


Test.java
import java.io.*;

import javax.servlet.ServletException;
import javax.servlet.http.*;

@SuppressWarnings("serial")
public class Test extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {

        PrintWriter out = res.getWriter();
        out.println("<html><body>");
        out.println("Hello");
        out.println("</body></html>");
    }
}

web.xml
<?xml version="1.0" encoding="UTF-8" ?>
<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/web-app_2_4.xsd"
    version="2.4">
    <description>scwcd</description>
    <display-name>scwcd</display-name>
    <distributable />

    <servlet>
        <servlet-name>Test</servlet-name>
        <servlet-class>sample.Test</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Test</servlet-name>
        <url-pattern>/Test</url-pattern>
    </servlet-mapping>
</web-app>

See http://localhost:8080/scwcd/Test on your browser.

<Result>
Hello

Tags in the web.xml
servlet             :    Information for a Servlet
servlet-name     :    Servlet name
servlet-class     :    [package name].[Servlet name]
Use a jsp-file tag for specifying a jsp file
servlet-mapping    :    Mapping between a Servlet and URL
url-pattern        :    The URL pattern for a Servlet

URL is like this:
http://[domain]/[project root]/[Savlet name]


The distributable tag
That means the application can be deployed in a distributed environment.

What is Servlet

The javax.servlet package provides basic interfaces and classes for a Servlet program.


Life cycle
init
  service  doXxxx  destroy

The service method
Any request to a Servlet goes through a service method.
The service method is defined in the javax.servlet.Servlet interface.
 
The doXxxx method
These methods are defined in the javax.servlet.http.HttpServlet class.
In a Servlet, these methods can be overridden.

doGet     HTTP GET request
doPost     HTTP POST request
doPut     HTTP PUT request
doHead     HTTP HEAD request
doDelete     HTTP DELETE request
doOptions     HTTP OPTIONS request
doTrace     HTTP TRACE request

 

Annotation

Annotation is something like notes in a program.
JDK 5.0 or any later version supports annortaton.
See Annotation on java.sun.com

@Override
If the method is not properly overridden, then a compile error occurs.

class Super {
    void func(){
        System.out.println("Super");
    }
}
class Sub extends Super {
    @Override
    int func() {
        System.out.println("Sub");
    }
}

___________

@Deprecated
Warning of a deprecated method.

public static void main(String[] args) {
    func();
    }
    @Deprecated
    static void func() { }
}
___________

@SuppressWarnings("deprecation")
Suppresses the warning of a deprecated method.

@SuppressWarnings("fallthrough")
Suppresses the warning of the fall-through in a switch statement

@SuppressWarnings("finally")
Suppresses the warning that a finally block is not properly finished

@SuppressWarnings("serial")
Suppresses the warning that a serialVersionUID is not defined

When you supress more than one warning, write like this:
@SuppressWarnings({"deprecation", "finally"})

Generics

JDK 5.0 or any later version supports generics.
See Generics for the details.

For Collections

/* Conventional way */
List list1 = new ArrayList();
/* Generics */
List list2 = new ArrayList();
List list3 = new ArrayList();

list1.add("Conventional");
list2.add("Generics");
list3.add(new Integer(7));

String conventional = (String) list1.get(0);
String generics = list2.get(0);
/* java.lang.ClassCastException occurs */
Integer i = (Integer)list1.get(0);
/* Compile error */
Integer i2 = (Integer)list2.get(0);


About ClassCastException
If you cast an object to a type that has no is-a relation with the object, 
But generics provide the way to find this kind of error when you complie the code.

wait, notify, notifyAll

How to use wait、notify、notifyAll methods

These methods can be used in a synchronized block.
These methods can work when the thread holds the lock.

wait
Relinquishes the lock

notify/notifyAll
Relinquishes the lock after synchronized block

See also javadoc.

Synchronization of multiple threads

If An object is accessed by multiple threads, these threads should be synchronized.
Use the 'synchronized' modifier for those cases.

In the example below, two person withdraw money from the same account.
If the savings is below 10, no one can withdraw any money.
If the savings is at or above 10, each person withdraws 10, and thus the amount of savings will never be below 0.

<Sample>
public class Sample {
    public static void main(String[] arvs) {
        Account account = new Account(100);
        Family tom = new Family(account, "Tom");
        Family bob = new Family(account, "Bob");
        tom.start();
        bob.start();
    }
}
class Family extends Thread {
    private Account account;
    private String name;
    Family (Account account, String name) {
        this.account = account;
        this.name = name;
    }
    public void run() {
        for (int i = 0; i < 6; i++) {
            if (account.withdraw(10)) {
                System.out.println(
                name + " withdrew money. The amount of savings is "
                + account.toString());
            } else {
                System.out.println(
                name + " couldn't withdraw money. The amount of savings is "
                + account.toString());
            }
        }
    }
}
/* The Account class */
class Account {
    private int savings; // savings
    Account (int savings) {
        this.savings = savings;
    }
    /* Returns true if there are enough savings to withdraw */
    private boolean withdrawable(int amount) {
        if (savings >= amount) {
            return true;
        } else {
            return false;
        }
    }
    /* Returns true if the withdrawal has been made */
    public synchronized boolean withdraw(int amount) {
        if (withdrawable(amount)) {
            // Sleep one second in order to see the flow easily
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }
            savings -= amount;
            return true;
        } else {
            return false;
        }
    }
    public String toString() {
        return String.valueOf(savings);
    }
}

<Result>
Tom withdrew money. The amount of savings is 90
Tom withdrew money. The amount of savings is 80
Tom withdrew money. The amount of savings is 70
Tom withdrew money. The amount of savings is 60
Tom withdrew money. The amount of savings is 50
Tom withdrew money. The amount of savings is 40
Bob withdrew money. The amount of savings is 30
Bob withdrew money. The amount of savings is 20
Bob withdrew money. The amount of savings is 10
Bob withdrew money. The amount of savings is 0
Bob couldn't withdraw money. The amount of savings is 0
Bob couldn't withdraw money. The amount of savings is 0

If you don't synchronized them, the result would be like this:

e.g.

Bob withdrew money. The amount of savings is 80
Tom withdrew money. The amount of savings is 80
Tom withdrew money. The amount of savings is 60
Bob withdrew money. The amount of savings is 60
Bob withdrew money. The amount of savings is 50
Tom withdrew money. The amount of savings is 50
Bob withdrew money. The amount of savings is 30
Tom withdrew money. The amount of savings is 30
Tom withdrew money. The amount of savings is 10
Bob withdrew money. The amount of savings is 10
Bob withdrew money. The amount of savings is -10
Tom withdrew money. The amount of savings is -10

As above, the amount of savings goes into negative numbers, which is considered strange.


Another way of synchronization
The code above can be synchronized by locking the common Account object.
    public void run() {
        synchronized (account) {
        for (int i = 0; i < 6; i++) {
            if (account.withdraw(10)) {
                System.out.println(
                name + " withdrew money. The amount of savings is "
                + account.toString());
            } else {
                System.out.println(
                name + " couldn't withdraw money. The amount of savings is "
                + account.toString());
            }
        }
        }
    }

In this case, any thread except the currently running thread cannnot access all methods of the Account object.

It can be said that synchornization = locking the object

A priority of a thread

Every thread has a priority.
Use the setPriority method to specify the priority.
Priorities range from 1 to 10.
It is not assured that waiting threads start in order of priority.
Therefore, it is not recommended to write a program depending on threads' priorities.

join

In a multi-thread program, use the join method to let other thread wait until one thread finishes.
e.g.
There are two thread named 'ta' and 'tb'.

ta.join() means 'tb' waits until 'ta' finishes.


class R_A implements Runnable {
    public void run(){
        for (int i = 0; i < 100; i++) {
            System.out.println("Thread "
                + Thread.currentThread().getName());
        }
    }
}
class R_B implements Runnable {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("Thread "
                + Thread.currentThread().getName());
        }
    }
}
public class ThreadRunnable1 {
    public static void main(String[] args) {
        R_A ra = new R_A();
        R_B rb = new R_B();
        Thread ta = new Thread(ra);
        Thread tb = new Thread(rb);
        ta.setName("A");    // Set a Thread name
        tb.setName("B");    // Set a Thread name
        ta.start();
        try {
            ta.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tb.start();
    }
}

<Result>
After the Thread A completes its execution, the Thread B executes its procedure.

Runnable

Basic program
Create a Thread object using a class that implements the Runnable interface as an argument.

Override the run method.

class Runnable_A implements Runnable {
    public void run(){
        for (int i = 0; i < 100; i++) {
            System.out.println("Thread "
                + Thread.currentThread().getName());
        }
    }
}
class Runnable_B implements Runnable {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("Thread "
                + Thread.currentThread().getName());
        }
    }
}
public class Test {
    public st_atic void main(String[] args) {
        Runnable_A r_a = new Runnable_A();
        Runnable_B r_b = new Runnable_B();
        Thread t_a = new Thread(r_a);
        Thread t_b = new Thread(r_b);
        t_a.setName("A");    // Set a Thread name
        t_b.setName("B");    // Set a Thread name
        t_a.st_art();
        t_b.st_art();
    }
}
<Result>
A Thread name to be displayed sometimes changes alternately.

Thread

Basic program
Extend the Thread class and override the run method


class Test {
    public static void main(String[] args) {
        Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("Hi");
                }
            }
        };
        Thread t2 = new Thread() {
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("World");
                }
            }
        };
        t1.start();
        t2.start();
    }
}

‘Hi’ or ‘World’ is randomly displayed.

‘Hi’ and ‘World’ are sometimes coming and going.

12/25/2008

Multiple threads

See java.lang.Thread about threads.
Java applications can have multiple threads of execution running concurrently.
(It depends on the thread scheduling of a computer if it has only one CPU.)
 
Implemetation

Extend the
java.lang.Thread class.

Implement the
java.lang.Runnable interface.
 
Life cycle of a thread
Generation
 → Executable → Execution → Finalization

How to make a thread unexecutable
Use these methods.

sleep
wait

How to make a waiting thread executable

Use these methods.
notify
notifyAll

How to have a running thread back to an executable state

Use this method.
yield

Synchronization

Use the synchronize keyword to synchronize multiple threads if necessary.

Anonymous inner classes

An anonymous inner class doesn’t have a class name.
You can define these classes in a method.

Sample
public class Test {
    public static void main(String[] args) {
        Super super = new Super() {
            @Override
            void func() {
                System.out.println("Anonymous class");
            }
        };
        super.func();

    }
} 
class Super {
    void func() {
        System.out.println("Super class");
    }
}

Result
Anonymous class

Local inner classes

A class defined in a method is called a local inner class.
The instance of a local inner class should be generated in the same method where the local inner class is defined.
You cannot use access modifiers but can use
final or abstract keyword
Local variables except
final variables cannot be accessed from a local inner class.
Members of an outer class can be accessed from its local inner classes.

Sample
public class Test {
    public static void main(String[] args) {
        final int x = 1;
        class Local {
            void func() {
                System.out.println(x);
            }
        }
        Local l = new Local();
        l.func();
    }
}

Result
1

 

12/23/2008

Static nested classes

You can deal with static nested classes like other static members.
Sample
public class Test {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.func();
    }
}
class Outer {
    static class Inner {
        void func(){
            System.out.println("Inner class");
        }
    }
}

Result
Inner class

12/19/2008

Inner classes

What are called inner classes are as follows:
Inner class
Static nested class
Local inner class
Anonymous class
 


Inner class
An instance of an outer class can reach its inner class.

<Sample>
public class Test
 {
    public static void main(String[] args) {
        Outer.Inner1 inner = new Outer().new Inner1();
        inner.func();
        Outer outer = new Outer();
        outer.func();
    }
}
class Outer {
    class Inner1 {
        void func(){
            System.out.println("Inner class 1");
        }
    }
    class Inner2 {
            void func(){
            System.out.println("Inner class 2");
        }
    }
    void func() {
        new Inner2().func();
    }
}

<Result>
Inner class 1
Inner class 2

 

Garbage collection

Java garbage collection destroys objects as follows:

  • Objects that nothing refers to
  • Objects that nothing can refer to.


Set an object to ‘null’
If you set a variable to null, then it refers to nothing and the garbage collection destroys this object.

Set an object to another value
If you set a variable to another value, the object previously referred to becomes a target of the garbage collection.

Integer a = new Integer(1);
Integer b = new Integer(2);
a = b;

At this time, nothing refers to the instance ‘new Integer(1)’ and thus it becomes a target of the garbage collection.

Isolate references

= null
= null

The garbage collection targets them.

Can we execute a garbage collection immediately?
No.
You can only request a garbage collection.
When to execute it depends on JVM.
 
Request a garbage collection
・ System.gc();
・ Runtime.getRuntime().gc();

finalize method
 A finalize method is invoked just before the garbage collection destroys an object.
A finalize method is invoked once for each object.
It is not recommended to write important procedure in a finalize method.

 

12/18/2008

The Collection framework

The Collection framework consists of the interfaces (List, Set, Map) and their subclasses.

You cannot use primitive values for the elements of a Collection.


Sample

List list = new ArrayList();
for (int i = 0; i <>
    list.add(new Integer(i));
}
for (int i = 0; i <>
    System.out.println(list.get(i));
}

Result
0
1
2
3
4

12/17/2008

Override the equals method and the hashCode method

When you compare two objects of your original class with an equals method, it is better to override Object class’s equals method in your original class so that overridden equals method can return true if two objects are “semantically equal”.

The equals method in the Object class returns true if the two objects are “equal”.

Override example
public class Test {
    public static void main(String[] args) {
        Cat c1 = new Cat(1);
        Cat c2 = new Cat(1);
        System.out.println(c1.equals(c2));
    }
}
class Cat { 
    private final int c;
    Cat(int c) {
        this.t = c;
    }
    public int getCatValue() {
        return c;
    }
    public boolean equals(Object obj) {
        if ((obj instanceof Cat) &&
            (((Cat)obj).getCatValue() == c)) {
            return true;
        } else {
            return false;
        }
    }
}

Result
true
_______

Override the hashCode method
It is highly recommended that you override the hashCode method in your original class when you override the equals method.
A HashXxx class such as the HashMap class stores objects based on their hash code, which enables a quick search.

The hashcode method in the Object class returns a unique hash code value.

Therefore, when you override it in your original class, it should return the same hash code value if the two objects are “semantically equal”.

An example of simple and appropriate implementation in the Cat class is as follows:


public int hashCode() {
    return c;
}

Using your original class within the Collection framework may become dangerous unless you override the hashCode method.

12/16/2008

Wrapper classes

A wrapper class wraps a primitive value in an object.
Primitive         Wrapper
byte                     Byte
short                   Short
int                         Integer
long                     Long
float                     Float
double                Double
boolean              Boolean
char                     Character

A constructor of a wrapper class can take a primitive value as an argument.

A wrapper class, except the Character class, can take a String value as an argument.

Creating objects
e.g.
Double d = new Double(7.0);
Double d = Double.valueOf(7.0);
Double d = Double.valueOf("7.0");
Double d = Double.valueOf("7.0f");
Short s = d.shortValue(d);

Getting a primitive value from a wrapper object
e.g.
double value = Double.parseDouble("2.0");
double value = Double.parseDouble("2.0d");

Comparison of objects
Use the
== operator or an equals method to compare objects.
The equals method defined in the Object class is overridden in the wrapper classes and the String class.
 However, Object’s equals method and others overridden in the String class and the wrapper class are different in behavior.
The equals method in the Object class returns true if two objects are “equal”.
 An equals method in the String class or wrapper classes returns true if two objects are “semantically equal”.

Sample
Object object1 = new Object();
Object object2 = new Object();
System.out.println("object1 == object2 : " + (object1 == object2));
System.out.println("object1.equals(object2) : " + object1.equals(object2));

Integer int1 = new Integer(5);
Integer int2 = new Integer(5);
System.out.println("int1 == int2 : " + (int1 == int2));
System.out.println("int1.equals(int2) : " + int1.equals(int2));

Result
object1 == object2 : false
object1.equals(object2) : false
int1 == int2 : false
int1.equals(int2) : true