Java Connection Pooling - Domino - Websphere

I have developed a web application using the Lotus Notes/Domino Tag library (lotus.domino.taglib domtags.jar), I know need to implement connection pooling. My environment is Websphere as the application and web server and Domino as the database on a separate server. I am not using JDBC for connectivity but the domino tags DB, View, Form etc. to connect to the database.

Can you please tell me how to implement connection pooling for the Domino server. The following sample code has been suggested by the Lotus folks:

import java.io.IOException;

import javax.servlet.Servlet;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import lotus.domino.NotesFactory;

import lotus.domino.Session;

public class ConnPool3 extends HttpServlet implements Servlet

{ 

Session s = null;

static org.omg.CORBA.ORB orb = null;

static int count = 0;

static Object sem = new Object();

public void doGet(HttpServletRequest request,

HttpServletResponse response) throws IOException

{

try

{

synchronized (sem)

{

if ((orb == null) || ((count++ % 10) == 0))

orb = NotesFactory.createORB();

}

s = NotesFactory.createSession(“dominotest:63148”, orb, request);

//s = NotesFactory.createSession(“dominotest:63148”, uname, upassword);

String name = s.getUserName();

String p = s.getPlatform();

s.recycle();

response.setContentType(“text/html”);

ServletOutputStream out = response.getOutputStream();

out.println(“Information from servlet:
”);

out.println("
Name = " + name);

out.println("
Count = " + count);

out.println("Platform = " + p);

}

catch (Exception e)

{

e.printStackTrace();

}

}

}

All help and suggestions will be highly appreciated.

Thank you!

Bharat V Patel

Cincinnat, Ohio

Subject: Java Connection Pooling - Domino - Websphere

You don’t provide any details about your Domino Custom JSP Tag library (DCT) web application, so I wonder what problem you want to solve, and what your criteria for success might be?

Some things you should know before starting: Domino sessions contain user-specific data, so your connection pool needs to be more than an lru cache. The Domino session provides the server-side context for all the other objects - databases, views, documents - which all happily exist in a hierarchical relationship. A Domino session can become invalid at the server end when the Domino diiop task times it out. At the client end is your pool, and it will have to deal - by asking the session if its valid, and re-creating it when needed.

You could extend your connection pool so it keeps other objects too - database, view, and document objects - but then you must honor the Domino object hierarchy - always deliver the view that is correct given the user’s Domino session and open Domino database. If an ancestor object were to go away, say due to a session timeout, so must all of its descendants.

At Lotusphere 2004 I learned there were folks who wanted to do all that and use JSPs and the DCT library to just do the ‘view’ part of their MVC apps, so in the 6.0.4/6.5.3 releases you will find a new attribute named ‘dojkey’ in the session, db, view, and document tags. doj = Domino Object for Java, and the dojkey specifies the name of an attribute in the request object, or, because you are doing a chain of jsp:includes, in the session object, where the DCT will find the DOJ object it should use.

When the dojkey is supplied, but there is no object in either the request or session objects, the DCT will create one and add it as an attribute of the request object. That’s the only helpful thing the DCT will do when the dojkey attribute is present - it will not validate the object it gets, it will not do cleanup, it will report errors but will not try recover from them (if the session has been timed out at the server, the DCT will normally reconnect - but the tag will likely not contain login info now.)

Hope that helps!

-sl

Subject: RE: Java Connection Pooling - Domino - Websphere

Steve,

Your note have been very helpful, thank you!

My application is totally based on using JSP’s with no beans, but direct connections to the Notes/Domino DB using the "domino:db tag. The entire application does work, but my concern is that once the system is live on the Internet, heavy database I/O will degrade performance, hence the need to implement connection pooling.

Herewith is a sample of one of my JSP’s:

<%@ page import=“java.util., java.text., lotus.domino.*” %>

Haulpass Home - WTG - Bid System

<%@taglib uri=“/WEB-INF/domtags.tld” prefix=“domino”%>

<%@taglib uri=“/WEB-INF/domutil.tld” prefix=“domutil”%>

<%-- --%>

domino:session id=“mses” host=“<%= uhost %>” user=“<%= uname %>” password=“<%= upassword %>”>

<%

    // Store the username and password into session context

    session.setAttribute("uhost", uhost);

    session.setAttribute("uname", uname);

    session.setAttribute("upassword", upassword);



    boolean oddRow = true; 

    boolean rowPrep = false;

    boolean dueDateEmpty = false;

    int dateComp = 0;       

    String vname = "(LUByNumber)";

	String fname = "BID.jsp";

	String dbname = "xxxxxxxxxx\\IENCustom.nsf";

	String ftsearch = null;

	String s_status = " ";

	String s_bfrdate = null;

	String s_btodate = null;

	String s_dfrdate = null;

	String s_dtodate = null;

	

	String wrkFld = null;

	Date brDate = new Date();

	String brStrDate = null;

	Date dueDate = new Date();

	String dueStrDate = null;

	String bidNumber = null;

	String bidName = null;

	String bidHeaderID = "ABC";

	Date todaysDate = new Date();

	String todaysStrDate = null;

		

	GregorianCalendar cal = new GregorianCalendar();

	SimpleDateFormat  fmt = new SimpleDateFormat("MM-dd-yyyy" );

            Date todaysDatePlus = new Date();

            cal.add(Calendar.DATE, 14);

	todaysDatePlus = cal.getTime();

	fmt.setLenient(false);

  

    					

	session.setAttribute("View", vname);

	session.setAttribute("Form", fname);

	session.setAttribute("db", dbname);

	session.setAttribute("BidNum", bidHeaderID);

	session.setAttribute("s_status", s_status);

	session.setAttribute("s_bfrdate", s_bfrdate);

	session.setAttribute("s_btodate", s_btodate);

	session.setAttribute("s_dfrdate", s_dfrdate);

	session.setAttribute("s_dtodate", s_dtodate);

%>

<domino:preserve name=“View”/>

<domino:preserve name=“Form”/>

<domino:preserve name=“db”/>

<domino:preserve name=“BidNum”/>

    <TR>

      <TD>

        <TABLE cellSpacing=0 cellPadding=0  border=0 >

          <TBODY>

          

            <TD vAlign=bottom><FONT size=3><B>Bid Invitation</B></FONT></TD>

            <TD vAlign=bottom align=right>&nbsp;</TD></TR>

         

          <TR>

            <TD>&nbsp;</TD></TR></TBODY></TABLE></TD></TR>

    

    



<domino:db  id="mdb" dbserver="<%= mses.getServerName() %>" dbname="<%= dbname %>">

<domino:preserve name=“View”/>

<domino:preserve name=“Form”/>

<domino:preserve name=“db”/>

<domino:preserve name=“search”/>

	<domino:view viewname="<%= vname %>" id="theView" ftsearch="<%=ftsearch%>">

		<domino:ifserverevent event="OnAction" for="DeleteSelected">

			<domino:selectedloop>

				<% document.remove(true); %>

			</domino:selectedloop> 

		</domino:ifserverevent>





		<domino:page id="pageInfo" name="pageInfo" rows="99">



			<TABLE width="700" bgColor=#c0c0c0 border=2>

          <TBODY>

          <TR>

            <TD width="100%" bgColor=#ffffff>

              <TABLE width="100%" border="1"> 

                <TBODY>

                <TR bgColor=#D2E4FC>

                <TD><b>Bid Number</Td>

                <TD><b>Bid Name</Td>

                <TD><b>Broadcast Date</Td>

                <TD><b>Due Date (EST)</Td>

                <TD><b>Action</Td></TR>

             <domino:viewloop id="viewEntry">

			

			

			 

			<% brStrDate = "";

			   brDate = new Date();

			   dueStrDate = "";

			   dueDate = new Date();

			   dueDateEmpty = false; %>

			  

				<domino:ifdocumententry>

					

					

					

					<%

					for(int colCount = 1 ; colCount <= theView.getColumnCount() ; colCount++)

					{ 

						lotus.domino.ViewColumn vc = theView.getColumn(colCount);

						

								

						

						



							if(vc.isIcon())

							{

								// Display View icon

								String iconfile = getIconFile(viewEntry, colCount);

								

							}

							else

							{

								%> 

									 										

										 

										 <domino:viewitem id="fld" col="<%=colCount%>" format="<%= getFormat(vc, viewEntry, colCount) %>"/>

										<%  wrkFld = fld.toString();

										    

										    if (colCount == 1) {

										       bidNumber = wrkFld;}  

										    if (colCount == 2) {

										       bidName = wrkFld; }   

										    if (colCount == 3 && wrkFld.length() > 0) {

										       SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");

										       f.setLenient(false);

										       brStrDate = wrkFld;

										       brDate = f.parse(wrkFld); }

										    if (colCount == 4 && (wrkFld.length() <= 1)) {

										       dueDateEmpty = true; }  %> 

										    

										    <% if (colCount == 4 && wrkFld.length() > 0) {

										       SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");

										       f.setLenient(false);

										       dueStrDate = wrkFld;

										       dueDate = f.parse(wrkFld); } %> 

										  

										 							       

										     

										   <%   if (false) { %>

										     <domino:viewitem  col="<%=colCount%>" format="<%= getFormat(vc, viewEntry, colCount) %>"/> 

										  <% } %>

										       						 

									</td>

									

								<%

							} // End of if icon

						

					} // End of for loop

					%>

					<%  if ((dueDate.after(todaysDate)) && (dueDate.after(todaysDatePlus))) { %>

					<% if (oddRow) {  oddRow = false; %>

			        <TR class="oddRow"> <% }

			        else { oddRow = true; %>

			        <TR class="evenRow"> <% } %>

					<td class="editbutton"><%=bidNumber%></td>

					<td class="editbutton"><%=bidName%></td>

					<td class="editbutton"><%=brStrDate%></td>

					<td class="editbutton"><%=dueStrDate%></td>

					<td class="editbutton">

					    <domino:formlink href="<%= fname %>" >

							Download Documents/Bid Package

						</domino:formlink>

					</td>

					</tr>

					<% } %>  

				  </domino:ifdocumententry>  

				  <domino:ifcategoryentry>  

					<td>

					</td>

					<td>

					</td>

					<td>

					</td>

					

				  </domino:ifcategoryentry>  

			</tr>

			

			</domino:viewloop>

			</table>

		</domino:page>

		<domino:novalues>

			<tr><td>No documents found.</td></tr>

		</domino:novalues>

		</domino:view>

</domino:db>



                  

                </TBODY></TABLE></TD></TR></TBODY></TABLE>

                

                </TD></TR></TBODY></TABLE>
    <TR>

      <TD>

        <TABLE cellSpacing=0 cellPadding=0  border=0 align="left">

          <TBODY>

            <TR><TD>&nbsp;</TD></TR>

            <TD vAlign=bottom><FONT size=-1>&nbsp;&nbsp;You can view a complete list of your bids on the <A HREF="BidManagement.jsp?View=(LubyNumber)&Form=BID.jsp&db=xxxxxxxxxx\\IENCustom.nsf" title="Bid Management">Bid Management</A> 

        page.</FONT></TD>

            <TD vAlign=bottom align=right>&nbsp;</TD></TR>

            <TR><TD>&nbsp;</TD></TR>

            <TR><TD>&nbsp;</TD></TR>

            <TD vAlign=bottom><FONT size=3><B>Bids Due within 14 days</B></FONT></TD>

            <TD vAlign=bottom align=right>&nbsp;</TD></TR>

         <TR><TD>&nbsp;</TD></TR>

         

          <TR>

            <TD>&nbsp;</TD></TR></TBODY></TABLE></TD></TR>

    

    <TR>

      

      <TD width="100%">

        

      



<domino:db  id="mdb2" dbserver="<%= mses.getServerName() %>" dbname="<%= dbname %>">

	



	<domino:view viewname="<%= vname %>" id="theView2" enableselect="true" ftsearch="<%=ftsearch%>">

		<domino:ifserverevent event="OnAction" for="DeleteSelected">

			<domino:selectedloop>

				<% document.remove(true); %>

			</domino:selectedloop> 

		</domino:ifserverevent>

<domino:preserve name=“View”/>

<domino:preserve name=“Form”/>

<domino:preserve name=“db”/>

<domino:preserve name=“search”/>

		<domino:page id="pageInfo2" name="pageInfo2" rows="99">



			<TABLE width="700" bgColor=#c0c0c0 border=2>

          <TBODY>

          <TR>

            <TD width="100%" bgColor=#ffffff>

              <TABLE width="100%" border="1">

                <TBODY>

                <TR bgColor=#D2E4FC>

                <TD><b>Bid Number</Td>

                <TD><b>Bid Name</Td>

                <TD><b>Broadcast Date</Td>

                <TD><b>Due Date (EST)</Td>

                <TD><b>Action</Td></TR>

                

			<domino:viewloop id="viewEntry2">

			 

			<% brStrDate = "";

			   brDate = new Date();

			   dueStrDate = "";

			   dueDate = new Date();

			   dueDateEmpty = false; %>

			 

				  <domino:ifdocumententry>  

					

					

					

					<%

					for(int colCount2 = 1 ; colCount2 <= theView2.getColumnCount() ; colCount2++)

					{ 

						lotus.domino.ViewColumn vc2 = theView2.getColumn(colCount2);

						

						

						

						

						



							if(vc2.isIcon())

							{

								// Display View icon

								String iconfile2 = getIconFile(viewEntry2, colCount2);

								%>

									<td class="docentry2" width="15">

										<%if(iconfile2 != null) {%>

											<img src="<%=iconfile2%>" alt="<%=iconfile2%>" border=0 height=13 width=14>

										<%}%>	

									</td>

								<%

							}

							else

							{

								%>

									<td class="docentry2">

										<domino:indent>&nbsp;&nbsp;&nbsp;&nbsp;</domino:indent>

										

										 

										 <domino:viewitem id="fld2" col="<%=colCount2%>" format="<%= getFormat(vc2, viewEntry2, colCount2) %>"/>

										<%  wrkFld = fld2.toString();

										    

										    if (colCount2 == 1) {

										       bidNumber = wrkFld; }  

										    if (colCount2 == 2) {

										       bidName = wrkFld; }   

										    if (colCount2 == 3 && wrkFld.length() > 0) {

										       SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");

										       f.setLenient(false);

										       brStrDate = wrkFld;

										       brDate = f.parse(wrkFld); }

										    if (colCount2 == 4 && (wrkFld.length() <= 1)) {

										       dueDateEmpty = true; }  %> 

										    

										    <% if (colCount2 == 4 && wrkFld.length() > 0) {

										       SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");

										       f.setLenient(false);

										       dueStrDate = wrkFld;

										       dueDate = f.parse(wrkFld);

										       f.setLenient(false);

										       todaysStrDate = f.format(todaysDate); } %> 

										  

										 							       

										     

										   <%   if (false) { %>

										     <domino:viewitem  col="<%=colCount2%>" format="<%= getFormat(vc2, viewEntry2, colCount2) %>"/> 

										  <% } %>

										       						 

									</td>

									

								<%

							} // End of if icon

						

					} // End of for loop

					%>

					<%--  if ((dueDate.after(todaysDate)) && (dueDate.before(todaysDatePlus))) {  --%>

					<%  if (((dueStrDate.equals(todaysStrDate)) || (dueDate.after(todaysDate))) && (dueDate.before(todaysDatePlus))) {    

					if (oddRow) {  oddRow = false; %>

			        <TR class="oddRow"> <% }

			        else { oddRow = true; %>

			        <TR class="evenRow"> <% } %>

					<td class="editbutton"><%=bidNumber%></td>

					<td class="editbutton"><%=bidName%></td>

					<td class="editbutton"><%=brStrDate%></td>

					<td class="editbutton"><%=dueStrDate%></td>

					<td class="editbutton">

						<domino:formlink href="<%= fname %>">

							Download Documents/Bid Package

						</domino:formlink>

						 

					</td>

					<% } %>  

				  </domino:ifdocumententry>  

				  <domino:ifcategoryentry>  

					<td>

					</td>

					<td>

					</td>

					<td>

					</td>

					

				  </domino:ifcategoryentry>  

			</tr>

			

			</domino:viewloop>

			</table>

		</domino:page>

		<domino:novalues>

			<tr><td>No documents found.</td></tr>

		</domino:novalues>

	</domino:view>

</domino:db> 

</domino:session>

 

Subject: RE: Java Connection Pooling - Domino - Websphere

Since your application is totally based on JSPs, another option you might consider is the domino:session tag’s ‘duration’ attribute. If set to ‘session’, the DCT will keep your Domino iiop session open for the duration of the HttpSession. It also assumes that the diiop task will have a smallish timeout value, so before using a Domino session object it checks to see if it’s valid, and will re-create the session when needed.

A smallish timeout will help the Domino server, since client side object caching locks down a lot of server resources over a very long time (best case - the length of the HttpSession between the webserver and browser, worst case - that plus the length of the diiop timeout value if the connection pool does not correctly terminate each Domino session. Default diiop timeout is 60 minutes.).

The duration attribute also supports values of ‘request’, which will create a Domino session on each HttpRequest, and ‘page’, which will create a Domino session in each jsp. The default when the duration attribute is not supplied is ‘page’, for compatiblity with older versions.

Local Domino sessions must be terminated by the thread that creates them, so the domino:session tag automatically downgrades a duration=‘session’ to a duration=‘request’ when using a local session.

I tend to use a form that posts to this jsp:

<%@ page language="java"contentType=“text/html; charset=UTF-8” isErrorPage=“false”

import="java.util.*, java.lang.*, lotus.domino.*, simple.domino.project.*" %>

<%@ taglib uri=“/WEB-INF/domtags.tld” prefix=“domino” %>

Login validation

<%

// Pick up the data supplied in the login page

String hostname = request.getParameter(“Host”);

String username = request.getParameter(“Name”);

String password = request.getParameter(“Password”);

String dbname = request.getParameter(“dbname”);

// If the user wants an anonymous connection, set the fields accordingly

if (username != null && username.equals(“Anonymous”)) {

  username = null;

  password = null;

}

%>

<domino:session  host="<%= hostname %>" user="<%= username %>" password="<%= password %>"  duration="session" >

<%

	// Store the supplied data in the session context   

	session.setAttribute("hostName", hostname);

	session.setAttribute("userName", username);

	session.setAttribute("password", password);

	session.setAttribute("loggedIn", "Yes");

	session.setAttribute("dbName", dbname);

%>

	<jsp:include page="application-start.jsp" flush="true" />



</domino:session>

This is the only jsp that uses the domino:session tag.

The session tag works real hard to supply defaults if you dont provide them - domino:session is valid - it creates a local session for the anonymous user.

If the jsp:include’d page were to use its own domino:session tag, the values of the arguments would have to match exactly in order to find the session opened by the calling jsp. As the web app gets changed over time, having to hunt down all the domino:session tags and keep them in sync is error prone.

If you copy one of the jsps to another web app, you can still get different types of Domino sessions because the domino:session tag uses preset and default values supplied in web.xml. So having just on instance of it makes it much easier, I find.

Hope that helps!

-sl