Download Servlets (Hunter) Chapter 10 and 3rd project

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Servlets Chapter 10
Applet/servlet communication
(with a database twist)
Why would you want appletservlet communication?
• At the time the text was written, jsp had
not established itself as THE way to do UI.
(It still hasn’t but that’s another story).
• Flex wasn’t around yet as a presentation
option.
• The java api is big and you can build nice
UI with it, although it is not always quick or
easy.
What is involved in applet-servlet
communication?
• The original applet specification prohibited applets from
modifying files on the client’s machine, basically treating
the applet as “untrusted”.
• Later specifications allowed for “trusted” applets, making
possible an applet to configure Java Web Server, or an
applet to provide UI for a Blog/Chat.
• Typically, an “untrusted” applet would need to
communicate with the server to present information in a
nice format, to the user.
Why the need for applet-servlet
communication?
• An applet handling chat, or providing dowjones info would need to communicate
with the server for updates.
Before JDK1.1
1. Establish http connection to CGI program
on server. The applet acts like a
browser.
2. Have applet establish a raw socket
connection to a non-http server. This
program would listen on some port and
communicate using a custom protocol.
Choice 1: pros
• Choice 1 is easy to write. Applet can use java.net.URL
and .URLConnection classes to manage the channel,
and the CGI program can be written as usual.
• Even if the applet is behind a firewall it should work.
(Firewalls typically allow http connections but disallow
raw sockets).
• The server-side programming can be done in any
language.
• It works for jdk1.0 and so works for all java-enabled
browsers.
• Using https, it would be possible to establish a secure
connection.
• The same CGI program could be accessed by browsers
as well.
Choice 1: cons
• It is slow. The two programs can’t
communicate interactively. There’s also a
delay when the CGI launches.
• Requests are typically an array of
name/value pairs.
• Responses must be formatted in a
previously devised manner.
• Only the applet can initiate the
communication.
Choice 2 pros & cons
•
•
•
•
•
Allows bi-directional sustained communication.
The server-side program can be more efficient.
BUT
It fails if the applet is behind a firewall.
The server-side code may be complicated to
write. Some process must be listening at a port.
• A custom protocol may need to be developed.
• The server-side program probably can’t be used
by browers.
Servlets and object serialization
• Servlets have made much headway
replacing slow CGI programs.
• Java object serialization simplifies the
applet-servlet communication model.
• A dedicated communication “object” can
be passed back and forth.
JDBC, CORBA, RMI
• Jdk1.1 added jdbc and rmi to the java api.
• In theory, an applet could use jdbc to
directly connect to a database server,
although in general, going through a
servlet is better. To look up something in
the database, an applet might pass
information to a servlet which connects to
the db and then passes back an object
(which might just be a string.)
RMI
•
•
•
Remote method invocation allows an applet to invoke methods of a java
object on a server and possibly allows that server object to invoke applet
methods, too.
It allows applets and server objects to communicate using a high-level o-o
paradigm.
With RMI there is no “request” or “response” – those are http terms.
RMI
Instead, there are method invokations An applet might get a stock’s daily
high by calling stockserver.dailyhigh(…)
The server can make “call backs” to methods of an applet, maybe indicating
a stock price has changed by calling theapplet.update(…)
It can work through a firewall using a technique called tunneling (a nontrivial activity, or RMI could use the HTTP protocol.) HTTP does not support
call-backs and has other overhead cost.
.
•
•
RMI
• RMI uses “stubs” and “skeleton” classes, because the caller needs
to know something about the way the callee looks, works and is
called.
• RMI uses a naming registry so clients can obtain references to
remote objects.
• Netscape $.X and up supported RMI (I think Firefox does but
haven’t tried it) IE does not support RMI.
• RMI requires a java client.
CORBA
• Common-object-request-brokerarchitecture is similar to RMI.
• It allows for distributed objects written in
different languages.
• With CORBA and IIOP communication, a
C++ client might communicate with a
servlet. This is not covered in the Hunter
text.
Hunter’s chapter 10 example(s)
• Hunter develops an applet/servlet that use All-of-theabove (as available) for communication. Ie., try RMI, if
not supported by the browser, try a socket, but if the
applet is behind a firewall, try HTTP.
• Hunter’s example is the Daytime Server. It sends time of
day. The applet has a GUI in which the time, retrieved
via different mechanisms from the servlet, is displayed.
• Some methods used are deprecated.
• I don’t remember if I tried this in Netscape at the time I
built it, but I would have to revisit it to see if it works in
Firefox. (See next screen where RMI does NOT come
up in IE).
Applet called
The applet slide#1
import java.io.*;
import java.net.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import com.oreilly.servlet.HttpMessage;
public class DaytimeApplet extends JApplet implements ActionListener{
static final int DEFAULT_PORT = 1313;
TextField httpText, httpObject, socketText, socketObject, RMIObject;
Button refresh;
public void init() {
// Construct the user interface
Container c=getContentPane();
c.setLayout(new BorderLayout());
// On the left create labels for the various communication
// mechanisms
Panel west = new Panel();
west.setLayout(new GridLayout(5, 1));
west.add(new Label("HTTP text: ", Label.RIGHT));
west.add(new Label("HTTP object: ", Label.RIGHT));
west.add(new Label("Socket text: ", Label.RIGHT));
west.add(new Label("Socket object: ", Label.RIGHT));
west.add(new Label("RMI object: ", Label.RIGHT));
c.add("West", west);
Applet slide 2
// On the right create text fields to display the retrieved time values
Panel center = new Panel();
center.setLayout(new GridLayout(5, 1));
httpText = new TextField();
httpText.setEditable(false);
center.add(httpText);
httpObject = new TextField();
httpObject.setEditable(false);
center.add(httpObject);
socketText = new TextField();
socketText.setEditable(false);
center.add(socketText);
socketObject = new TextField();
socketObject.setEditable(false);
center.add(socketObject);
RMIObject = new TextField();
RMIObject.setEditable(false);
center.add(RMIObject);
c.add("Center", center);
// On the bottom create a button to update the times
Panel south = new Panel();
refresh = new Button("Refresh");
south.add(refresh);
c.add("South", south);
refresh();
refresh.addActionListener(this);
}
Applet slide 3
private void refresh() {
// Fetch and display the time values
httpText.setText(getDateUsingHttpText());
httpObject.setText(getDateUsingHttpObject());
// socketText.setText(getDateUsingSocketText());
// socketObject.setText(getDateUsingSocketObject());
// RMIObject.setText(getDateUsingRMIObject()); }
private String getDateUsingHttpText() {
try {
// Construct a URL referring to the servlet
URL url = new URL( "http://CSCI345.oneonta.edu:8080/myexamples/DaytimeServlet");
// Create a com.oreilly.servlet.HttpMessage to communicate with that URL
HttpMessage msg = new HttpMessage(url);
// Send a GET message to the servlet, with no query string
// Get the response as an InputStream
InputStream in = msg.sendGetMessage();
// Wrap the InputStream with a DataInputStream
DataInputStream result =
new DataInputStream(new BufferedInputStream(in));
// Read the first line of the response, which should be
// a string representation of the current time
String date = result.readLine();
// Close the InputStream
in.close();
// Return the retrieved time
return date; }
catch (Exception e) {
// If there was a problem, print to System.out
// (typically the Java console) and return null
e.printStackTrace();
return null; } }
Applet slide 4
private String getDateUsingHttpObject() {
try {
// Construct a URL referring to the servlet
URL url = new URL(
"http://CSCI345.oneonta.edu:8080/myexamples/DaytimeServlet");
// Create a com.oreilly.servlet.HttpMessage to communicate with that URL
HttpMessage msg = new HttpMessage(url);
// Construct a Properties list to say format=object
Properties props = new Properties();
props.put("format", "object");
// Send a GET message to the servlet, passing "props" as a query string
// Get the response as an ObjectInputStream
InputStream in = msg.sendGetMessage(props);
ObjectInputStream result = new ObjectInputStream(in);
// Read the Date object from the stream
Object obj = result.readObject();
Date date = (Date)obj;
// Return the string representation of the Date
return date.toString(); }
catch (Exception e) {
// If there was a problem, print to System.out
// (typically the Java console) and return null
e.printStackTrace();
return null; } }
Applet slide 5
private int getSocketPort() {
try { return Integer.parseInt(getParameter("socketPort")); }
catch (NumberFormatException e) { return DEFAULT_PORT; } }
private String getDateUsingSocketText() {
InputStream in = null;
try {
// Establish a socket connection with the servlet
Socket socket = new Socket(getCodeBase().getHost(), getSocketPort());
// Print an empty line, indicating we want the time as plain text
PrintStream out = new PrintStream(socket.getOutputStream());
out.println();
out.flush();
// Read the first line of the response
// It should contain the current time
in = socket.getInputStream();
DataInputStream result =
new DataInputStream(new BufferedInputStream(in));
String date = result.readLine();
// Return the retrieved string
return date; }
catch (Exception e) {
// If there was a problem, print to System.out
// (typically the Java console) and return null
e.printStackTrace();
return null; }
finally {
// Always close the connection
// This code executes no matter how the try block completes
if (in != null) {
try { in.close(); }
catch (IOException ignored) { }
} } }
Applet slide6
private String getDateUsingSocketObject() {
InputStream in = null;
try {
// Establish a socket connection with the servlet
Socket socket = new Socket(getCodeBase().getHost(), getSocketPort());
// Print a line saying "object", indicating we want the time as
// a serialized Date object
PrintStream out = new PrintStream(socket.getOutputStream());
out.println("object");
out.flush();
// Create an ObjectInputStream to read the response
in = socket.getInputStream();
ObjectInputStream result =
new ObjectInputStream(new BufferedInputStream(in));
// Read an object, and cast it to be a Date
Object obj = result.readObject();
Date date = (Date)obj;
// Return a string representation of the retrieved Date
return date.toString(); }
catch (Exception e) {
// If there was a problem, print to System.out
// (typically the Java console) and return null
e.printStackTrace();
return null; }
finally {
// Always close the connection
// This code executes no matter how the try block completes
if (in != null) {
try { in.close(); }
catch (IOException ignored) { }
} } }
Applet slide 7
private String getRegistryHost() {
return getCodeBase().getHost(); }
private int getRegistryPort() {
try { return Integer.parseInt(getParameter("registryPort")); }
catch (NumberFormatException e) { return Registry.REGISTRY_PORT; } }
private String getRegistryName() {
String name = getParameter("registryName");
if (name == null) {
name = "DaytimeServlet"; // default }
return name; }
private String getDateUsingRMIObject() {
try {
Registry registry =
LocateRegistry.getRegistry(getRegistryHost(), getRegistryPort());
DaytimeServer daytime =
(DaytimeServer)registry.lookup(getRegistryName());
return daytime.getDate().toString();
}
catch (ClassCastException e) {
System.out.println("Retrieved object was not a DaytimeServer: " +
e.getMessage()); }
catch (NotBoundException e) {
System.out.println(getRegistryName() + " not bound: " + e.getMessage()); }
catch (RemoteException e) {
System.out.println("Hit remote exception: " + e.getMessage()); }
catch (Exception e) {
System.out.println("Problem getting DaytimeServer reference: " +
e.getClass().getName() + ": " + e.getMessage()); }
return null; }
public void actionPerformed(ActionEvent event) {
refresh(); }}
You’ll have to fix some stuff
• I put the applet’s html and class file in the
tomcat/webapps/root directory.
• I changed the URL in it so the servlet
could be with my other servlets in
myexamples.
• I upgraded the applet to JApplet with
ActionListener from jdk1.1
• Still other deprecated stuff in it I didn’t
change.
A class used by the server for RMI
import java.util.Date;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface DaytimeServer extends Remote {
public Date getDate() throws RemoteException;
}
The servlet slide 1
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.oreilly.servlet.RemoteDaemonHttpServlet;
public class DaytimeServlet extends RemoteDaemonHttpServlet
implements DaytimeServer
{
public Date getDate() {
return new Date(); }
public void init(ServletConfig config) throws ServletException {
// As before, if you override init() you have to call super.init()
super.init(config);
}
Servlet slide 2
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// If the client says "format=object" then
// send the Date as a serialized object
if ("object".equals(req.getParameter("format"))) {
ObjectOutputStream out = new ObjectOutputStream(res.getOutputStream());
out.writeObject(getDate()); }
// Otherwise send the Date as a normal ASCII string
else {
PrintWriter out = res.getWriter();
out.println(getDate().toString()); } }
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
doGet(req, res); }
public void destroy() {
// If you override destroy() you also have to call super.destroy()
super.destroy(); }
// Handle a client's socket connection by spawning a DaytimeConnection
// thread.
public void handleClient(Socket client) {
new DaytimeConnection(this, client).start(); }}
Server slide 3
class DaytimeConnection extends Thread {
DaytimeServlet servlet;
Socket client;
DaytimeConnection(DaytimeServlet servlet, Socket client) {
this.servlet = servlet;
this.client = client;
setPriority(NORM_PRIORITY - 1); }
public void run() {
try {
// Read the first line sent by the client
DataInputStream in = new DataInputStream(
new BufferedInputStream(
client.getInputStream()));
String line = in.readLine();
// If it was "object" then return the Date as a serialized object
if ("object".equals(line)) {
ObjectOutputStream out =
new ObjectOutputStream(client.getOutputStream());
out.writeObject(servlet.getDate());
out.close();
}
// Otherwise, send the Date as a normal string
else {
// Wrap a PrintStream around the Socket's OutputStream
PrintStream out = new PrintStream(client.getOutputStream());
out.println(servlet.getDate().toString());
out.close();
}
// Be sure to close the connection
client.close(); }
catch (IOException e) {
servlet.getServletContext()
.log(e, "IOException while handling client request"); }
catch (Exception e) {
servlet.getServletContext()
.log("Exception while handling client request"); } }}
Changes to servlet
• The RMI part is not working ---I need to
look at the registry stuff to see why.
• One thing… jdk1.5 no longer provides
skeleton parts of the rmic method for the
server side, only stubs are provided, so I
might try doing this one in jdk1.4 (to match
what the text describes).
Applet called
Servlet called directly from tomcat
MySQL
• Click on the administration tool
• It will put a ryg stoplight in the bottom
corner of your screen
• Select this icon (show me)
• Start the server standalone
MySQL
MySQL
• MySQL is a real database tool, with security, and an
administrative program. (MySQLAdministrator) It can
manipulate a number of databases.
Here’s a table I created in the test
database
In mysqlcc directory
• Run mysqlcc
• Select query then select insert (or delete)
record.
• You can also edit the table itself and
change the field datatypes.
mysqlcc allows you to edit tables
A servlet that looks into the test database
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;
public class Servlet2 extends HttpServletJXGB {
//Initialize global variables
public void init(ServletConfig config) throws ServletException {
super.init(config); }
//Process the HTTP Get request
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = new PrintWriter (response.getOutputStream());
Connection conn=myBroker.getConnection();
Statement stmt=null;
String query="";
out.println("<html>");
out.println("<head><title>Servlet1</title></head>");
out.println("<body>");
//out.println("Hello World...Servlet2 is running!<BR>");
A servlet that looks into the test database:
slide 2
try {
stmt = conn.createStatement ();
query="select name,grade,age from table1";
out.println("Query: "+query+"<BR>");
ResultSet rset=stmt.executeQuery( query );
while (rset.next ()){
out.prinln("name: "+rset.getString(1));
out.println("grade: "+rset.getString(2));
out.println("age: "+rset.getString(3));
out.println("<BR>");
}
}catch (SQLException e2) {
System.out.println("SQLException: "+e2);
}finally {
try{if(stmt != null) {stmt.close();}} catch(SQLException e1){System.out.println("SQLException: "+e1);}
myBroker.freeConnection(conn); // Release connection back to pool
}
out.println("Querying a MySQL table!<BR>");
out.println("</body></html>");
out.close(); }
//Process the HTTP Post request
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException { }
public String getServletInfo() {
return "Servlet 2"; }
}
HttpServletJXGB: a special
database broker class
/**
* Database Global Broker Superclass.
* @version 1.0.0 7/28/99
* @author Marc A. Mnich
*/
import java.sql.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import sun.misc.*;
import java.util.*;
import com.javaexchange.dbConnectionBroker.*;
import org.gjt.mm.mysql.*;
/**
* Creates a two-tier database connection pool that can be shared
* by many servlets through inheritance.
* @version 1.0.0 7/28/99
* @author Marc A. Mnich
*/
public class HttpServletJXGB extends HttpServlet {
protected static DbConnectionBroker myBroker;
HttpServletJXGB slide 2
public void init (ServletConfig config) throws ServletException {
super.init(config);
if(myBroker == null) { // Only created by first servlet to call
Properties p = new Properties();
try {
p.load(new FileInputStream("p:\\classes\\JXGBconfig.dat"));
String dbDriver = (String) p.get("dbDriver");
String dbServer = (String) p.get("dbServer");
String dbLogin = (String) p.get("dbLogin");
String dbPassword = (String) p.get("dbPassword");
int minConns = Integer.parseInt((String) p.get("minConns"));
int maxConns = Integer.parseInt((String) p.get("maxConns"));
String logFileString = (String) p.get("logFileString");
double maxConnTime =
(new Double((String)p.get("maxConnTime"))).doubleValue();
myBroker = new
DbConnectionBroker(dbDriver,dbServer,dbLogin,dbPassword,
minConns,maxConns,logFileString,maxConnTime);
}
catch (FileNotFoundException f) {System.out.println("File not found "+f.toString());}
catch (IOException e) {System.out.println("IO Exception "+e.toString());}
}
}
}
.dat file in p:/classes specifies
database used by broker
dbDriver=org.gjt.mm.mysql.Driver
dbServer=jdbc:mysql://localhost/test
dbLogin=
dbPassword=
minConns=10
maxConns=20
logFileString=p:\\classes\\connections.log
maxConnTime=2
Querying a mysql table
Applet uses sendPostMessage from
HttpMessage class to upload a serailizable
object
public InputStream sendPostMessage(Serializable obj) throws IOException{
URLConnection con=servlet.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type","application/x-java-serailizableobject");
ObjectOutputStream out= new ObjectOutputStream(con.getOutputStream());
out.writeObject(obj);
out.flush();
out.close();
return con.getInputStream();
}
The applet passing & receiving
(string) objects from servlet
Printed in system.out (server dos
display)
Object applet: refresh display button code
private void refresh() {
// Fetch and display the time values
String s=httpSendObject.getText();
try{
if(s.length()>0){
URL url = new URL(
"http://CSCI345.oneonta.edu:8080/myexamples/ObjectServlet");
HttpMessage msg=new HttpMessage(url);
InputStream in=msg.sendPostMessage(s);
ObjectInputStream br=new ObjectInputStream (in);
String tmp=(String) br.readObject();
httpSendObject.setText("msg"+tmp);
}//if
httpReceiveObject.setText(getHttpObject());
}//try
catch(IOException e){}
catch(ClassNotFoundException e){}
}
ObjectServlet
public String getMessage(){ct++;return message+ct;}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// If the client says "format=object" then
// send the Date as a serialized object
if ("object".equals(req.getParameter("format"))) {
ObjectOutputStream out = new
ObjectOutputStream(res.getOutputStream());
out.writeObject(getMessage());
}
else{
PrintWriter out = res.getWriter();
out.println(getMessage());
}
ObjectServlet
public void doPost(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
ObjectInputStream objin= new
ObjectInputStream(req.getInputStream());
try{
String s= (String) objin.readObject();
System.out.println("from applet"+s);
}
catch(ClassNotFoundException
e){System.out.println("class not found ex line 37");}
}//method
ObjectServlet
public void handleClient(Socket client) {
new ObjectConnection(this, client).start();
}}
class ObjectConnection extends Thread {
ObjectServlet servlet;
Socket client;
ObjectServlet, thread continued
public ObjectConnection(ObjectServlet servlet, Socket client) {
this.servlet = servlet;
this.client = client;
setPriority(NORM_PRIORITY - 1); }
public void run() {
try {
// Read the first line sent by the client
ObjectInputStream in = new ObjectInputStream(
client.getInputStream());
String line = (String) in.readLine();
// If it was "object" then return the message as a serialized object
if ("object".equals(line)) {
ObjectOutputStream out =
new ObjectOutputStream(client.getOutputStream());
out.writeObject(servlet.getMessage());
out.close();
}
// Be sure to close the connection
client.close(); }
catch (IOException e) {
servlet.getServletContext()
.log(e, "IOException while handling client request"); }
catch (Exception e) {
servlet.getServletContext()
.log("Exception while handling client request"); } }}
Related documents