Web Programming Unit-3 Notes
Web Programming Unit-3 Notes
Web Programming Unit-3 Notes
Basic Principles
Basically, the JDBC API is a software library providing a number of Java classes and
interfaces that allows programmers to:
1. A so-called Database URL, which encoded using standard URL syntax (protocol + host +
object). The protocol part starts always with "jdbc:" folowed by the name of the RDBMS
(in our case "mysql") and terminated with "://" symbols. Thus, the protocol part in our
example is "jdbc:mysql://". The host part identifies a server where the DBMS is running.
In our case (Servlets & DBMS on the same computer) "localhost" can be used to identify
the host. Finally, the name of a particular database must be supplied preceeded with the
slash character. In our case this would be "/example".
2. A registered username that has the proper privileges for manipulating the database.
3. A password valid for the username.
try
{
Statement statement = connection_.createStatement();
}
catch(SQLException exc)
{
exc.printStackTrace();
}
If an error occurs during the execution of the createStatement() method a SQLException will be
thrown. Instances of the Statement Class provides a public interface to insert, update, or retrieve
data from a database. Depending on a particular database operation, an appropriate method
should be invoked. For instance,
• executeUpdate() can be used to insert data into a relation
• executeQuery() can be used to retrieve data from a database
...
try
{
String insert_sql_stmt = "INSERT INTO " + table + " VALUES(" + values + ")";
statement.executeUpdate(insert_sql_stmt);
}
catch(SQLException exc){exc.printStackTrace();} ...
Other methods of the "statement" class can be also applyed to its instances.
if we need to retrieve the keys automatically generated by the "executeUpdate" statement, we
need to pass the "Statement.RETURN_GENERATED_KEYS" argument in advance.
try
{
String sql = "INSERT INTO " + table + " VALUES(" + values + ")";
statement.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
ResultSet keys = statement.getGeneratedKeys();
}
catch(SQLException exc){exc.printStackTrace();}
Similarly, to retrieve data from a database we need to obtain an instance of the Statment
class, and then to invoke executeQuery() method on this instance. This method takes a string
containing SQL source as an argument.
try
{
String sql = "SELECT ...";
ResultSet query_result = statement.executeQuery(sql);
} catch(SQLException exc){exc.printStackTrace();}
Note, that the "sql" argument should contain a valid SQL Select statement. The
executeQuery() method returns an instance of the ResultSet class. Generally, execution of any
JDBC statement that returns data from a database, results in an instance of the ResultSet class.
This instances may be seen as a number of rows (tuples) that hold the current results. The
number and type of columns in this object corresponds to the number and types of columns
returned as the result from the database system.
...
try
{
String sql = "SELECT * FROM Customer;";
ResultSet query_result = statement.executeQuery(sql);
...
The "executeQuery" command will result in obtaining an instance of the ResultSet class
which will hold all tuples from the Customer table as rows, each row will contain 3 values: "cn",
"cname" and "ccity". Normally, the SQL statement exlicitly defines the "ResultSet" internal
structure. Once when we set a current row of the ResultSet, we can retrieve values by means of
a number of methods. The methods correspond to a column type. Thus, to retrieve the value of a
string column, we invoke a getString() method. Similarily, to retrive an integer value we simply
invoke a getInt() method.
try
{
String sql = "SELECT cname, pname, qnt";
sql = sql + " FROM Customer, Product, Transaction";
sql = sql + " where Customer.ccity = \"Graz\" And";
sql = sql + " Customer.cn = Transaction.cn And";
sql = sql + " Transaction.pn = Product.pn";
ResultSet query_result = statement.executeQuery(sql);
while(query_result.next())
{
String customerName = query_result.getString("cname");
String productTitle = query_result.getString("pname");
int productQuantity = query_result.getInt("cid");
... }
Socket Programming
The basic java classes (java.net package) that supports Socket programming, namely:
o InetAddress
o Socket
o ServerSocket
o DatagramSocket
o DatagramPacket
o MulticastSocket
Example 2: The following examples show how to create TcpEchoServer and the corresponding
TcpEchoClient.
import java.net.*;
import java.io.*;
import java.util.*;
try {
reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
writer = new PrintWriter(client.getOutputStream());
writer.println("Welcome to my server"): writer.flush();
message = reader.readLine();
while (!(message == null || message.equalsIgnoreCase("exit"))) {
writer.println(message); writer.flush(); message = reader.readLine(); }
client.close(); count--;
System.out.println("Active Connections = " + count);
} catch (Exception ex) { count--;
System.out.println("Active Connections = " + count); } } }
DatagramPacket class, used to represent the data for sending and receiving.
DatagramSocket class for creating a socket used to send and receive DatagramPackets.
The java.net.DatagramPacket class:
Example 4: The following examples show how to create a UdpEchoServer and the
corresponding UdpEchoClient.
import java.net.*;
import java.io.*;
import java.net.*;
import java.io.*;
3. Multicast Sockets
Multicasting is achieved in Java using the same DatagramPacket class used for normal
Datagrams. This is used together with the MulticastSocket class. The MulticastSocket class is
a subclass of the DatagramSocket class, with the following methods for joining and leaving a
multicast group added.
void joinGroup(InetAddress mcastaddr)
void leaveGroup(InetAddress mcastaddr)
void setTimeToLive(int ttl)
Example 5: The following examples shows a sample Multicast sender and receiver.
import java.io.*;
import java.net.*;
import java.io.*;
import java.net.*;
public class MulticastSender {
public static void main(String[] args) {
MulticastSocket sender;
InetAddress group;
try {
group = InetAddress.getByName("224.100.0.5");
sender = new MulticastSocket(9095);
sender.setTimeToLive(32);
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("Enter message for Multicast: ");
String message = stdin.readLine();
if (message.length() == 0) {
sender.leaveGroup(group);
sender.close();
break;
}
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(),
group, 9095);
sender.send(packet);
} }
catch (Exception ex) { System.out.println("Exception: "+ ex); } } }
Interfaces
In RMI, the definition of a remote service is coded using a Java interface.
The implementation of the remote service is coded in a class
The key to understanding RMI is to remember that interfaces define behavior and classes
define implementation.
between theclient and the server is handled through the stub and skeleton.
Stub and Skeleton Layer
In this layer, RMI uses the Proxy design pattern. In the Proxy pattern, an object in one context is
represented by another (the proxy) in a separate context. The proxy knows how to forward
method calls between the participating objects. The following class diagram illustrates the Proxy
pattern.
In RMI's use of the Proxy pattern, the stub class plays the role of the proxy, and the remote
service implementation class plays the role of the RealSubject.
A skeleton is a helper class that is generated for RMI to use. The skeleton understands
how to communicate with the stub across the RMI link. The skeleton carries on a conversation
with the stub; it reads the parameters for the method call from the link, makes the call to the
remote service implementation object, accepts the return value, and then writes the return value
back to the stub.
The Remote Reference Layers defines and supports the invocation semantics of the RMI
connection. This layer provides a RemoteRef object that represents the link to the remote service
implementation object.
The stub objects use the invoke() method in RemoteRef to forward the method call. The
RemoteRef object understands the invocation semantics for remote services.
The JDK 1.1 implementation of RMI provides only one way for clients to connect to remote
service implementations: a unicast, point-to-point connection. Before a client can use a remote
service, the remote service must be instantiated on the server and exported to the RMI system.
The Java 2 SDK implementation of RMI adds a new semantic for the client-server connection.
In this version, RMI supports activatable remote objects. When a method call is made to the
proxy for an activatable object, RMI determines if the remote service implementation object is
dormant. If it is dormant, RMI will instantiate the object and restore its state from a disk file.
Once an activatable object is in memory, it behaves just like JDK 1.1 remote service
implementation objects.
Transport Layer
The Transport Layer makes the connection between JVMs. All connections are stream-based
network connections that use TCP/IP. Even if two JVMs are running on the same physical
computer, they connect through their host computer's TCP/IP network protocol stack. The
following diagram shows the unfettered use of TCP/IP connections between JVMs.
As you know, TCP/IP provides a persistent, stream-based connection between two machines
based on an IP address and port number at each end. Usually a DNS name is used instead of an
IP address; this means you could talk about a TCP/IP connection between
flicka.magelang.com:3452 and rosa.jguru.com:4432. In the current release of RMI, TCP/IP
connections are used as the foundation for all machine-to-machine connections.
On top of TCP/IP, RMI uses a wire level protocol called Java Remote Method Protocol (JRMP).
JRMP is a proprietary, stream-based protocol that is only partially specified is now in two
versions. The first version was released with the JDK 1.1 version of RMI and required the use of
Skeleton classes on the server. The second version was released with the Java 2 SDK. It has been
optimized for performance and does not require skeleton classes.Some other changes with the
Java 2 SDK are that RMI service interfaces are not required to extend from java.rmi.Remote and
their service methods do not necessarily throw RemoteException.
RMI can use many different directory services, including the Java Naming and Directory
Interface (JNDI). RMI itself includes a simple service called the RMI Registry, rmiregistry. The
RMI Registry runs on each machine that hosts remote service objects and accepts queries for
services, by default on port 1099.
On a host machine, a server program creates a remote service by first creating a local object that
implements that service. Next, it exports that object to RMI. When the object is exported, RMI
creates a listening service that waits for clients to connect and request the service. After
exporting, the server registers the object in the RMI Registry under a public name.
On the client side, the RMI Registry is accessed through the static class Naming. It provides the
method lookup() that a client uses to query a registry. The method lookup() accepts a URL that
specifies the server host name and the name of the desired service. The method returns a remote
reference to the service object. The URL takes the form:
rmi://<host_name>
[:<name_service_port>]
/<service_name>
where the host_name is a name recognized on the local area network (LAN) or a DNS name on
the Internet. The name_service_port only needs to be specified only if the naming service is
running on a different port to the default 1099.
Build a simple remote calculator service and use it from a client program.
A working RMI system is composed of several parts.
To simplify things, you will use a single directory for the client and server code. By running the
client and the server out of the same directory, you will not have to set up an HTTP or FTP
server to provide the class files.Assuming that the RMI system is already designed, you take the
following steps to build a system:
1. Interfaces: First, write and compile the Java code for the service interface. The
Calculator interface defines all of the remote features offered by the service:
2. Implementation
Next, write the implementation for the remote service. This is the CalculatorImpl class:
implements Calculator {
//RemoteException exception
super(); }
The implementation class uses UnicastRemoteObject to link into the RMI system. In the
example the implementation class directly extends UnicastRemoteObject. This is not a
requirement. A class that does not extend UnicastRemoteObject may use its exportObject()
method to be linked into RMI.
3. Stubs and Skeletons: You next use the RMI compiler, rmic, to generate the stub and skeleton
files. The compiler runs on the remote service implementation class file.
>rmic CalculatorImpl
4. Host Server: Remote RMI services must be hosted in a server process. The class
CalculatorServer is a very simple server that provides the bare essentials for hosting.
import java.rmi.Naming;
public class CalculatorServer {
public CalculatorServer() {
try {
Naming.rebind("rmi://localhost:1099/CalculatorService", c);
try {
System.out.println( c.sub(4, 3) );
System.out.println( c.add(4, 5) );
System.out.println( c.mul(3, 6) );
System.out.println( c.div(9, 3) );
System.out.println();
System.out.println("MalformedURLException");
System.out.println(murle); }
catch (RemoteException re) {
System.out.println();
System.out.println("RemoteException");
System.out.println(re); }
System.out.println();
System.out.println("NotBoundException");
System.out.println(nbe); }
System.out.println();
System.out.println("java.lang.ArithmeticException");
System.out.println(ae); } }}
You are now ready to run the system! You need to start three consoles, one for the server, one
for the client, and one for the RMIRegistry.
Start with the Registry. You must be in the directory that contains the classes you have written.
From there, enter the following: > rmiregistry
If all goes well, the registry will start running and you can switch to the next console.
In the second console start the server hosting the CalculatorService, and enter the following:
>java CalculatorServer
It will start, load the implementation into memory and wait for a client connection.