According to thread MVC above, I create web.xml like this

<servlet>
        <servlet-name>addServlet</servlet-name>
        <servlet-class>servlet.AddServlet</servlet-class>
        <init-param>
            <param-name>dbURL</param-name>
            <param-value>jdbc:odbc:database</param-value>
        </init-param>
        <init-param>
            <param-name>dbUserName</param-name>
            <param-value>username</param-value>
        </init-param>
        <init-param>
            <param-name>dbPassword</param-name>
            <param-value>password</param-value>
        </init-param>
        <init-param>
            <param-name>JdbcDriver</param-name>
            <param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
        </init-param>
    </servlet>
    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>servlet.loginServlet</servlet-class>
        <init-param>
            <param-name>dbURL</param-name>
            <param-value>jdbc:odbc:database</param-value>
        </init-param>
        <init-param>
            <param-name>dbUserName</param-name>
            <param-value>username</param-value>
        </init-param>
        <init-param>
            <param-name>dbPassword</param-name>
            <param-value>password</param-value>
        </init-param>
        <init-param>
            <param-name>JdbcDriver</param-name>
            <param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
        </init-param>
    </servlet>
    <servlet>
        <servlet-name>registerServlet</servlet-name>
        <servlet-class>servlet.registerServlet</servlet-class>
        <init-param>
            <param-name>dbURL</param-name>
            <param-value>jdbc:odbc:database</param-value>
        </init-param>
        <init-param>
            <param-name>dbUserName</param-name>
            <param-value>username</param-value>
        </init-param>
        <init-param>
            <param-name>dbPassword</param-name>
            <param-value>password</param-value>
        </init-param>
        <init-param>
            <param-name>JdbcDriver</param-name>
            <param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
        </init-param>
    </servlet>

myServlet.java

...
public void init(ServletConfig config) throws ServletException {
   super.init(config);
   dm = new dataManager();
   dm.setDbURL(config.getInitParameter("dbURL"));
   dm.setDbUserName(config.getInitParameter("dbUserName"));
   dm.setDbPassword(config.getInitParameter("dbPassword"));
   try {
      Class.forName(config.getInitParameter("JdbcDriver"));
   }
   catch (Exception ex) {
      System.out.println("Initialize connector string");
      ex.printStackTrace();
   }
}
...

Is there any other way to minimize the code in web.xml, so I don't have to add init parameter in all servlet.

Btw, how can I get the id of Array, so I can take an action for it.
For example, if I delete the title number 1, it will be delete title number 1, and if I wan to edit title number 2, it will edit title number 2.

Better illustration is in the attachment.

Thanks a lot

Recommended Answers

All 21 Replies

<servlet>
        <servlet-name>addServlet</servlet-name>
        <servlet-class>servlet.AddServlet</servlet-class>
        
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>servlet.loginServlet</servlet-class>
        
        <servlet-name>registerServlet</servlet-name>
        <servlet-class>servlet.registerServlet</servlet-class>

<!-- ONLY ONE DECLARATION NEED IT -->
        <init-param>
            <param-name>dbURL</param-name>
            <param-value>jdbc:odbc:database</param-value>
        </init-param>
        <init-param>
            <param-name>dbUserName</param-name>
            <param-value>username</param-value>
        </init-param>
        <init-param>
            <param-name>dbPassword</param-name>
            <param-value>password</param-value>
        </init-param>
        <init-param>
            <param-name>JdbcDriver</param-name>
            <param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
        </init-param>
    </servlet>

peter_budo you are fantastic..

Any clue with my other question, I still looking for..

Your titles should be linked with some unique IDs. So then when you select something to delete, you will not use a title that can repeat multiple times, but ID associated with that title

I try to give an Id for the title, but when I hit the delete button, it said NullPointer Exception.

tilte.jsp

<%@page contentType="text/html" pageEncoding="UTF-8" %>
<%@page import="java.util.ArrayList" %>
<%@page import="beans.titleBean" %>
<jsp:useBean id="title" type="ArrayList<beans.titleBean>" scope="request" />
<!DOCTYPE html PUBLIC "-//W3C<%@page import="java.util.ArrayList" %>//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link rel="stylesheet" type="text/css" href="css/global.css" />
        <title>Title</title>
    </head>
    <body>
        <div id="box">
            <form action="action" method="post">
            <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Title</th>
                    <th class="action">&nbsp;</th>
                    <th class="action">&nbsp;</th>
                </tr>
            </thead>
            <tr>
                <td class="title">
                    <% for(int i=0; i < title.size(); i++) {
                        titleBean t = new titleBean();
                        t = (titleBean) title.get(i);
                    %>
                    <input type="text" name="id" value="<%= t.getID() %>" />
                </td>
                <td class="title"><%= t.getTitle() %></td>
                <td><input type="submit" name="actionCommand" value="Edit" /></td>
                <td><input type="submit" name="actionCommand" value="Delete" /></td>
            </tr>
            <tr>
                <td class="title"><% } %></td>
                <td>&nbsp;</td>
                <td>&nbsp;</td>
                <td>&nbsp;</td>
            </tr>
        </table>
        </form>
        </div>
    </body>
</html>

dataManager.java

public void delete(String id) {
        Connection conn = getConnection();
        if(conn != null) {
            PreparedStatement pstmt = null;
            try {
                String query = "Delete dbTitle WHERE id=?";
                pstmt = conn.prepareStatement(query);
                pstmt.setString(1, id);
                int rows = pstmt.executeUpdate();
                if(rows == 1) {
                    System.out.println("Row is deleted.");
                }
                else{
                    System.out.println("Row is not deleted.");
                }
            }
            catch(SQLException sqle) {
                sqle.printStackTrace();
            }
            finally {
                try {
                    pstmt.close();
	        }
	        catch (SQLException sqle) {
                    sqle.printStackTrace();
                }
	        putConnection(conn);
	    }
	}
    }

actionServlet

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        String actionCommand = request.getParameter("actionCommand");
        String id = request.getParameter("id");

        if(actionCommand != null) {
            if(actionCommand.equals("Delete")) {
                dm.delete(id);
                RequestDispatcher dispatcher = request.getRequestDispatcher("delete.jsp");
                dispatcher.forward(request, response);
            }
            else if(actionCommand.equals("Edit")) {
                RequestDispatcher dispatcher = request.getRequestDispatcher("editTitle.jsp");
                dispatcher.forward(request, response);
            }
        }
    }

The error is in actionServlet = dm.delete(id)

If you placed system call already in servlet when you query about parameters sent to servlet you would find out that ID is actually never passed.

Each of your submit buttons should have the item ID associated with them. Use "id" parameter that is available for most html tags to give them item ID which will be passed on submit (check out standard attributes).

I still don't understand about "id" in the submit button.
If I use "name", it can be call in request.getParameter, how about "id".

Btw I create an input tag which type="hidden" and name="id" value="<%= t.getID %>". It can pass with the request.getParameter, but still got problem.

I check the url with method="get" and found http://localhost:8080/dbTitle/edit?id=1&action=Edit&id=2&id=3

It seems all value pass with the request.getParameter.

How to resolve this, do you got an example.

<input type="submit" id="<%= t.getID %>" name="actionCommand" value="Edit" />
<input type="submit" id="<%= t.getID %>" name="actionCommand" value="Delete" />

How to sent it in servlet.

If "name", I can sent it with request.getParameter, but "id" can not.

Sorry I just realised what stupid thing I posted.

Here is what you been looking for. Simple example

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
    <title></title>
  </head>
  <body>
  	<form method="POST" action="controller">
	  	<table>
	  		<tr>
	  			<td>Record 1</td>
	  			<td><input type="submit" name="123" value="Edit" /></td>
	  			<td><input type="submit" name="123" value="Delete" /></td>
	  		</tr>
	  		<tr>
	  			<td>Record 2</td>
	  			<td><input type="submit" name="234" value="Edit" /></td>
	  			<td><input type="submit" name="234" value="Delete" /></td>
	  		</tr>
	  		<tr>
	  			<td>Record 3</td>
	  			<td><input type="submit" name="345" value="Edit" /></td>
	  			<td><input type="submit" name="345" value="Delete" /></td>
	  		</tr>
	  	</table>
	  </form>  
  </body>
</html>
import java.util.Enumeration;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServlet;


public class Controller extends HttpServlet{
	
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException
	{		
		Enumeration en = request.getParameterNames();
		while(en.hasMoreElements()){
			String name = (String) en.nextElement();
			System.out.println("Retrieved name is "+name);
			
			String value = request.getParameter(name);
			System.out.println("Value is " + value);
		}
	}
}

Basically in name attribute you will pass ID of the item you want to manipulate. In your servlet because you do not know what name will pop-up you need to query for list of the names (this will be only one as you working with buttons and not radio or check boxes) that has been submitted. Once you have them loop through list get the name of attribute used and based on that query about action to be taken. The above is just crude example that need to be fine-tuned, but I hope you get idea

Sorry I just realised what stupid thing I posted.

You must be kidding, your post always great.:)

Thanks peter_budo for the simple example, I finally finish it.
You know what, I almost give up and try to use checkbox in every row, then change request.getParameter with request.getParameterValues. It was work, but heloooooo..

Anyway, back to the web.xml, GashFish v2.1 giving an error when I used this

<servlet>
        <servlet-name>addServlet</servlet-name>
        <servlet-class>servlet.AddServlet</servlet-class>
 
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>servlet.loginServlet</servlet-class>
 
        <servlet-name>registerServlet</servlet-name>
        <servlet-class>servlet.registerServlet</servlet-class>
 
<!-- ONLY ONE DECLARATION NEED IT -->
        <init-param>
            <param-name>dbURL</param-name>
            <param-value>jdbc:odbc:database</param-value>
        </init-param>
        <init-param>
            <param-name>dbUserName</param-name>
            <param-value>username</param-value>
        </init-param>
        <init-param>
            <param-name>dbPassword</param-name>
            <param-value>password</param-value>
        </init-param>
        <init-param>
            <param-name>JdbcDriver</param-name>
            <param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
        </init-param>
    </servlet>

Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'servlet-name'. One of '{"http://java.sun.com/xml/ns/javaee":init-param, "http://java.sun.com/xml/ns/javaee":load-on-startup, "http://java.sun.com/xml/ns/javaee":run-as, "http://java.sun.com/xml/ns/javaee":security-role-ref}' is expected.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:410)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3165)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1777)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:685)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2747)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
at com.sun.enterprise.deployment.io.DeploymentDescriptorFile.read(DeploymentDescriptorFile.java:298)
... 17 more

Do you have experience with this.

I had finally time to look at the above book and looks like web.xml file needs to be changed to something like this (I had no chance to test it so I have no idea if it will actually work. Also in my tutorial here is direct request for DB driver where in this case config file is using connection pool)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
	<servlet>
		<servlet-name>LoginServlet</servlet-name>
       	<servlet-class>LoginServlet</servlet-class>
       
       <init-param>
		    <param-name>dbUserName</param-name>
		    <param-value>root</param-value>
	    </init-param>
	  	<init-param>
		    <param-name>dbPassword</param-name>
		    <param-value>p14m10m</param-value>
	    </init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>LoginServlet</servlet-name>
       <url-pattern>/login</url-pattern>		
	</servlet-mapping>
	
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	
	<resource-ref>
		<!-- 
		Contains the JNDI name of the data source 
		NOT SURE IF THE NAME IS NEED IT AS IN BOOK EXAMPLE 
		IT WAS USED FOR REFERENCE CALL FROM JSP THROUGH JSTL 
		-->
		<res-ref-name>jdbc/mysqlpool</res-ref-name>
		<!--
		Contains the fully qualified name of the resource to be obtained via JNDI;
		 for data sources, this will always be javax.sql.DataSource. 
		 -->		
		<res-type>javax.sql.DataSource</res-type>
		<!-- 
		Element should have a value of Container when using the <resource-ref> 
		element to define a data source as a resource. This allows the application server 
		to use the credentials set up in the connection pool corresponding 
		to the data source to log into the database. 
		-->
		<res-auth>Container</res-auth>
	</resource-ref>
</web-app>

If this doesn't work you will need to try GlassFish forum (as I do not see point in waiting here as nobody else so far replied :( )

> According to thread MVC above, I create web.xml like this

Don't repeat your database configuration; what you need is not a servlet level initialization i.e. ServletConfig but application level initialization i.e. ServletContext.

Would be possible to get some show-case example as neither me or rizza_f grow up to the challenge yet...

The point I was trying to make is that instead of having a configuration like in this post, it'd be better to declare the initialization parameters at the web app level instead of declaring it for each and every servlet. You then configure a ServletContextListener i.e. create a class which receives a servlet context notifications like creation of a servlet context and it's destruction.

You can then use the contextInitialized() method to either create your own pooled datasource and push its reference in the application context or read in the database config parameters like database details, username and password and place them in the context. Now whenever you want a db connection you either retrieve the datasource or manually create a connection based on the database details pushed in the context. A sample:

<!-- Your deployment descriptor -->
<web-app>
  <context-param>
    <param-name>DB_URI</param-name>
    <param-value>jdbc:oracle:thin:scott/tiger@myhost:1521:mysid</param-value>
  </context-param>
  <context-param>
    <param-name>DB_USER</param-name>
    <param-value>scott</param-value>
  </context-param>
  <context-param>
    <param-name>DB_PWD</param-name>
    <param-value>tiger</param-value>
  </context-param>

  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>mypkg.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>Login.do</url-pattern>
  </servlet-mapping>

  <listener>
    <listener-class>mypkg.MyContextListener</listener-class>
  </listener>
</web-app>
package mypkg;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import java.myconnpool.library.MyDataSource;

public class MyContextListener implements ServletContextListener {

  @Override
  public void contextInitialized(ServletContextEvent event) {
      ServletContext context = event.getServletContext();

      String uri = context.getInitParameter("DB_URI");
      String user = context.getInitParameter("DB_USER");
      String user = context.getInitParameter("DB_PWD");
      
      // Create a datasource using any of the connection pooling
      // libraries out there
      MyDataSource mds =
        MyDataSource.createDataSource(uri, user, pass);
      context.setAttribute("DS", mds);
  }

  @Override
  public void contextDestroyed(ServletContextEvent event) {
    // Close the datasource using the API of the connection pool library
    // you have used
    ServletContext context = event.getServletContext();
    MyDataSource mds = (MyDataSource) ctx.getAttribute("DS");
    mds.close();
  }

}
package mypkg;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.servlet.ServletException;

import javax.sql.DataSource;

import java.io.IOException;

public class LoginServlet extends HttpServlet {

  protected void  doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
    doPost(req, res);
  }

  protected void  doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
    // Retrieve the user name and password entered by the user
    String user = request.getParameter("user");
    String pwd = request.getParameter("pwd");
    
    // Retrieve the datasource
    DataSource ds = (DataSource)getServletContext().getAttribute("DS");
    
    // Retrieve the connection from the datasource and authenticate
    // the user; fire off other queries etc. etc. This datasource object
    // can now be retrieved in any servlet/jsp without duplicating the
    // database config placed in the deployment descriptor :-)
  }

}

Of course, the possibilities are limitless as to what you can configure using the context parameters and listener classes, but yeah, that's how its normally done.

Thanx ~s.o.s~, great example!

Wow thanks, I will try it and give the report soon.

import java.myconnpool.library.MyDataSource;

I don't understand about the code, it telling me the package does not exist.

What did I miss, I already add mysql-connector library and create connection pool, when I ping it success.

I change myconnpool with the name of connection pool that I created, but still same error.

You are suppose to replace with reference to what ever connection pool you use.

So what connection you use and what steps you used to add it to your project?

I use MySQL for the database and GlassFish v2.1 for the server

I create the web.xml like ~S.O.S~ code above

<web-app>
  <context-param>
    <param-name>DB_URI</param-name>
    <param-value>[B]jdbc:mysql://localhost:3306/test[/B]</param-value>
  </context-param>
  <context-param>
    <param-name>DB_USER</param-name>
    <param-value>scott</param-value>
  </context-param>
  <context-param>
    <param-name>DB_PWD</param-name>
    <param-value>tiger</param-value>
  </context-param>
 
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>mypkg.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>Login.do</url-pattern>
  </servlet-mapping>
 
  <listener>
    <listener-class>mypkg.MyContextListener</listener-class>
  </listener>
</web-app>

Then I create the connection pool follow this link

JDBC Connection Pool Name : MySQLConnectionPool
JNDI name = jdbc/test

If you are using the connection pooling mechanism provided by the container instead of creating your own connection pool [as mentioned in my first post], you need to:
- remove the database related initialization parameters since you won't be coding the connection pool creation.
- change the code in your ServletContextListener class
- add extra configuration in the deployment descriptor i.e. the resource-ref element

Read this for more details.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.