Wednesday, April 3, 2013

Handling Session Timeout in Wicket

Define the timeout period in web.xml :
 
<session-config>

<session-timeout>60</session-timeout>

</session-config>



Create a class which extend the AjaxselfUpdatingTimerBehavior and implements IAjaxIndicatorAware :


import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;

import org.apache.wicket.ajax.IAjaxIndicatorAware;

import org.apache.wicket.util.time.Duration;

 

public class TimerBehavior extends AjaxSelfUpdatingTimerBehavior implements IAjaxIndicatorAware{

 

      public TimerBehavior(Duration updateInterval) {

            super(updateInterval);

      }


      private static final long serialVersionUID = 1L;

 

      @Override

      public String getAjaxIndicatorMarkupId() {

            return null;

      }


}
Create a panel which ill show the confirmation popup to decide whether to continue with current session or close :
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.panel.Panel;
 
public class SessionTimeOutPanel extends Panel{
      /**
       *
       */
      private static final long serialVersionUID = 1L;
     
      private boolean status;
     
      public boolean isStatus() {
            return status;
      }
 
      public void setStatus(boolean status) {
            this.status = status;
      }
     
      public SessionTimeOutPanel(String id,final ModalWindow modalWindow) {
            super(id);
            status = false;              
            AjaxLink okLink = new AjaxLink("OkButton") {
                 
                  @Override
                  public void onClick(AjaxRequestTarget target) {
                        setStatus(true);
                        modalWindow.close(target);
                  }
            };
            AjaxLink cancelLink = new AjaxLink("CancelButton") {
                 
                  @Override
                  public void onClick(AjaxRequestTarget target) {
                        setStatus(false);
                        modalWindow.close(target);
                  }
            };
            add(okLink);
           add(cancelLink);
      }
     
}
 HTML page for the above panel:
<wicket:panel>
      <span class="" style="width:99%;background: #4286c5 !important;">Session Time Out</span>
      <div class="">
            <label class="" style="width:100%">Your session is about to expire.Do you wish to continue?</label><br />
      </div><br/>
      <div id="" style="width:100%  padding:1.3em 0em;padding-top:32%
height:2.3em; ">
<a   class=""   href="#" tabindex=""
style="margin-right: 3%;margin-left:35%"  wicket:id="OkButton"> <span>Ok</span>
</a>
<a   class=""   href="#" tabindex=""
style="margin-right: 2%;" wicket:id="CancelButton"><span >Cancel</span>
</a>
      </div>
</wicket:panel>
Create a abstract web page ,all pages should implement this abstractpage:


import org.apache.wicket.Request;

import org.apache.wicket.RequestCycle;

import org.apache.wicket.ajax.AjaxRequestTarget;

import org.apache.wicket.ajax.IAjaxIndicatorAware;

import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;

import org.apache.wicket.markup.html.WebMarkupContainer;

import org.apache.wicket.markup.html.WebPage;

import org.apache.wicket.protocol.http.PageExpiredException;

import org.apache.wicket.protocol.http.WebRequest;

import org.apache.wicket.util.time.Duration;

 

public abstract class AbstractPage extends WebPage implements

IAjaxIndicatorAware {

 

     

      protected ModalWindow sessionTimeOutModalWindow;

     

      private transient HttpSession httpSession;

      private  int timeOut=0;

      private int timOutCount=0;

     

     

      public ModalWindow getSessionTimeOutModalWindow() {

            sessionTimeOutModalWindow = new ModalWindow("sessionTimeout");

        final SessionTimeOutPanel sessionTimeOutPanel = new SessionTimeOutPanel(

                  sessionTimeOutModalWindow.getContentId(),

                  sessionTimeOutModalWindow);

        sessionTimeOutPanel.setOutputMarkupId(true);

        sessionTimeOutModalWindow.setContent(sessionTimeOutPanel);

        sessionTimeOutModalWindow.setInitialHeight(135);

        sessionTimeOutModalWindow.setInitialWidth(400);

        sessionTimeOutModalWindow.setResizable(false);

       

        sessionTimeOutModalWindow.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {                        

            public void onClose(AjaxRequestTarget target) { 

          

          if (sessionTimeOutPanel.isStatus()) {

              if(httpSession!=null){

              httpSession.setMaxInactiveInterval(timeOut);

              timOutCount=timeOut;

              }else{

                   throw new PageExpiredException("PageExpiredException");

                    }

             

          }

          else

          {

            target.prependJavascript("window.opener='X';window.open('','_parent','');" +

                        "window.close();");

          }

            }});

                 

        Request request = RequestCycle.get().getRequest();

        if( request instanceof WebRequest )

        {

            WebRequest wr = (WebRequest)request;

            httpSession = wr.getHttpServletRequest().getSession();

            if( httpSession != null ) {

                timeOut=httpSession.getMaxInactiveInterval();

            }

        }

 

 

        return sessionTimeOutModalWindow;

    }

     

     

     

      /**

       * constructor

       */

      public AbstractPage() {

 

          add(getSessionTimeOutModalWindow());

          final WebMarkupContainer timer=new WebMarkupContainer("timer");

        timer.setOutputMarkupPlaceholderTag(true);

        timer.add(new TimerBehavior(Duration.ONE_SECOND){

 

                /**

                   *

                   */

                  private static final long serialVersionUID = 1L;

 

                        @Override

                protected void onPostProcessTarget(AjaxRequestTarget target) {

                    timOutCount--;

                 

                    if(timOutCount==60){

                      sessionTimeOutModalWindow.show(target);

                     // target.addComponent(sessionTimeOutModalWindow);

                    }

                }

         

        });

 

      add(timer);

 

      }

@Override

    public String getAjaxIndicatorMarkupId() {

            timOutCount=timeOut;

           

            return null;

    }

In Html Page add the below lines :

<div wicket:id="sessionTimeout"></div>


<div wicket:id="timer"></div>

 
 
 

Monday, April 1, 2013

Database Connection Pooling


Database Connection Pooling

 

·        Opening a connection to a database in a time consuming process . For smaller queries execution, it takes more time to open connection than executing queries.

·        Suppose if system takes 3seconds to establish a database connection, Since, for each query it tries to open the connection, to execute the 10 queries, it spends 300 seconds to open the connection.

·        Every time client sends the request, the connection has been opened which is more time consuming process. It will affect the application performance. So, Instead of opening a database connection each time to execute the queries, we could pre-allocating database connections and reuse it.

 

 Solution :

 

   We could create pool of connections in advance, So we could avoid the overhead of when the client made requests on database.

 

Create the pool of connection in advance :




When jsp/servlet request for connection , get the unused connection from the pool.


Connection is used by new jsp/servlet :

When finished jsp/servlete returns the connection back to the pool, now the connection is available for use :




















       The connection pool class can able to perform the following tasks .

                1. Preallocate the connections.

                2. Manage available connections

                3. Allocate new connections

                4. Wait for a connection to become available

                5. Close the connections

 

 

 

  • I have used two collection vectors to store available idle connection(availableConnection) and unavailable busy connections(busyConnection).
  • The constructor of the class gets the url, username and password etc as input and create the connection pool. The connection pool objects are store in vector collection named availableConnection.
  • When the user request for connection, the function getConnection() initially checks whether the available connection is free or not. If it is free ,it will remove the connection from availableConnection vector and add it to the busyConnection vector. Now the connection is in use.
  • If the connection is not free and the totalConnection has not reached maxConnection limit then it will make the new connection for the user.
  • When the connection is required but there is no free connections and the totalConnection reached the maxConnection limit then we should wait(call wait() method) until the connection has been released and notify or notifyAll is called.
  • Connections are closed when they are garbage collected but sometimes we need to  close it explicitly.

 

ConnectionPool.java

 

import java.sql.*;

import java.util.*;

 

public class ConnectionPool implements Runnable {

 

private String driver, url, username, password;

private int maxConnections;

private boolean waitIfBusy;

private Vector availableConnections, busyConnections;

private boolean connectionPending = false;

 

public ConnectionPool(String driver, String url,String username, String password,int initialConnections,

int maxConnections,boolean waitIfBusy)throws SQLException {

 

this.driver = driver;

this.url = url;

this.username = username;

this.password = password;

this.maxConnections = maxConnections;

this.waitIfBusy = waitIfBusy;

if (initialConnections > maxConnections) {

initialConnections = maxConnections;

}

 

//pre-allocate the connections

availableConnections = new Vector(initialConnections);

busyConnections = new Vector();

for(int i=0; i<initialConnections; i++) {

availableConnections.addElement(makeNewConnection());

}

}

 

//manage the available connections

public synchronized Connection getConnection() throws SQLException {

 

if (!availableConnections.isEmpty()) {

Connection existingConnection =(Connection)availableConnections.lastElement();

int lastIndex = availableConnections.size() - 1;

availableConnections.removeElementAt(lastIndex);

if (existingConnection.isClosed()) {

notifyAll();

return(getConnection());

} else {

busyConnections.addElement(existingConnection);

return(existingConnection);

}

} else {

//allocate new connections

if ((totalConnections() < maxConnections) &&!connectionPending) {

makeBackgroundConnection();

} else if (!waitIfBusy) {

throw new SQLException("Connection limit reached");

}

//wait for a connection to become available

try {

wait();

} catch(InterruptedException ie) {}

return(getConnection());

}

}

 

 

private void makeBackgroundConnection() {

 

connectionPending = true;

try {

Thread connectThread = new Thread(this);

connectThread.start();

} catch(OutOfMemoryError oome) {

System.out.println(“Exception :”+oome);

 

}

}

 

public void run() {

 

try {

Connection connection = makeNewConnection();

synchronized(this) {

availableConnections.addElement(connection);

connectionPending = false;

notifyAll();

}

} catch(Exception e) {

}

}

 

private Connection makeNewConnection() throws SQLException {

 

try {

Class.forName(driver);

Connection connection =

DriverManager.getConnection(url, username, password);

return(connection);

} catch(ClassNotFoundException cnfe) {

throw new SQLException("Can’t find class for driver: " +driver);

}

}

 

 

public synchronized void free(Connection connection) {

 

busyConnections.removeElement(connection);

availableConnections.addElement(connection);

 

// Wake up threads that are waiting for a connection

 

notifyAll();

}

 

public synchronized int totalConnections() {

 

return(availableConnections.size() +

busyConnections.size());

}

 

 

//close the connections

public synchronized void closeAllConnections() {

 

closeConnections(availableConnections);

availableConnections = new Vector();

closeConnections(busyConnections);

busyConnections = new Vector();

}

 

private void closeConnections(Vector connections) {

 

try {

for(int connectionCount=0; connectionCount <connections.size();connectionCount ++) {

Connection connection =

(Connection)connections.elementAt(connectionCount);

if (!connection.isClosed()) {

connection.close();

}

}

} catch(SQLException sqle) {

System.out.println(“Exception :”+sqle);

}

}

 

public synchronized String toString() {

String info =

"ConnectionPool(" + url + "," + username + ")" +

", available=" + availableConnections.size() +

", busy=" + busyConnections.size() +

", max=" + maxConnections;

return(info);

}

}

Sunday, March 24, 2013

Can we have multiple struts config file in struts?

Hi..,

  I have little knowledge about the struts. One of the main component of struts is struts-config.xml file which contains all the routing and configuration information for the struts application.

 I have aware about how to use the struts config just like all other java developers put all the struts related stuff(action,form,message resource etc.) into a single struts config file.

 One of my friend asked me once ,can we use multiple struts config file?? I never thought about this. Actually i do not know the answer but I said "yeah,i think we can use it. but i never used it". Then i got to know from the google.

Yes, We can have mulitple configuration file in one application. we can use it the following way.

 <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>
        org.apache.struts.action.ActionServlet
    </servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>
         /WEB-INF/struts-config-1.xml, /WEB-INF/struts-config-2.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>