Web technologies/2014-2015/Laboratory 7

Web Servers

edit

A web server can be:

  • a computer that is responsible for accepting HTTP requests from clients, which are known as Web browsers, and serving them HTTP responses along with optional data contents, which usually are Web pages such as HTML documents and linked objects (images, etc.);
  • A computer program that provides the functionality described in the first sense of the term. For example: Apache HTTP Server, Apache Tomcat Server, Internet Information Services Server (ISS), Jetty, etc.

Basically, all web serves share the following capabilities:

  • HTTP – usually, requests of this type are accepted by web servers. The response is usually a HTML document
  • HTTPS
  • Logging – usually information about requests and responses are logged into files, that can be later queried by internet administrators.
  • Configurability
  • Authentication
  • Dynamic content handling – CGI, SCGI, Perl, Python, JSP, PHP, ASP, ASP.NET etc.
  • Content compression
  • Virtual Hosts
  • Large file support
  • Module support
  • ...

Links:

Java Servlets

edit

Servlets are Java technology's answer to CGI programming. They are programs that run on a Web server and build Web pages. Their specification first appeared in June 1997. The current version is 4.0.

Creating a servlet is simple if you know Java, and have a Java compiler For those not used with servlets, but used in executing stand alone Java applications, the way you execute a servlet, it may be strange at first.

To test a servlet you need a web container. The Apache Tomcat Server will do the job.

Creating and deploying a Java Servlet

edit
  • create a class that extends HttpServlet
  • override the doGet(...) and doPost(...) methods. The first one handles content submitted using a GET method, and the second one a POST method. Usually they both call the same method for processing and handling data. They have 2 parameters:
    • HttpServletRequest: has methods that let you find out about incoming information such as FORM data, HTTP request headers, etc.
    • HttpServletResponse: has methods that lets you specify the HTTP response line (200, 404, etc.), response headers (Content-Type, Set-Cookie, etc.), and, most importantly, lets you obtain a PrintWriter used to send output back to the client.
  • enter the program code – A simple Servlet example is shown bellow:


	import java.io.*;
	import javax.servlet.*;
	import javax.servlet.http.*;
	public class SomeServlet extends HttpServlet {
		public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			// Use "request" to read incoming HTTP headers (e.g. cookies)
			// and HTML form data (e.g. data the user entered and submitted)
			// Use "response" to specify the HTTP response line and headers
			// (e.g. specifying the content type, setting cookies).
			PrintWriter out = response.getWriter();
			// Use "out" to send content to browser
			out.println(Welcome to your first servlet!);
		}
	}


  • deploy the servlet: For each servlet you need to have the following directory structure (Supose tomcat is installed in $USER_HOME):
    • a public directory ($USER_HOME/webapps/SomeServlet/). containing html, jsp files and other public resources. This is the root directory of the application
    • a $USER_HOME/webapps/SomeServlet/WEB-INF/web.xml file which represents the deployment descriptor. A short example of a deployment descriptor is as follows:


	<?xml version=”1.0” encoding=”ISO-8859-1”?>
	<!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”>
	<web-app>
		<servlet>
			<!-- Asociates to the servlet class, a servlet name used when calling it in a browser -->
			<servlet-name>MyServlet</servlet-name>
				<servlet-class>a.very.long.servlet.class.name</servlet-class>
			</servlet>
			<!-- Each servlet in the web application gets a servlet mapping The url pattern is used to map URI to servlets. The context path starts always
			with a slash ("/") and never ends in a slash. The servlet path immediately follows the context path -->
			<servlet-mapping>
				<servlet-name>MyServlet</servlet-name>
				<url-pattern>/servlet/MyServlet</url-pattern>
			</servlet-mapping>
	</web-app>


    • a $USER_HOME/webapps/SomeServlet/WEB-INF/classes/ directory. This will contain the Java classes (including the servlet classes) you use in your web application
    • a $USER_HOME/webapps/SomeServlet/WEB-INF/lib/ directory. This will contain additional libraries used in the web application

NOTE: Java NetBeans comes bundled with an Apache Tomcat Server. You can directly create/deploy your application from it without requiring the following steps. Eclipse also has the Web tool platform (WTP) which you can use. To install it please consult this tutorial. After following the above mentioned steps the servlet can then be called in a browser by typing http://localhost:8080/SomeServlet/MyServlet.

You will have to have Java EE version installed. You can find it here. Or you can add to you project classpath the servlet 3.0 jar file found here.

If you have an Apache Tomcat installation you can find the Jar file at <TOMCAT_HOME>/lib/servlet-api.jar.

Examples of servlet usages

edit

Retrieving the request headers

edit
	import java.io.*;
	import javax.servlet.*;
	import javax.servlet.http.*;
	import java.util.*;

	public class ShowRequestHeaders extends HttpServlet {
		public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			//Set the response content
			response.setContentType("text/html");
			PrintWriter out = response.getWriter();
			String title = "Servlet Example: Showing Request Headers";
			out.println("<html><head></head><body bgcolor=\"#FDF5E6\">\n" + "<h1 align=\"center\">" + title + "</h1>\n" + "<b>Request Method: </b>" + 
                        //Get the main request method. Usually POST or GET
                        request.getMethod() + "<br>\n" + "<b>Request URI: </b>" +
                        //Get the URI (the part between the hostname and port, and form data)
                        //Example: http://localhost:8080/testServlet/GetPicture?Id=1234
                        request.getRequestURI() + "<br>\n" +
                        "<b>Request Protocol: </b>" +
                        //Get the third part of the request line, usualy „HTTP/1.0” or „HTTP/1/1”
                        request.getProtocol() + "<br><br>\n" + "<table border=\"1\" align=\"center\">\n" + "<tr bgcolor=\"#FFAD00\">\n" + "<th>Header Name<th>Header Value");
		
			//Get an enumeration containing all the header names received
			Enumeration headerNames = request.getHeaderNames();
			while (headerNames.hasMoreElements()) {
				//Obtain header name
				String headerName = (String)headerNames.nextElement();
				out.println("<tr><td>" + headerName);
				//Get the content of the header
				out.println(" <td>" + request.getHeader(headerName));
			}

			out.println("</table>\n</body></html>");
		}

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


Other useful methods:

  • the getAuthType and getRemoteUser methods, which break the Authorisation header into its component pieces
  • the getDateHeader and getIntHeader methods, which read the specified header and then convert them to Date and int values, respectively

Handling cookies

edit

For cookies we have the getCookies method, which returns the contents of the Cookie header, parsed and stored in an array of Cookie objects:


	import java.io.*;
	import javax.servlet.*;
	import javax.servlet.http.*;
	import java.net.*;

	public class CookieExample extends HttpServlet {
		public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			//Get the cookie list
			Cookie[] cookies = request.getCookies();
			//Search for a cookie called name. If not found then return „New User”
			String searchString = CookieExample.getCookieValue(cookies, "name", "New User");
			//Simply print the message Hello UserName
			response.setContentType("text/html");
			PrintWriter out = response.getWriter();
			out.println(Welcome  + userName);
		}
		
		public static String getCookieValue(Cookie[] cookies, String cookieName, String defaultValue) {
			for (int i=0; i<cookies.length; i++) {
				Cookie cookie = cookies[i];
				if (cookieName.equals(cookie.getName())) {
					return(cookie.getValue());
				}
			}
			//If the cookie was not found, return the default value specified as parameter
			return (defaultValue);
		}

		@SuppressWarnings("unused")
		public static void setCookie(String cookieName, String cookieValue){
			Cookie yourCookie = new Cookie(cookieName, cookieValue);
			yourCookie.setVersion(1);
			yourCookie.setDomain("www.yourdomain.com");
			response.addCookie(yourCookie);
		}
	}

Handling sessions

edit

There are cases in which we need to store some persistent information regarding user input data. One example is an online shopping store where we need to keep track of what the user has added to its shopping cart. Several ways of achieving this exist:

  • Cookies – it has a disadvantage of not working on browser that either do not support or have cookies disabled
  • URL rewriting – basically means that every URL has to have some extra data appended at its end, data which uniquely identifies its session
  • Hidden form fields – we could have a hidden input type in the form which stores the session identifier
  • Using Servlets – Java servlets handles sessions pretty straight forwarding, by introducing a HttpSession class for managing the session data for current request. It also has the advantage of keeping data on server side, making it client safe.

We will focus in what follows on the last choice:

The HttpSession class offers us all the methods required for handling sessions:

  • getValue("key") – returns the value for the given key. Deprecated since version 2.2
  • getAttribute("key") – to be used instead of the getValue
  • putValue("key", value) – stores a session key with a given value. Deprecated since version 2.2. (It was used in association with getValue)
  • setAttribute("key", value) - stores a session key with a given value. It is used together with getAttribute
  • getValueNames() - all the attribute names in a String array. Deprecated since version 2.2
  • getAttributeNames() – all the attribute names in an Enumeration
  • getSession(true) – looks up the HttpObject currently associated with the request
  • getId() – returns the unique identifier generated for each session
  • isNew() – returns true if the client has never seen the session. This usually happens because it was just created rather than being referenced by an incoming client request. It returns false for already existing sessions.
  • getCreationTime() – returns the time in milliseconds since the epoch, at which the session was made.
  • getLastAccessedTime() - returns the time, in milliseconds since the epoch, at which the session was last sent from the client
  • getMaxInactiveInterval() – returns the amount of time in seconds, that the session should go without access before being automatically invalidated. A negative value indicates that the session should never timeout

The following fragments of code show us how we can get and set session variables:


	//Retrieving the value of a session variable:
	//This fragment can be placed in the doGet or doPost methods
	HttpSession session = request.getSession(true);
	//Get the value stored in the session attribute called userName
	String userName = (String)session.getValue("userName");
	//If it is null than we have no value
	if (previousItems != null) {
		out.println(Hello new user);
	}
	//Otherwise display a text on the page
	else {
		out.println(Hello  + userName);
	}
	//...

	//Setting a session variable:
	//This fragment can be placed in the doGet and doPost methods
	HttpSession session = request.getSession(true);
	//Get the value stored in the parameter called UserName
	String userName= request.getParameter("UserName");
	//Associate its value with the session attribute called userName
	session.putValue("userName", userName);
	//...


Form data processing

edit
	import java.io.*;
	import javax.servlet.*;
	import javax.servlet.http.*;
	import java.util.*;

	public class ManageFormData extends HttpServlet {
		public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			response.setContentType("text/html");
			PrintWriter out = response.getWriter();
			//Get the parameter UserName. This assumes there is a HTML form on the page that
			//called this servlet that has an <input type=”text” name=”UserName”>
			String enteredName = request.getParameter("UserName");
			//Set the cookie
			ManageFormData.setCookie(name, enteredName);
		}
         
		public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			doGet(request, response);
		}
         
	//Cookie methods here
	}


Alternatively we could use the getParameterNames() method to get all the parameter names. The method belongs to the HttpServletRequest class:


	...
	Enumeration paramNames = request.getParameterNames();
	//While there are elements in the enumeration loop
	while (paramNames.hasMoreElements()) {
		//Get the next parameter
		String paramName = (String)paramNames.nextElement();
		//Get the values for the parameter
		String[] paramValues = request.getParameterValues(paramName);
		//If the length of the array is one then
		if (paramValues.length == 1) {
			//Get its value
			String paramValue = paramValues[0];
			//If the length of its value its 0 than we had no data
			if (paramValue.length() == 0) {
				//No value. Handle this case
				//out.print("No Value");
			}
			//We had data so print it
			else {
				//Do something with the data
				//out.print(paramValue);
			}
		}
		else {
			for (int i=0; i<paramValues.length; i++) {
				//Do something with the value of param i: paramValues[i]);
			}
		}
	}


Links:

JDBC

edit

Java DataBase Connection (JDBC) is a standard API, through which Java developers can access databases, regardless of the driver and database product.

NOTE: see and try also HSQLDB for an easy to run and test SQL database.

In order for JDBC to be used we need:

  • at least JDK 1.1
  • a JDBC driver (see https://www.geeksforgeeks.org/jdbc-drivers/. Here is a list). If you do not want to download and install any JDBC drivers, and if you use JDK 1.1, you should know that Sun provides for this JDK version a driver that is ODBC compatible. You should be able, by using it, to connect to any ODBC compliant database. Nevertheless you will need to create an ODBC data-source for your database, for your applications to access it.

There are several steps needed in order to access a database through JDBC:

  • Load database driver (2 options exist):
    • load the default Sun jdbc-odbc driver


	//Attempt to load database driver
	try{
		// Load Sun's jdbc-odbc driver
		Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
	}
	//Driver not found
	catch (ClassNotFoundException cnfe) {
		System.err.println ("Unable to load database driver");
		System.err.println ("Details : " + cnfe);
		System.exit(0);
	}



	//Attempt to load database driver
	try{
		// Load connector/J driver
		Class.forName("com.mysql.jdbc.Driver").newInstance();
	}
	//Driver not found
	catch (ClassNotFoundException cnfe) {
		System.err.println ("Unable to load database driver");
		System.err.println ("Details : " + cnfe);
		System.exit(0);
	}


  • Connect to the database driver:


	// Create a URL that identifies database
	String url = "jdbc:odbc:" + args[0];
	//The URL is made of the following: jdbc:<subprotocol>:<name>
	//<subprotocol> - represents the name of a valid driver or other solution for databases connection.
	//<name> - is an alias, corresponding to the physical database. Its syntax is the following: //hostname:port/databasename

	//Create the actual connection (uncomment what you want use):
	//a) Using the default Sun jdbc-odbc driver
	//Connection db_connection = DriverManager.getConnection (url, "user", "password");
	//b) using the connector/J driver for MySQL databases
	//Connection db_connection = DriverManager.getConnection("jdbc:mysql://localhost/test?" + "user=YOUR_USER&password=USER_PASSWORD");

Execute queries:

edit

Executing updates: can be accomplished in 3 different ways:

  • using Statement: used for sending simple SQL instructions, without parameters
	//Create a statement used to send SQL commands
	Statement db_statement = db_connection.createStatement();
	//Create a simple table, which stores a user ID, name and password
	db_statement.executeUpdate ("create table users { int id, char(50) name, char(50) password };");
	//Insert a user, so the table contains data
	b_statement.executeUpdate ("insert into users values (1, 'John', 'md5_encrypted_password');");
	//Commit changes
	db_connection.commit();


  • using PreparedStatement: used for sending pre-compiled parameterised SQL


	//Create a statement used to send SQL commands
	PreparedStatement db_statement = db_connection.prepareStatement("update users set name=? where id=?");
	//Give values to the variables
	db_statement.setString(1, "Dan");
	db_statement.setInt(2, 123);
	db_statement.executeUpdate ();
	//Commit changes
	db_connection.commit();
  • statements using CallableStatement: allows the use of stored procedures located on the DBMS server


  • executing queries:


    
	//Create a statement used to send SQL commands
	Statement db_statement = db_connection.createStatement();
	//Execute query
	ResultSet result = db_statement.executeQuery("select * from users");
	//While more rows exist, print them
	while (result.next()){
		//Use the getInt method to obtain user id
		System.out.println ("ID : " + result.getInt("ID"));
		//Use the getString method to obtain user name
		System.out.println ("Name : " + result.getString("Name"));
		System.out.println ();
	}


NOTE: Queries can also be executed by the means of the 3 methods described above.

Links:


Exercises

edit

Start a simple Java servlet (use the examples from the lab) and deployed the on a web container. Steps for setting up Servlets in Eclipse IDE can be found here.

I recommend using Jetty

You can find useful information here and here.

For JDBC please consult these links: link1, link2. For more information about installing JDBC in eclipse please consult these links: link1

Complete Example of using sqlite in Java can be found here.

Homework

edit
  • Create 2 small servlets and 2 HTML pages with the following functionality:
    • the first HTML page will contain a form having the following fields:
      • user first name (text)
      • user last name (text)
      • user username (text)
      • user password (password - at least 6 characters with validation)
      • user retyped password (password)
      • user address (text)
      • user email (text – with js validation)
      • user interests (textarea)
      • clear form button and a submit button
      • Only the first part of the Homework is mandatory. The second part will be added to the end of the JSP laboratory from next week.
    • the second HTML page will contain a form for querying a database for users as follows:
      • a search textbox where the searched user (complete or partial) will be entered
      • 2 radio buttons (one called Exact search and the other Containing) for search options.
      • a submit button
    • the first servlet will store the user information from the first HTML page both inside a session and inside a database. The database structure will be designed so that it can hold the submitted information.
    • the second servlet will return the result of the query performed by the second HTML page.


HINT: see [1] for a way of creating a database from Netbeans

Gabriel Iuhasz, 2019-10-29, iuhasz.gabriel@e-uvt.ro