Adding multiple parameters in the request using displaytag

I was struggled a lot and facing difficulties to add multiple parameters in the request while the displaytag option. Finally, able to find some useful links about it after a long struggle. Hence, decided to write a blog with all the possibilities together in detailed with samples.

In this blog, we have used mysql database to store and retrieve the data in the application.  Database Table structure is as follows:

Employee:

Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
FirstName VARCHAR(20)
MiddleName  VARCHAR(20)
LastName VARCHAR(20)
Adress VARCHAR(50)
City VARCHAR(30)

Upon a successful creation of a table with the above structure, inserted some sample values into the database.

Upon a successful access of this table from the application tier, saved the data into List as follows:

while(rs.next()) {
   if(list == null) {
      list = new ArrayList<EmployeesResultBean>();
   }
   list.add(new EmployeesResultBean(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),rs.getString(5),rs.getString(6)));
}
request.setAttribute( "result", list );

EmployeesResultBean class is as follows:

public class EmployeesResultBean{
int id;
String firstName, lastName, middleName, address, city;

/**
* @return the id
*/
   public int getId() {
      return id;
   }

/**
* @param id the id to set
*/
   public void setId(int id) {
      this.id = id;
   }

/**
* @return the firstName
*/
   public String getFirstName() {
      return firstName;
   }

/**
* @param firstName the firstName to set
*/
   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }

/**
* @return the lastName
*/
   public String getLastName() {
      return lastName;
   }

/**
* @param lastName the lastName to set
*/
   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

/**
* @return the middleName
*/
   public String getMiddleName() {
      return middleName;
   }

/**
* @param middleName the middleName to set
*/
   public void setMiddleName(String middleName) {
      this.middleName = middleName;
   }

/**
* @return the address
*/
   public String getAddress() {
      return address;
   }

/**
* @param address the address to set
*/
   public void setAddress(String address) {
      this.address = address;
   }

/**
* @return the city
*/
   public String getCity() {
      return city;
   }

/**
* @param city the city to set
*/
   public void setCity(String city) {
      this.city = city;
   }

/**
* @param id
* @param firstName
* @param lastNamae
* @param middleName
* @param address
* @param city
*/
   public EmployeesBean(int id, String firstName, String lastName,String middleName, String address, String city) {
      super();
      this.id = id;
      this.firstName = firstName;
      this.lastName = lastName;
      this.middleName = middleName;
      this.address = address;
      this.city = city;
   }
}

Now, the result has been stored in the list and placed in the  request attribute to access further.

Following are the various options to display the result using displaytag options:
Basic table:

<display:table name="result" />

Basic, columns:


<display:table name="result">
<display:column property="id" title="ID" />
<display:column property="firstName" title="First Name"/>
<display:column property="middleName" title="Middle Name"/>
<display:column property="lastName"  title="Last Name"/>
<display:column property="address" title="Address"/>
<display:column property="city" title="City"/>
</display:table>

Sending the value as a parameter:

<display:table name="result">
<display:column property="id" title="ID" href="nextpage.jsp" paramId="id" paramProperty="id"/>
<display:column property="firstName" title="First Name"/>
<display:column property="middleName" title="Middle Name"/>
<display:column property="lastName"  title="Last Name"/>
<display:column property="address" title="Address"/>
<display:column property="city" title="City"/>
</display:table>

The hyperlink will point to ‘http://<$IP>:<$PORT>/<$CONTEXT>/nextpage.jsp?id=<$ID>’

Sending multiple parameters for another page:

To implement this, we need to use a decorator that can be used to create dynamic links on the fly so that you can either click on a particular column value and “drill down” for more information, or you can create a column of text labels which are hyperlinks that perform some action on the object in that row. These dynamic links can be created based on some primary key of the object, or they can make use of the object List index.

<display:table name="result" pagesize="15" decorator="com.samples.LinkDecorator">
<display:column property="link" title="ID" />
<display:column property="firstName" title="First Name"/>
<display:column property="middleName" title="Middle Name"/>
<display:column property="lastName"  title="Last Name"/>
<display:column property="address" title="Address"/>
<display:column property="city" title="City"/>
</display:table>

If we have observed clearly, we have used the property called ‘link’ and the decorator class ‘com.samples.LinkDecorator’. So, the decorator class appears as follows:

package com.samples;
import org.displaytag.decorator.TableDecorator;

/**
* @author vinod@pramati.com
* Sep 11, 2011
*/
public class LinkDecorator extends TableDecorator {
   public String getLink(){
      EmployeesBean empData = (EmployeesBean) getCurrentRowObject();
      String link = "<a href=\"nextpage.jsp?id=" + empData.getId() + "&amp;amp;amp;amp;amp;amp;amp;amp;amp;fname="+ empData.getFirstName()+"\">" + empData.getId() +"</a>";
      return link;
   }
}

The hyperlink(ID) will point to ‘http://<$IP>:<$PORT>/<$CONTEXT>/nextpage.jsp?id=<$ID>&fname=<$FirstName>’

Display using the group of details:

In this scenario, assume need to display the data based on city and first name. For this, the display tag appears as:

<display:table name="result">
<display:column property="id" title="ID" href="nextpage.jsp" paramId="id" paramProperty="id"/>
<display:column property="firstName" title="First Name" group="2"/>
<display:column property="middleName" title="Middle Name"/>
<display:column property="lastName"  title="Last Name"/>
<display:column property="address" title="Address"/>
<display:column property="city" title="City" group="1"/>
</display:table>

Specified VM Args like Xmx in the java command multiple times

One day during the discussion with our colleagues received the following query:

Q:

If we specify -Xms and -Xmx values twice/more in the java command, which one will reflect?

We thought for some time and come out with different answers for the same. Hence, decided to test in detailed for the proper answer. Hence, started the testing as follows:

1. java -Xms256m -Xmx256m -XX:PermSize=128m -XX:MaxPermSize=256m -Xms256m -Xmx256m Test

Fortunatly, we are using JDK 1.6 which contains jconsole utility to identify the memory utilization details. We see the following:

Maximum heap size: 253,440 kbytes

2. java -Xms256m -Xmx256m -XX:PermSize=128m -XX:MaxPermSize=256m -Xms256m -Xmx512m Test

Maximum heap size: 506,816 kbytes

3. java -Xms256m -Xmx256m -XX:PermSize=128m -XX:MaxPermSize=256m -Xms256m -Xmx1024m Test

Maximum heap size: 1,013,632 kbytes

4. java -Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=256m -Xms256m -Xmx256m Test

Maximum heap size: 253,440 kbytes

5. java -Xms256m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -Xms256m -Xmx256m Test

Maximum heap size: 253,440 kbytes

6. java -Xms256m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -Xms512m -Xmx512m -Xms256m -Xmx256m Test

Maximum heap size: 253,440 kbytes

From the above experiment, it confirms that the Xms and Xmx values are reflected which comes in the last position of command. From this, it appears that the values are pushed in to the stack and pop the values using LIFO method.

Customize MySQL data directory from default location to user defined location

MySQL is a widely used open source database. Generally, the data stored in the database is very huge. Depends on the information stored in the database, most of the times user faces an issue with the space allocated for the default partition. In the scenario of running out of space, need to move the data directory from default location to user specific location. This is a short little guide to show you how to move mysql to another partition on the system.

1. Collect complete backup of current database using

mysqldump -u root -p --all-databases > <$TEMP-DIR>/mysqldump.sql

2. Now, stop mysql service using '/etc/init.d/mysqld stop'.
3. By default, MySQL data directory is /var/lib/mysql. Hence, copy MySQL directory to custom location using 'cp -R /var/lib/mysql <$CUSTOM-DIR>'
4. Modify the owner to mysql using 'chown -R mysql:mysql <$CUSTOM-DIR>/mysql'(Installed directory owner should equal to the user specified in the my.cnf file. By default 'mysql' is the user specified in the file).
5. Remove ibdata1,ib_logfile0 and ib_logfile1 if exist under '<$CUSTOM-DIR>/mysql' directory.
6. Now, edit '/etc/my.cnf' file and modify the datadir value to custom directory as 'datadir = <$CUSTOM-DIR>/mysql'.

Sample my.cnf file for reference:


[mysqld]
#datadir=/var/lib/mysql
datadir=<$CUSTOM-DIR>/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Default to using old password format for compatibility with mysql 3.x
# clients (those using the mysqlclient10 compatibility package).
old_passwords=1


[mysqld_safe]
log-error=<$CUSTOM-DIR>/mysql/logs/startmysql.log
pid-file=/var/run/mysqld/mysqld.pid

7. Start mysql service using ‘/etc/init.d/mysqld start‘.

Known issues:

1.

110215 11:30:11 [ERROR] /usr/libexec/mysqld: Can't find file: './mysql/host.frm' (errno: 13)
110215 11:30:11 [ERROR] /usr/libexec/mysqld: Can't find file: './mysql/host.frm' (errno: 13)
110215 11:30:11 [ERROR] Fatal error: Can't open and lock privilege tables: Can't find file: './mysql/host.frm' (errno: 13)

Sol:

Check the permissions for configured directory. Owner for this directory should be a mysql instead of root.

2.

# /etc/init.d/mysqld start
Timeout error occurred trying to start MySQL Daemon.
Starting MySQL: [FAILED]


During the access of Database :

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

Sol:

If no exceptions are reported in the log file at this point of time, cross check the mysql.sock path in /etc/my.cnf file. It should point to /var/lib/mysql/mysql.sock. Should not modify this path and also verify the existance of mysql directory in the specified location.

Memory Leak with Oracle 10g JDBC drivers

When Application server’s prepared statement cache is enabled with Oracle 10g JDBC driver, few of our customers reported high memory usage as well as memory leaks in some cases. We have observed that the prepared statements returned back to server cache still hold onto the result set values, even on closing the Result Set.

Memory architectures of 9i and 10g drivers are completely different. Since 10g, prepared statements hold the fetched result set values even after closing the result set. This is done to make subsequent query executions faster, as releasing the memory back to the system and acquiring it in the next execution cycle is very expensive. You can find more explanation in the document.

Let us consider a situation, where we have around 100 connections in the pool and each connection has a statement cache of size 100, and assume 100 result set rows have been cached, each of 1KB. Each prepared statement would hold on to 100KB of results and for each connection ~10MB (100 x 100KB). And for the entire pool of connections it would be close to ~1GB (100 x 10MB). This explains the high memory usage situation with Oracle 10g drivers.

Oracle driver’s Implicit cache implementation seems to workaround this problem, by clearing up the Result Set values through an additional configuration parameter.

Implicit Statement Cache

Implicit cache is provided by the JDBC Driver implementation and when enabled, implicitly caches the prepared statement objects. But, Implicit statement cache stores only meta data not the statement data and state required for a prepared statement. Oracle driver documentation discusses about performance degradation when using Implicit cache. We verified this by comparing the standard performance benchmark SpecjAppServer 2004 with Application Server caching against Oracle’s implicit cache.

Memory Leak Fix

For 10g driver
Oracle implicit statement cache provides connection property, oracle.jdbc.FreeMemoryOnEnterImplicitCache which when set to true clears the cached result set values, when the statement is returned back to cache. The following are the comparison results for SpecJ benchmark, and we haven’t observed any considerable performance degradation using Driver’s implicit cache.

SpecJ Results comparison with Server Statement Cache and Oracle Implicit Statement Cache

SpecJSummary

DealerSummary

For 11g driver
From 11g driver onwards there is no need to set oracle.jdbc.FreeMemoryOnEnterImplicitCache connection property to true. If we use implicit statement cache, automatically result set values are cleared.

Conclusion
To avoid oracle driver’s memory leak  issue in pramati server,

1. Enable oracle implicit statement cache by writing a custom validator class.
2. Set pramati server’s statement cache size to zero and add the connection initialization validator class.
3. Pass the oracle.jdbc.FreeMemoryOnEnterImplicitCache property or as one of connection property(this property is applicable only for 10.2.0.4.0 jdbc drivers).

In the connection intialialization validator class, we could add below code to enable the Oracle Implicit Cache,

public class CustomConnectionValidator implements ObjectValidator {

    public boolean isValid(Object obj) {
        System.out.println("Custom Connection Validation");
        try {
            OracleConnection ocon = (OracleConnection)obj;
            ocon.setImplicitCachingEnabled(true);
            ocon.setStatementCacheSize(300);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return true;
    }

    public int getModeOfValidation() {
        return CHECK_UNTIL_INVALID;
    }
}

Make the statement cache size as zero and add the connection intialization validator class,

<datasource connection-factory="cf" description="No Description"
         name="ds_spec" system-managed="false" transaction-isolation=""
         transaction-participation="true">
     <pool-properties cache-size="0" connection-request-timeout-seconds=""
         idle-timeout-seconds="" initial-pool-size="100"
         max-pool-size="100" min-pool-size="100"
         refresh-interval-seconds="5600"/>
     <connection-initialization class="CustomConnectionValidator"
         db-retrials="0" db-retry-interval-millis="0"/>
     <connection-validation on-acquire="false" on-release="false" sql=""/>
     <connection-tracking enable="false"/>
 </datasource>

We should pass oracle.jdbc.FreeMemoryOnEnterImplicitCache property as one of connection property for connection factory as follows,

<connection-factory authorized-by="container" classname="oracle.jdbc.driver.OracleDriver"
         classpath="" description="No Description" name="cf"
         url="jdbc:oracle:thin:@192.168.1.81:1521:specdb">
    <login-parameters mask-password="true" password="dGlnZXI=" user="scott"/>
    <properties>
        <property name="protocol" value="thin"/>
<property name="oracle.jdbc.freeMemoryOnEnterImplicitCache" value="true"/>
    </properties>
 </connection-factory>

Server socket JVM_Bind issue in Windows Vista

Recently, one of our customers reported an “Unrecognized Windows Sockets error: 0: JVM_Bind” during application deployment.

Exception in thread "main" java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:359)
at java.net.ServerSocket.bind(ServerSocket.java:319)
at java.net.ServerSocket.<init>(ServerSocket.java:185)
at java.net.ServerSocket.<init>(ServerSocket.java:97)
......

From the exception stack trace it is evident that the Server socket is bound to an already used up port. In our case it was re-deployment which is failing, so we took netstat after the first successful deployment. In the netstat report, to our surprise we observed that the port is bound to two different network interfaces.

Active Connections
TCP    0.0.0.0:4445           test:0           LISTENING
TCP    [::]:4445              test:0           LISTENING

The is because, on Windows Vista every socket is bound to both IPv4 and IPv6 network interfaces by default. (IPv6 interface is denoted by the [::] convention in the output).

netstat report after stopping the application, still shows the port listening on the IPv6 interface.

Active Connections
TCP    [::]:4445               test:0          LISTENING

This clearly indicates that the port is not getting released from the IPv6 interface on stopping the application. Hence, the second deployment which uses the same port fails.

Windows XP, 2003 or 2008 by default comes with IPv4 network interface only, where as Vista comes with both IPv4 and IPv6 interfaces enabled. When the Server socket is created without any bind address, the socket is bound to all the network interfaces available on the system. To find out all the interfaces available on a system we can use JDK’s NetworkInterface.getNetworkInterfaces() method. The following is the output on XP and Vista systems respectively,

XP:

MS TCP Loopback interface
Host Name : localhost                         Addresss : 127.0.0.1

Broadcom NetXtreme 57xx Gigabit Controller - Packet Scheduler Miniport
Host Name : test-n.pramati.com                Addresss : 192.168.1.31

Vista:

Software Loopback Interface 1
Host Name : 0:0:0:0:0:0:0:1                  Addresss : 0:0:0:0:0:0:0:1
Host Name : 127.0.0.1                        Addresss : 127.0.0.1

Realtek RTL8169/8110 Family PCI Gigabit Ethernet NIC (NDIS 6.0)
Host Name : fe80:0:0:0:c00a:dda9:3eb8:49ac%8   Addresss : fe80:0:0:0:c00a:dda9:3eb8:49ac%8
Host Name : test.pramati.com                 Addresss : 192.168.1.82

After going through the JDK bugs database, we found bug ID 6598160 reported. To understand the above issue, let us try the example quoted in the bug description,

ServerSocket ss = null;
try {
   ss = new ServerSocket(5252);
   Runtime.getRuntime().exec(new String[] {"notepad.exe"});
   System.in.read();
} finally  {
   ss.close();
}

While running the above code on Windows Vista, notepad application is opened and socket doesn’t close until we press a key and enter. Taking netstat before stopping the process, we can see port 5252 listening on all available network interfaces,

Active Connections
TCP    0.0.0.0:5252           test:0           LISTENING
TCP    [::]:5252              test:0           LISTENING

After stopping the process, but not closing the launched notepad application, netstat still shows the port 5252 listening on IPv6 interface. This is an issue with JDK 1.6 on Windows with IPv6 enabled.

Active Connections
TCP    [::]:5252               test:0           LISTENING

This is because in JDK for Vista, IPv4 socket has it’s handles set to non-inherit while creation, but not for the IPv6 stack. So, this allows the child process i.e. notepad, to inherit the handle to the socket for IPv6 interfaces. So, while child process is still alive, even if the parent process stops port is still not freed. As soon as notepad is closed, port is released on IPv6 interfaces.

We can run java application with system property -Djava.net.preferIPv4Stack=true to avoid socket listening on IPv6 interfaces, but this will make the application not able to communicate through IPv6 protocol. This issue has been fixed in JDK 1.6 update 10 on Windows.

Disabling Unsafe SSL Session Renegotiation on Pramati Server

Pramati Server internally uses, JDK SSL sockets to communicate over https. The underlying JDK in use, handles ssl handshake and re-negotiation if required. Hence to disable session renegotiation, one must use a JDK which has the issue addressed (for Example JDK 1.6 update 21). For already installed pramati servers, one can change the JDK in use by changing JAVA_HOME variable in the file <server-install>/server/bin/setup.bat (or setup.sh in UNIX OS).

@ ECHO Generated batch file to setup Environment Variables for Pramati Server 6.0
set install_root=D:\Pserver60_1091_SP3\server
set JAVA_HOME=D:\Java\jdk1.6.0_21
set PATH=%JAVA_HOME%\bin;%PATH%
set CLASSPATH=%JAVA_HOME%\lib\tools.jar;%install_root%\lib\pramati\classpath.jar;

Now the nodes can be started using the runserver script file as usual and SSL Session renegotiation shall be disabled by default.

Testing SSL Session renegotiation:
For my test case I have used the instructions at http://blog.ivanristic.com/2009/12/testing-for-ssl-renegotiation.html

The Console output:

C:\OpenSSL098a\bin&gt;openssl s_client -connect localhost:443
Loading ’screen’ into random state – done
CONNECTED(00000784)
depth=0 /C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
verify return:1

. . .
[SSL-Handshake-Messages]

. . .

HEAD / HTTP/1.0
R
RENEGOTIATING
6776:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:.\ssl\s3_pkt.c:534:

closed

C:\OpenSSL098a\bin&gt;

Step By Step:
1. Navigate to the OpenSSL bin directory on a Command Prompt
2. Execute command to connect to running web server using command

openssl s_client -connect localhost:443

3. If the server IP and Port are correct, connection will be through and a lot of SSL handshake messages shall be printed on console.

Loading ’screen’ into random state – done
CONNECTED(00000784)
depth=0 /C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
verify return:1

Certificate chain
0 s:/C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
i:/C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate

Server certificate
—–BEGIN CERTIFICATE—–
MIICXzCCAcigAwIBAgIES6tMbTANBgkqhkiG9w0BAQUFADB0MQ4wDAYDVQQGEwVJ
bmRpYTELMAkGA1UECBMCQVAxEjAQBgNVBAcTCUh5ZGVyYWJhZDEQMA4GA1UEChMH
UHJhbWF0aTEUMBIGA1UECxMLRW5naW5lZXJpbmcxGTAXBgNVBAMTEHRlc3QgY2Vy
dGlmaWNhdGUwHhcNMTAwMzI1MTE0MzQxWhcNMTEwMzI1MTE0MzQxWjB0MQ4wDAYD
VQQGEwVJbmRpYTELMAkGA1UECBMCQVAxEjAQBgNVBAcTCUh5ZGVyYWJhZDEQMA4G
A1UEChMHUHJhbWF0aTEUMBIGA1UECxMLRW5naW5lZXJpbmcxGTAXBgNVBAMTEHRl
c3QgY2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALi1cXLT
TxkqxCcHVm/7JcoRn3uJlex3NAnEMYNLTopf2SOzdJDYRjd3MHY3JcT+yEtvfNSR
Vpj7KyDTD0Up2XDZyk0+yJAI6DqLelmfak4/uDbXMW9T7jW7Gu2jbJA5WJD5oyHF
MuiWRAu3xdL049H5uRDJpUN2ckVGBN/eBdOnAgMBAAEwDQYJKoZIhvcNAQEFBQAD
gYEASdTN256auusTcKOReeh2OW8y0PS6kI4eSPjAWCqI+bnixtxc5bhNp/p2kjbL
IqcfpQnRmffbMLXlHJgV03DL4jUTXQCwJu6Jw4fHwiUnU+prcruVDSPT9pNZbEId
ou8CYYE5ISVz+wWSXv6tXRDVhLjj4JZVOl58p9DqzUR+Evc=
—–END CERTIFICATE—–
subject=/C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
issuer=/C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate

No client certificate CA names sent

SSL handshake has read 1152 bytes and written 338 bytes

New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol  : TLSv1
Cipher    : EDH-RSA-DES-CBC3-SHA
Session-ID: 4C5027FBD785EA3AAAB4ACBB45A1426E52D5DF829DD13D1B9CDF25C6266D6FC6
Session-ID-ctx:
Master-Key: 291247553A11AF4AC9FB54DE32D677ACE804605675D3EC58B72572D31E831EFB4D2E6C339AB39458E56E8650D2FF8253
Key-Arg   : None
Start Time: 1280321531
Timeout   : 300 (sec)
Verify return code: 18 (self signed certificate)

4. Now, the connection shall remain active for the socket idle timeout seconds, which is usually 3 seconds for default Pramati Server node.
5. We can send first line of Request header now. Paste the following at command prompt and press enter (before the time out happens of-course).

HEAD / HTTP/1.0

6. Now we can initiate a renegotiation by typing R and pressing enter.

R

(The time out sure applies here as well. So make sure you key in R and press enter before the time out of 3 seconds starting from the point we pressed enter for the HEAD line above)

7. A renegotiation request is now initiated. Now is the time for results. If JDK does not allow renegotiation, the output on the same window shall be as given below:

RENEGOTIATING
6776:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:.\ssl\s3_pkt.c:534:

8. If the JDK allows renegotiation, the output shall be like :

RENEGOTIATING
depth=0 /C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=India/ST=AP/L=Hyderabad/O=Pramati/OU=Engineering/CN=test certificate
verify return:1

9. We can leave the prompt now as it is, and the connection shall be closed automatically by time-out

closed

JDK also provides a system property to re-enable SSL re-negotiation, which can be configured in the server startup script runserver.bat / runserver.sh.

Extending Java URLs to support your own protocol

We have been evaluating to support deploying applications that are uploaded to ftp/http Servers. Usually to deploy an application, you need to download or copy the archive to the same machine where your Application Server runs. And using one of the various deployment tools provided by the Server, deploy application by specifying the file path.

To make the deployment process much simpler, we can now directly deploy the archive using URL spec. Java URLs can be made to work with protocols like http, ftp, etc., with support for introspection of standard headers and authentication mechanisms. For example, you can download an archive uploaded to ftp site as shown below.

URL url = new URL("ftp://guest:guest@ftp.mysite.com/apps/myapp.war");
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();

You can see that the user & password are also included within the URL, as it requires authentication. Now, all that we need to deploy application is the URL spec., ftp://guest:guest@ftp.mysite.com/apps/myapp.war. This is not just enough, with the growing adoption towards cloud storage services like Amazon S3, there is need to support more protocols. Java allows configuring custom protocol handlers by implementing java.net.URLStreamHandler and placing it in the classpath. The following is a protocol handler for Amazon S3.

package sun.net.www.protocol.s3;

public class Handler extends URLStreamHandler {

   protected URLConnection openConnection(URL u) throws IOException {
      InputStream is;
      try {
         RestS3Service s3Service = new RestS3Service(
               new AWSCredentials(accessKey, secretAccessKey));
         S3Object s3obj = s3Service.getObject(
               new S3Bucket(u.getHost()), u.getPath().substring(1));
         is = s3obj.getDataInputStream();
      }catch (S3ServiceException e){
         throw new IOException(e);
      }
      final InputStream inputStream = is;
      return new URLConnection(u) {
         public InputStream getInputStream() throws IOException {
            return this.inputStream;
         }
         public void connect() throws IOException {
            // Nothing to do. When we give back this object
         }
      };
   }
}

The package name for the handler class, sun.net.www.protocol.s3 indicates URL mechanism to use this handler for S3 protocol, i.e. for all URLs of the form s3://s3.amazon.com/mybucket/myapp.war, and most importantly the class name should be named as Handler. The package name convention is enforced to make sure the standard protocol handlers are always loaded by the Java boot strap classloaders. However, there is an antidote if you intend to override the default behaviour through system property java.protocol.handler.pkgs, which allows specifying a comma separated list of packages to look for the protocol handlers.

However, the above approach requires protocol handler classes to be placed in system classpath only. There is another approach to control the protocol handling mechanism through the java.net.URLStreamHandlerFactory class, which can be set through a public static method in java.net.URL.

URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
   public URLStreamHandler createURLStreamHandler(String protocol) {
      ...
      return null;//if you do not intend to create handler for this protocol
   }
});

With the Factory approach we can completely customize the class loading mechanism, package and class name conventions and overriding the default protocol handlers. But the downside is, once the Factory is set, it cannot be reset within the JVM. Especially, if running within a Container or Server environment which has the URLStreamHandlerFactory already set, there is no way of setting our own factory again.

Using the above approaches, we can support deploying applications from one of your favourite storage services through its own protocol.

Performance issues with JDBC drivers’ for MS SQL Server

Recently one of our customers reported that their JMS server startup was taking long time, when they restart the server after a downtime. They were using MS SQL Server 2005 as the persistent store for JMS and Microsoft’s JDBC driver to connect to the database. Upon initial analysis, we figured that there were incomplete transactions present in the DB during the server restart. JMS Server loads all these transactions in-memory during the startup. The delay was around 20 minutes for 20K incomplete transactions. Ideally, as per our tests with other DBs, this should be done in 15-20 seconds. The thread dumps revealed us that even simple delete queries that are part of this transaction loading step were taking substantial amount of time. We started digging into the database and driver configuration and found that it was JDBC driver which was causing the whole slow-down.

SQL Server differentiates its data types that support Unicode from the ones that just support ASCII. For example, the character data types that support Unicode are nchar, nvarchar, longnvarchar where as their ASCII counter parts are char, varchar and longvarchar respectively. By default, all Microsoft’s JDBC drivers send the strings in Unicode format to the SQL Server, irrespective of whether the datatype of the corresponding column defined in the SQL Server supports Unicode or not. In the case where the data types of the columns support Unicode, everything is smooth. But, in cases where the data types of the columns do not support Unicode, serious performance issues arise especially during data fetches. SQL Server tries to convert non-unicode datatypes in the table to unicode datatypes before doing the comparison. Moreover, if an index exists on the non-unicode column, it will be ignored. This would ultimately lead to a whole table scan during data fetch, thereby slowing down the search queries drastically.

All the tables created by the JMS Server have non-unicode datatypes and hence will be the indexes on non-unicode datatypes. With this, we fell in the trap of the MS JDBC driver’s default behaviour, facing a performance degradation.

On digging the driver’s configuration, we figured that there is a property called sendStringParametersAsUnicode which helps in getting rid of this unicode conversion. This property defaults to ‘true’ which makes the JDBC driver send every string in Unicode format to the database by default. We switched off this property and achieved two improvements in our use-case:
1) All string parameters of our prepared statements are being sent to the database in ASCII format. This helped us overcome the Unicode conversion overhead.
2) Since Unicode conversion isn’t happening, all our indexes on varchar columns are being used during data fetches instead of whole table scans.

With this, we were able to get our JMS server started in less than 30 sec.

This performance degradation is quite possible with other driver’s for Microsoft SQL Server also as the default behaviour in the well-known drivers for MS SQL Server is to send strings as Unicode by default. However, all these drivers have a similar property to tweak the default behaviour. Here is a list of these of properties by vendor:

Vendor Parameter
JSQLConnect asciiStringParameters
JTDS sendStringParametersAsUnicode
DataDirectConnect sendStringParametersAsUnicode
Microsoft JDBC sendStringParametersAsUnicode
WebLogic Type 4 JDBC SQL Server driver sendStringParametersAsUnicode

How to apply the property in Pramati Server?
Pramati Server maintains all datasources, jdbc connection factories in an xml file called resource-config.xml. The property sendStringParametersAsUnicode has to be added under the ‘properties’ element of the corresponding jdbc connection factory.

Example:
<connection-factory authorized-by=”Container” classname=”com.microsoft.sqlserver.jdbc.SQLServerDriver” description=”" name=”jmsdb-cf” url=”jdbc:sqlserver://localhost\SQLEXPRESS;DatabaseName=TESTDB”>
<login-parameters mask-password=”false” password=”pramati” user=”sa”/>
<properties>
<property name=”sendStringParametersAsUnicode” value=”false”/>
</properties>
</connection-factory>

Alternately, the property can also be added to the connection url string as shown below:

<connection-factory authorized-by=”Container” classname=”com.microsoft.sqlserver.jdbc.SQLServerDriver” description=”" name=”jmsdb-cf”
url=”jdbc:sqlserver://localhost\SQLEXPRESS;DatabaseName=TESTDB;sendStringParametersAsUnicode=false“>
<login-parameters mask-password=”false” password=”pramati” user=”sa”/>
<properties/>
</connection-factory>

Working with Pramati Server MBeans

Like other Application servers, Pramati Server have Management Console, through which you can monitor server health, configure JDBC, JMS resources and much more  management/administrative activities. All these are done through Management Bean, popularly known as MBeans. Pramati Server’s Management Console implements Java Management Extensions (JMX) specifications (JSR 77). It also exposes Management APIs to facilitate server management through custom tools and applications. You can refer to the link here to have more idea on it.

If you have installed Pramati Server, then access the Management console through “http://<host_name>:<port_name>/admin” and login with default user name, password as “root” and “pramati” respectively.

where,

  1. <host_name> :  Is your host name where server is installed
  2. <port_name> :  HTTP listener port value, default is 8181

After logging in, on the left navigation panel, click on “Utilities”. Now you can see “MBean Viewer” link there. MBean Viewer is a utility provided in the Console to allow you to view details about all the MBeans present in and being used by the various Domains. Further expanding the Domain will list all the MBeans related to it. Clicking on a listed MBean will display the following three tabs for the same MBean:

  1. attributes
  2. operations
  3. notifications

You can also avail the Management APIs for particular MBean, by clicking on the link provided under “JavaDoc” section. You can use them as per requirement. Click on the “Help?” icon present on MBean Viewer page to know more about it.

Now, lets see a sample which shows the status of the Datasource configured on the Pramati Server. I assume that you already have a DataSource configured on server. Find more information on configuring DataSources here.  Now coming to our sample with MBean, here is the snippet of code:

import java.util.Properties;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.InitialContext;

import com.pramati.services.admin.base.StatisticsProvider;
import com.pramati.services.admin.stat.Statistic;
import com.pramati.services.admin.stat.StatisticMetadata;
import com.pramati.services.admin.stat.Stats;
import com.pramati.services.admin.util.PoolStatus;
import com.pramati.services.j2ee.spi.admin.J2EEServerMBean;
import com.pramati.services.resource.spi.admin.JDBCResourceMBean;
import com.pramati.services.resource.spi.admin.JDBCSelfManagedDataSourceMBean;

public class MyMBeanLookup {

public static void main(String args[]) {
try {

//Create Initial Context to the server where we want to lookup the resources
Properties props = new java.util.Properties();
props.put("java.naming.factory.initial","com.pramati.naming.client.PramatiClientContextFactory");
props.put("java.naming.provider.url", "rmi://127.0.0.1:9191");
InitialContext ic = new javax.naming.InitialContext(props);
J2EEServerMBean mBeanServer = (J2EEServerMBean) ic.lookup("root-server-mbean");

//Get Name of Node
System.out.println("The Server Node Name is :: " + mBeanServer.getServerName());

//Get hold of JDBCResourceMBean
JDBCResourceMBean myResourceMbean = mBeanServer.getJDBCResourceService();

//Get all Container Managed DataSources
JDBCSelfManagedDataSourceMBean[] dataSources = myResourceMbean.getJDBCSelfManagedDataSources();

//Iterate the datasources to get the stats
for (JDBCSelfManagedDataSourceMBean dataSource : dataSources) {
Stats getMyStats = dataSource.getStats();
System.out.println("The DS name :: " + dataSource.getJNDIName());
System.out.println("ConnectionRefreshRate in Minutes :: "+ dataSource.getConnectionRefreshRateMinutes());
System.out.println("ConnectionRequestTimeout in Seconds :: "+ dataSource.getConnectionRequestTimeout());

//Get Pool statistics
PoolStatus poolStat = dataSource.getCurrentPoolStatus();
System.out.println("Total Pool size :: " + poolStat.getPoolSize());
System.out.println("Free Pool size :: "+ poolStat.getFreePoolSize());
System.out.println("in Use Pool size :: "+ poolStat.getInUsePoolSize());
}
} catch (Exception e) {
e.printStackTrace();
}
}

}

Change the following line of code with appropriate host-name and naming port value for successful lookup on server.

props.put(”java.naming.provider.url”, “rmi://127.0.0.1:9191″);

To compile and execute the class successfully, you need to have following list of jar files in classpath:

  1. pramati_client_all.jar :   located at <$pserver_install>\server\lib\pramati_client
  2. pramati_client_all_jms.jar :   located at <$pserver_install>\server\lib\pramati_client
  3. pramati_jmsconn.jar :   located at <$pserver_install>\server\lib\pramati
  4. pramati_serveradmin.jar :   located at <$pserver_install>\server\lib\pramati
  5. pramati_util.jar :   located at <$pserver_install>\server\lib\pramati

On successful execution, you should see the status of the configured DataSource. Similarly you can view other services status through

com.pramati.services.j2ee.spi.admin.J2EEServerMBean
or
com.pramati.services.jms.spi.admin.JMSServerMBean

by looking up “root-server-mbean” or “jms-server-mbean” either from the same VM or remotely.

The sample was for viewing the statistics. You can also make any configurational changes through MBean. Changes can not be done through anonymous login. That means in the above example, user is an anonymous user. You must provide administrative credential details to do so. For this, add following three lines to your code:

props.put(”java.naming.security.principal”, “root”);
props.put(”java.naming.security.credentials”, “pramati”);
props.put(”com.pramati.naming.realm”, “system”);

where,

  1. root :   default user name
  2. pramati :   default password
  3. system :   default realm configured on Pramati Server

If you are not using the default values of these properties, then replace them with your customized ones.

Configure SSL on Pramati Server using Admin Console

SSL (Secure Socket Layer), is a request/response protocol that involves public and private keys, as well as a digital certificate. SSL technology allows web browsers and web servers to communicate over a secure connection. In this secure connection, the data that is being sent is encrypted before being sent and then is decrypted upon receipt and before processing. Both the browser and the server encrypt all traffic before sending any data. An SSL connector is pre-configured for the Application Server. By default this feature is disabled on Pramati Server. To configure SSL support on Pramati Server, you need to follow the simple steps:

Configure/Enable Server for HTTPS Requests :

1. If Pramati Server is already up and running and you want to configure SSL support on the fly with the default (https-port value 443) configuration, execute the following command at Server Shell prompt:

j2eeadmin@default> ssl_accept start

Eg:

Refer the following screen-shot for the details:

screen1

2.  If you want to configure SSL support with your own configuration:

* Edit server-config.xml file located at <install_dir>/server/nodes/<node_name>/config/ directory.

* Locate the following under the services tag:

<service name=”WebContainer” enabled=”true” class-name=”com.pramati.web.WebServer”>
<property name=”https-port” value=”443″/>
</service>

* By default, https-port is set as 443. Set this value to the required HTTPS port as you want to modify and save this file.

* Now, edit web-config.xml file located at <install_dir>/server/nodes/<node_name>/config/ directory.

* By default,

<protocol http-enabled="true" ssl-enabled="false"/>.

Set ssl-enabled to true as

<protocol http-enabled="true" ssl-enabled="true"/>.

* Save the changes and restart Server.

* Note that, you will see the following information during the restart of Pramati Server on the server console:

screen2

This confirms that SSL support is enabled successfully on Pramati Server.

Manage Security Certificates using Management Console:

1. Start Pramati Server and access the following url:

http://localhost:8181/admin/

2. Provide the required credentials and navigate to “Configure –> Security Certificates” available in the left panel of management console .

3. By default, you see a test certificate called “default” under “Server Certificates” section.  Click on “Add” button:

screen3

4. Once you have clicked “Add” button, the following screen will display for the details. Fill the details as per the requirement and click “Save” button:

screen4

5. Make sure that the certificate name should be equal to the domain name of the site for which you are trying to configure https. In the above example it is test.pramati.com.  Here, you can ignore the port numbers on which you are going to access the application.

6. The created certificate will appear as shown in the following screen-shot:

screen5

The created certificate contains “Alias” name with Issued By and Issued To information. Presently both the entries are equal to the target domain name. This indicates that the certificate is generated for this domain and not yet signed by CA.

7.  The server certificates are loaded during the startup of Pramati Server. By default test certificate is the one which is available, can be picked up. Hence, it is suggested that delete the existing test certificate with alias “default” after creating a new certificate (Eg: samplecert). To delete “default” certificate, check the box available against to alias name “default”  and click “Delete” button. Once you have deleted the existing default certificate, restart Pramati Server to use the newly created certificate.

Note:

It is always recommended that you should have only one certificate under “Server Certificate” section.

8. The certificate that is generated using Server is a self-signed certificate. For getting the certificate signed by a CA, a Certificate Signing Request (CSR) must be sent to the CA. To obtain the CSR,  click on the certificate’s alias name (samplecert) and select “Save CSR”  option in the next screen.

* In case of InternetExplorer, you will get a prompt for saving the file. Click on “Save” and provide the name as “CSRReply.cer“.

* In case of Firefox, CSR details will be displayed directly in right panel of management console. Copy the content and paste in a notepad. Save this file as “CSRReply.cer“.

9.  Once the CSR is generated, the CSR file has to be mailed to the CA. The CA signs the same and sends back the same.

10. Once you have received the mail from CA, extract the CSRReply certificate and save it on the localmachine as “CSRReply.cer“.

11. As most of the CA’s are already listed in Pramati Server under “Certification Authorities trusted by Server” section, you can import the CSRReply on the generated self-signed certificate.

Note:

If the CA is not listed in the trusted certs of Pramati Server, you will get “Exception while importing the CSR reply in the store…” exception. To overcome this problem, refer “General Exceptions with solutions” section which is explained after the completion of the current steps in this post.

12. To import CSRReply, click on alias (samplecert) name and browse for the CSRReply.cer file under “Certificate Signing Request Reply” section and click “Import“.

13. Upon the successful import of certificate, the following information(as shown in the screen-shot) will be displayed against the alias name under “Server Certificates” section:

screen6

14. This confirms that the certificate is issued to domain(test.pramati.com) by CA (verisign).

15. Now, access the following URL to confirm the same:

https://test.pramati.com/admin/ (if you have configured https-port as 443 else you have to access this url with port number specified). Make sure that test.pramati.com should points the machine where you have installed the certificate.

General Exceptions with solutions:

1.
File uploaded. Now putting certificate in store…

Exception while importing the CSR reply in the store…:Error while importing the CSR reply. – Could not establish the certificate chain.

Solution:

The above exception clearly indicates that the certificate chain is incomplete.  A certificate chain is a sequence of certificates, where each certificate in the chain is signed by the subsequent certificate. The last certificate in the chain is normally a self-signed certificate-a certificate that signs itself.

Following is the exception while trying with verisign trial certificate:

Exception while importing the CSR reply in the store…:Error while importing the CSR reply. – Could not establish the certificate chain. Missing certificate for issuer ‘CN=VeriSign Trial Secure Server CA – G2, OU=Terms of use at https://www.verisign.com/cps/testca (c)09, OU=”For Test Purposes Only. No assurances.”, O=”VeriSign, Inc.”, C=US’

*To resolve this problem, firstly, double click on “CSRReply.cer” certificate which you have received from CA and saved on the local machine. This certificate contains the information as shown below:

screen8

* This certificate is issued by “Verisign Trial Secure Server CA – G2“. So, you need to import root/intermediate certificate for “Verisign Trial Secure Server CA – G2“  into “Certification Authorities trusted by Server” section. You can get these root/intermediate certificates from respective CA. Mostly, all the instructions (download locations) are explained in the CSR reply mail sent by CA.

* Once you have download the root/intermediate certifcate from the respective locations, save this certificate as “inter.cer” and double click this certificate for the details. Details are as follows:

screen9

* As this certificate is issued by “Verisign Trial Secure Server Root CA – G2“, you need to import root/intermediate certificates for “Verisign Trial Secure Server Root CA – G2” into “Certification Authorities trusted by Server” section.

* Once you have download the Root CA certificate from repsective location, save this file as “RootCA.cer” and double click this certificate to view the details. Details are as follows:

screen10

* This indicates clearly that the “issued by” and “issued to” are same. This conclude that the chain completes if you have the above specified two root/intermediate certificates in the Pramati Server’s trusted store. To import these files, click on “Add” button under “Certification Authorities trusted by Server” section and browse for files and click “import” button to import the intermediate certificates.

* Once you have imported these files under “Certification Authorities trusted by Server” section, import CSRReply, by clicking on alias (samplecert) name and browse for the CSRReply.cer file under “Certificate Signing Request Reply” section and click “Import“.