<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Krishnan Subramanian</title>
	<atom:link href="http://blogs.embarcadero.com/krish/feed" rel="self" type="application/rss+xml" />
	<link>http://blogs.embarcadero.com/krish</link>
	<description></description>
	<pubDate>Thu, 28 Jul 2005 13:47:27 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en-US</language>
			<item>
		<title>Java &#38; SSL</title>
		<link>http://blogs.embarcadero.com/krish/2005/07/28/20601</link>
		<comments>http://blogs.embarcadero.com/krish/2005/07/28/20601#comments</comments>
		<pubDate>Thu, 28 Jul 2005 13:47:27 +0000</pubDate>
		<dc:creator>Krishnan Subramanian</dc:creator>
		
		<category><![CDATA[General]]></category>

		<category><![CDATA[J2EE]]></category>

		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/krish/2005/07/28/2239/</guid>
		<description><![CDATA[Some information on how SSL (or Transport Layer Security - TLS to be precise) works in general and how Java can be configured to use TLS. It is a rather long post . . .]]></description>
			<content:encoded><![CDATA[<p><P><SPAN style="FONT-FAMILY: Garamond">Java provides a whole slew of standardized APIs for&nbsp;everything under the Sun (pun intended) ranging from database access to security to protocols for remote access etc. Recently I was at a customer in Stockholm for 2 weeks &#8211; getting a testing/staging environment in place with a number of test and load scripts.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">To put a long story short, a number of load test scripts I was writing required SSL communication and though I had written applications that communicated over SSL with pluggable authentication &amp; authorization providers, I had never really gotten into SSL at the protocol level and decided to do that after my customer engagement.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">SSL was originally developed and published by Netscape. SSL version 3.0 formed the basis of the Transport Layer Security (TLS) protocol version 1.0.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">TLS 1.0 has 4 goals:</SPAN></P> <P><SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">&#183;<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Security (establish a secure connection between end points for communication)</SPAN></P> <P><SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">&#183;<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Interoperability (interoperate with different providers, implementations etc.)</SPAN></P> <P><SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">&#183;<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Extensible (new key &amp; encryption methods can be added without creating a new protocol)</SPAN></P> <P><SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">&#183;<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Efficient (CPU &amp; network utilization should be reduced)</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">The protocol stack looks something like this:</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond"></SPAN>&nbsp;</P> <P align="center"><SPAN style="FONT-FAMILY: Garamond">TLS Handshake | TLS Change Cipher spec | TLS Alert | HTTP<BR>TLS Record Protocol<BR>TCP<BR>IP</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">The TLS Record Protocol encapsulates higher level protocols and has two basic properties:</SPAN></P> <P><SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">&#183;<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Connection is private &#8211; that is, keys for encryption are generated uniquely for each connection</SPAN></P> <P><SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"><SPAN style="mso-list: Ignore">&#183;<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Connection is reliable &#8211; that is, tampering of data can be detected by integrity checks</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">It might be useful to understand how TLS operates. The essential sequences of steps for the handshake protocol are:</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">client sends a hello with security capabilities it (the client) knows about</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">server chooses the best capability from the client hello and responds with a chosen capability in its hello response (server hello)</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">server sends authentication information about itself and sends a key</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">4.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">server hello is done</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">5.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">client generates a key and sends it to server encoded with key sent by server in step 4</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">6.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">client finished</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">7.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">server finished</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">8.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">all subsequent communication between client and server switch to key generated in step 5</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond"></SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">Asymmetric cryptography &#8211; also known as public key cryptography uses an encryption algorithm in which two keys are produced. One key is made public and the other is private. These keys are inverses of one another &#8211; that is, what one key encrypts, the other decrypts and vice-versa. And it is not computationally feasible/possible to derive the key inverse from one key. Examples of asymmetric algorithms include RSA, DSS etc.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">In symmetric cryptography &#8211; also knows as secret key cryptography, the same key is used to encrypt and decrypt data.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">Asymmetric cryptography is generally more computationally intensive compared to symmetric cryptography.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">TLS 1.0 uses a combination of both asymmetric and symmetric cryptography. First, on the server side, a pair of public and private keys is generated. The private key is known only to the server while the public key can be distributed to clients. However, any party can supply a client with a public key thereby masquerading as a server. To solve this problem of public key distribution, certificates were introduced as a safe mechanism for an entity to pass on its public key to clients. The certificate is a digital equivalent of a passport and is issued by trusted organization usually called a certificate authority (e.g. Verisign, Thawte etc). The certificate authority will provide a certificate only upon proof of identity of the requester of the certificate. The certificate contains a number of fields including issuer (the certificate authority), the time period for which the certificate is valid, information about the entity that the certificate represents, the public key and the digital signature of the certificate authority that issued the certificate.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">Thus, the recipient of the public key can examine the certificate and decide if it chooses to accept the public key. </SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">To ensure data integrity TLS uses a cryptographic hash function. A hash is usually a fixed length of bits generated from a message. A cryptographic hash function is very similar to a checksum. While a checksum is used to check damages to data in transit, a cryptographic hash function is designed to check deliberate changes to data. Typically a cryptographic hash function will produce a large change to a resulting hash given a small change to the message. It is important to note that cryptographic hash does not require a key. Popular cryptographic hash functions include MD5, SHA-1 etc.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">The TLS process begins by a TLS handshake as was explained previously. The details are:</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Client sends a hello with the protocol it supports and the list of cipher suites it supports. The cipher suite contains information about the algorithm used for asymmetric cryptography (key exchange), symmetric cryptography and hash function (for data integrity and message authentication). The cipher suite will typically contain a list with the preferred suite on top. For example, one of the suites in the list might be: SSL_RSA_WITH_RC4_128_MD5. This indicates that the RSA algorithm is used for public-private keys (asymmetric cryptography), a 128 bit RC4 algorithm is used for secret keys (symmetric cryptography) and the MD5 cryptography hash function is used for data integrity and message authentication. The client hello message includes a list of compression algorithms if supported.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">The server chooses the top cipher suite and protocol it knows about and responds with that information as a part of its server hello message.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">The server sends its public key certificate to the client (server authentication)</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">4.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">The server completes its hello message</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">5.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">The client generates a pre-master secret, encrypts it using the public key from step 3 and sends it to the server. Since the private key is only known to the server, only the server will be able to decrypt the message.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">6.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Client sends a finish message &#8211; encrypted with the just negotiated algorithms and keys. The finish message includes the content of all previous handshake messages negotiated up until this message and its hash (Change Cipher Spec is done, but is not exactly a part of the handshake protocol and the finish is sent after the ChangeCipherSpec. Implies that communication will shift to using symmetric cryptography negotiated).</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">7.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">Server sends an equivalent finish message. The previous handshake messages included in the finish message with [its] hash prevent an eavesdropper from modifying any of the handshake messages (Change Cipher Spec is done, but is not exactly a part of the handshake protocol and the finish is sent after the ChangeCipherSpec. Implies that communication will shift to using symmetric cryptography negotiated).</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-fareast-font-family: Garamond; mso-bidi-font-family: Garamond"><SPAN style="mso-list: Ignore">8.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: Garamond">From the pre-master key, the client and server arrive independently to the same master key value (symmetric cryptography) that is used for subsequent encryption of messages between the client and the server for that session.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">On the Java side, Java provides an implementation of the TLS (version 1.0) and the SSL protocol (version 3.0) including encryption, server authentication and message integrity. The API is called the Java Secure Socket Extension (JSSE) and bundles an implementation of that API as well.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">In Java, certificates have to be placed in a keystore - a Java Key Store to be precise. The </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">keytool</SPAN><SPAN style="FONT-FAMILY: Garamond"> command line utility (bundled with the JDK) can generate test certificates or import existing certificates (issued certificates from a certificate authority). A keystore is standard mechanism to transport keys and certificates in a password protected file.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond">For example, to generate a RSA keypair, you would run:</SPAN><SPAN style="FONT-FAMILY: Garamond"></P> <P> <TABLE class="MsoTableGrid" cellSpacing="0" cellPadding="0" border="1"> <TBODY> <TR> <TD vAlign="top"><FONT face="Times New Roman"> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">$prompt&gt; keytool -genkey -alias serverCert -keyalg RSA -keysize 1024 -validity 9999 -keystore server.ks</SPAN></P> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">Enter keystore password:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>trustno1<BR>What is your first and last name?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[Unknown]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Krishnan Subramanian<BR>What is the name of your organizational unit?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[Unknown]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Professional Services<BR>What is the name of your organization?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[Unknown]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Borland Software Corporation<BR>What is the name of your City or Locality?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[Unknown]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Amstelveen<BR>What is the name of your State or Province?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[Unknown]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>North Holland<BR>What is the two-letter country code for this unit?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[Unknown]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>NL<BR>Is CN=Krishnan Subramanian, OU=Professional Services, O=Borland Software Corporation, L=Amstelveen, ST=North Holland, C=NL correct?<BR><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>[no]:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>y<BR>Enter key password for <BR><SPAN style="mso-spacerun: yes">&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN>(RETURN if same as keystore password):<SPAN style="mso-spacerun: yes">&nbsp; </SPAN></SPAN></P> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">$prompt&gt;</SPAN></P></FONT></TD></TR></TBODY></TABLE></P></SPAN> <P> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"></SPAN><SPAN style="FONT-FAMILY: 'Courier New'"></SPAN></P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">Initially when the </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">keytool</SPAN><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">&#8217;s </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">&#8211;genkey</SPAN><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'"> option is used, an RSA keypair is generated and the public key is wrapped in a self-signed certificate. Self-signed in the sense that the issuer of the certificate is the same as that of the entity for whom the keypair is being generated.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">If you were to apply to a commercial certificate authority (e.g. Thawte, Verisign etc) you would generate a certificate signing request (CSR) using the </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">keytool</SPAN><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">&#8217;s </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">&#8211;certreq</SPAN><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'"> option on the above generate keystore and submit the output of the certificate signing request along with necessary documentation proving your organization&#8217;s identity among others. After verification of documents, the certificate authority will issue you a certificate that you can then import into the keystore.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">However for testing purposes, it is overkill to apply to a certificate authority (fees for a certificate are usually a few hundred dollars). Remember that during the TLS handshake process, the server will send its certificate to the client. And it is up to the client to decide whether it will trust the certificate sent by the server. The trust is usually established by checking the issuing authority. There may be a certificate chain in which case, the client will navigate the certificate chain until it finds an issuing authority it will trust.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">You can check the content of the keystore using the keytool&#8217;s &#8211;list option. For example,</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'"> <TABLE class="MsoTableGrid" cellSpacing="0" cellPadding="0" border="1"> <TBODY> <TR> <TD vAlign="top"><FONT face="Times New Roman"> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">$prompt&gt;keytool -list -keystore server.ks<BR>Enter keystore password:<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>trustno1<BR><BR>Keystore type: jks<BR>Keystore provider: SUN</SPAN></P> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">Your keystore contains 1 entry<BR><BR>servercert, Jul 28, 2005, keyEntry,<BR>Certificate fingerprint (MD5): 3E:4C:D2:5F:D7:1C:F1:BF:5C:C2:CE:20:17:52:94:69</SPAN>&nbsp;</FONT></P></TD></TR></TBODY></TABLE></SPAN></P> <P> <P><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"></SPAN></P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">The above entry displays one </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">keyEntry</SPAN><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'"> (that is, a public/private key pair). It is important to note that the private key in the keystore is not accessible using the </SPAN><SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'">keytool</SPAN><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'"> utility.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">For an SSL Server application, for example &#8211; a Socket based application; you would specify the location and password of the keystore as JVM parameters.</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'">Here is a sample Socket Server application:</SPAN></P> <P><SPAN style="FONT-FAMILY: Garamond; mso-bidi-font-family: 'Courier New'"> <TABLE class="MsoTableGrid" cellSpacing="0" cellPadding="0" border="1"> <TBODY> <TR> <TD vAlign="top"><FONT face="Times New Roman"><PRE><FONT size="2"><B><SPAN style="COLOR: navy">import</SPAN></B><SPAN style="COLOR: black"> java.io.*;<BR></SPAN></FONT><FONT size="2"><B><SPAN style="COLOR: navy">import</SPAN></B><SPAN style="COLOR: black"> java.net.ServerSocket;<BR></SPAN></FONT><FONT size="2"><B><SPAN style="COLOR: navy">import</SPAN></B><SPAN style="COLOR: black"> java.net.Socket;<BR></SPAN></FONT><FONT size="2"><B><SPAN style="COLOR: navy">import</SPAN></B><SPAN style="COLOR: black"> javax.net.ssl.SSLServerSocket;<BR></SPAN></FONT><FONT size="2"><B><SPAN style="COLOR: navy">import</SPAN></B><SPAN style="COLOR: black"> javax.net.ssl.SSLServerSocketFactory;</SPAN></FONT></PRE><PRE><FONT size="2"><SPAN style="COLOR: black"></SPAN></FONT><FONT size="2"><B><SPAN style="COLOR: navy">public</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">class</SPAN></B><SPAN style="COLOR: black"> SocketServer {<BR><BR>  </SPAN></FONT><FONT size="2"><B><SPAN style="COLOR: navy">public</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">static</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">final</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">boolean</SPAN></B><SPAN style="COLOR: black"> <I>USE_SECURE</I> = </SPAN><B><SPAN style="COLOR: navy">true</SPAN></B><SPAN style="COLOR: black">;<BR></SPAN></FONT><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN></SPAN><B><SPAN style="COLOR: navy">public</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">static</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">final</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">int</SPAN></B><SPAN style="COLOR: black"> <I>PORT</I> = </SPAN><SPAN style="COLOR: blue">6666</SPAN><SPAN style="COLOR: black">;<BR></SPAN></FONT><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN></SPAN><B><SPAN style="COLOR: navy">public</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">static</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">final</SPAN></B><SPAN style="COLOR: black"> String <I>PASS_PHRASE</I> = </SPAN><SPAN style="COLOR: blue">"knock knock"</SPAN><SPAN style="COLOR: black">;</SPAN></FONT></PRE><PRE><SPAN style="COLOR: black"><FONT size="2"></FONT></SPAN></PRE><PRE><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN></SPAN><B><SPAN style="COLOR: navy">public</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">static</SPAN></B><SPAN style="COLOR: black"> </SPAN><B><SPAN style="COLOR: navy">void</SPAN></B><SPAN style="COLOR: black"> <I>main</I>(String[] </SPAN><SPAN style="COLOR: gray">args</SPAN><SPAN style="COLOR: black">) </SPAN><B><SPAN style="COLOR: navy">throws</SPAN></B><SPAN style="COLOR: black"> IOException {<BR></SPAN></FONT><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>ServerSocket mServerSocket = </SPAN><B><SPAN style="COLOR: navy">null</SPAN></B><SPAN style="COLOR: black">;<BR></SPAN></FONT><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN></SPAN><B><SPAN style="COLOR: navy">if</SPAN></B><SPAN style="COLOR: black"> (<I>USE_SECURE</I>) {<BR></SPAN></FONT><SPAN style="COLOR: black"><FONT size="2"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;</SPAN>mServerSocket = <I>getSecureSocket</I>();<BR></FONT></SPAN><SPAN style="COLOR: black"><FONT size="2"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}<BR></FONT></SPAN><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN></SPAN><B><SPAN style="COLOR: navy">else</SPAN></B><SPAN style="COLOR: black"> {<BR></SPAN></FONT><SPAN style="COLOR: black"><FONT size="2"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>mServerSocket = <I>getPlainSocket</I>();<BR></FONT></SPAN><SPAN style="COLOR: black"><FONT size="2"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}<BR></FONT></SPAN><FONT size="2"><SPAN style="COLOR: black"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN><I>System</I>.<I>out</I>.println(</SPAN><SPAN style="COLOR: blue">"SocketServer listening . . . "</SPAN><SPAN style="COLOR: black">);<BR></SPAN></FONT><SPAN style="COLOR: black"><FONT size="2"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN><I>startListening</I>(mServerSocket);<BR></FONT></SPAN></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/krish/?p=20601&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_20601" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Java%20%26amp%3B%20SSL&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fkrish%2F2005%2F07%2F28%2F20601" id="akst_email_20601" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/krish/2005/07/28/20601/feed</wfw:commentRss>
		</item>
		<item>
		<title>Extending Container Managed Persistence (CMP) Types</title>
		<link>http://blogs.embarcadero.com/krish/2004/12/22/2238</link>
		<comments>http://blogs.embarcadero.com/krish/2004/12/22/2238#comments</comments>
		<pubDate>Wed, 22 Dec 2004 16:25:09 +0000</pubDate>
		<dc:creator>Krishnan Subramanian</dc:creator>
		
		<category><![CDATA[Borland Enterprise Server]]></category>

		<category><![CDATA[J2EE]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/krish/2004/12/22/1809/</guid>
		<description><![CDATA[Entity beans represent an object view of data - usually stored in a relational database. The EJB 2.x specification does not limit the mapping&#160;of entity beans to a relational database although an RDBMS remains the most popular choice of supported persistence for most CMP engine implementations. Entity beans have been bashed - and continue to [...]]]></description>
			<content:encoded><![CDATA[<p><P align="justify"><FONT face="Verdana">Entity beans represent an object view of data - usually stored in a relational database. The EJB 2.x specification does not limit the mapping&nbsp;of entity beans to a relational database although an RDBMS remains the most popular choice of supported persistence for most CMP engine implementations.</FONT></P> <P align="justify"><FONT face="Verdana">Entity beans have been bashed - and continue to be bashed -&nbsp;for many reasons. The most common ones being performance (or the lack thereof) and the amount of necessary boiler-plate code&nbsp;to be written. The former is more of an implementation issue -&nbsp;that is, the responsibility of the Container vendor. And the latter is mostly due to the lack of proper tool support for treating EJBs as first class citizens. You can read some rantings&nbsp;concerning the latter at <A href="http://blogs.codegear.com/krish/archive/2004/11/12/1808.aspx">http://blogs.codegear.com/krish/archive/2004/11/12/1808.aspx</A></FONT></P> <P align="justify"><FONT face="Verdana">But a majority of the entity bean bashing is quite naive and by people mostly misinformed about&nbsp;the problem space entity beans attempt to address and when/why they should be used. Many cite performance as a factor. If I were to state that a popular Open Source AppServer provides poor scalability and performance for entity beans, what would the reaction of the community be? Indifference? If I&nbsp;went further&nbsp;to state that for an out-of-the-box comparison (only JVM heap sizes adjusted)&nbsp;of this Open Source product and the Borland Enterprise Server (BES), the latter led by a margin of 20x (2000%) in terms of raw throughput (transactions per second) and 3x (300%) after extensive tuning of both products, would the reaction of the community still be one of indifference? And that a raw-SQL (using DAO from a session bean)&nbsp;version of the benchmark&nbsp;on the&nbsp;Open Source AppServer showed it still lagging behind in performance&nbsp;compared to&nbsp;the entity bean version of the same benchmark running on BES? I might publish the results of that benchmark if I get some response <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </FONT></P> <P align="justify"><FONT face="Verdana">But I digress.</FONT></P> <P align="justify"><FONT face="Verdana">Most CMP 2.0 engines provide support for the following Java types that map to the specified SQL Types (these types are defined in the class <FONT face="Courier New">java.sql.Types</FONT>).</FONT></P> <P align="justify"><FONT face="Courier New">Java Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SQL Type<BR>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<BR>boolean/Boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BIT<BR>byte/Byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TINYINT<BR>char/Character&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CHAR(1)<BR>double/Double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DOUBLE<BR>float/Float&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; REAL<BR>int/Integer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INTEGER<BR>long/Long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BIGINT<BR>short/Short&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SMALLINT<BR>String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARCHAR<BR>java.math.BigDecimal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMERIC<BR>byte[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VARBINARY<BR>java.sql.Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DATE<BR>java.sql.Time&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TIME<BR>java.sql.Timestamp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TIMESTAMP<BR>java.util.Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TIMESTAMP<BR>java.io.Serializable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VARBINARY</FONT></P> <P align="justify"><FONT face="Verdana">In addition to these types, most Containers also provide support for LOBs (Large Objects) such as Oracle CLOBs (Character LOBs) and BLOBs (Binary LOBs). Many Containers also provide support for dependent objects, the fields of which are again are limited to the above listed types. Now assume that I have a type that is not listed or supported by the methods in the&nbsp;generic interfaces in the the java.sql package but rely on specific extensions provided by the database and the JDBC Driver. How do I map those to a CMP field?</FONT></P> <P align="justify"><FONT face="Verdana">Let&#8217;s take a specific example. I was recently at a BES customer here in Europe in the first week of Dec 2004 (the weather there was 17C compared to the almost freezing weather in Amsterdam). I had to work with a team of 5; all of them very intelligent and with a&nbsp;great sense of humour. They were using Oracle 9i and were using an Oracle specific type - <FONT face="Courier New">XMLTYPE</FONT> as one of the columns in the database. This specific type is stored internally as a CLOB, but cannot be accessed directly as a CLOB by the JDBC APIs. To access this field, you would have to use <FONT face="Courier New">oracle.jdbc.OracleResultSet</FONT> specific methods along the following lines:</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; // &#8230;. <BR>&nbsp; oracle.jdbc.OracleResultSet oracleRs = (oracle.jdbc.OracleResultSet) resultSet;<BR>&nbsp;&nbsp;oracle.jdbc.OPAQUE value = oracleRs.getOPAQUE(index);<BR>&nbsp; if (!oracleRs.wasNull()) {<BR>&nbsp;&nbsp;&nbsp; String xmlString = oracle.jdbc.XMLType.createXML(value).getStringVal();<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Verdana">And some similar code to set/modify the value.</FONT></P> <P align="justify"><FONT face="Verdana">The problem of course is that if you were using CMP, what type do you use as the CMP field? And more importantly, how do you map that field to the Oracle <FONT face="Courier New">XMLTYPE</FONT> in the database?</FONT></P> <P align="justify"><FONT face="Verdana">Borland Enterprise Server provides&nbsp;a mechanism to do so. How this work in short is that whenever a particular column type (CMP field) matches some criteria you specify (either the CMP field type or CMP field name or both), the Container can delegate the accessing/mutating of this field to custom methods you implement. In all cases, there will be no code changes involved&nbsp;in the entity bean or its generated code or its persistence manager. BES provides the following abstract interface:</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; package com.borland.ejb.pm;<BR><BR>&nbsp;&nbsp;import java.rmi.RemoteException;<BR><BR>&nbsp; public abstract interface JdbcAccesserFactory {<BR>&nbsp;&nbsp;&nbsp; JdbcGetter getGetter(Class cmpFieldType, String cmpFieldName) throws RemoteException;<BR>&nbsp;&nbsp;&nbsp; JdbcSetter getSetter(Class cmpFieldType, String cmpFieldName) throws RemoteException;<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Verdana">The implementation of this class has to create its implementation of the abstract class <FONT face="Courier New">JdbcGetter</FONT> and <FONT face="Courier New">JdbcSetter</FONT>. The custom implementations of <FONT face="Courier New">JdbcGetter</FONT> and <FONT face="Courier New">JdbcSetter</FONT> have to override methods to get or set the value using specific APIs. Methods in the <FONT face="Courier New">JdbcGetter</FONT> and <FONT face="Courier New">JdbcSetter</FONT> get passed the <FONT face="Courier New">java.sql.PreparedStatement</FONT>, <FONT face="Courier New">java.sql.ResultSet</FONT> and the value of the CMP field as parameters. From these, you can cast them to Oracle specific types and use Oracle JDBC Driver specific methods to get or set the value of the CMP field. To use our implementation of the <FONT face="Courier New">JdbcAccesserFactory</FONT>, an XML entry in the <FONT face="Courier New">ejb-borland.xml</FONT> (Table CMP property) instructs the EJB Container to use our class for accessing the value in the database.</FONT></P> <P align="justify"><FONT face="Verdana">In the case of an <FONT face="Courier New">XMLTYPE</FONT> field in the Oracle database, the first observation might be to&nbsp;map things to a CMP field of type <FONT face="Courier New">java.lang.String</FONT> and then undertake the conversion of this String field to Oracle <FONT face="Courier New">XMLTYPE</FONT> via our custom <FONT face="Courier New">JdbcGetter</FONT> and <FONT face="Courier New">JdbcSetter</FONT> implementations. Mapping directly to a String field is possible, but requires some more code to ensure that other <FONT face="Courier New">java.lang.String</FONT> fields in the <EM>same </EM>entity bean do not get mapped to <FONT face="Courier New">XMLTYPE</FONT> as well. For example, I might have 10 <FONT face="Courier New">java.lang.String</FONT> CMP fields in the same entity bean, of which 9 of them map to an Oracle <FONT face="Courier New">VARCHAR2</FONT> and only one maps to an <FONT face="Courier New">XMLTYPE</FONT>. Then I have to write extra code to ensure that only the<FONT face="Courier New"> java.lang.String</FONT> CMP field that maps to an Oracle <FONT face="Courier New">XMLTYPE</FONT> should be handled by my JdbcAccesserFactory implementation.</FONT></P> <P align="justify"><FONT face="Verdana">To get around these, for simplicity lets assume that I create a custom holder class along the lines of:</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; package com.whatever.data;<BR><BR>&nbsp; public class MyXmlStringHolder implements java.io.Serializable {<BR>&nbsp;&nbsp;&nbsp; private String xmlValue;<BR>&nbsp;&nbsp;&nbsp; public String getXmlValue() { return this.xmlValue; }<BR>&nbsp;&nbsp;&nbsp; public&nbsp;void setXmlValue(String newValue) {this.xmlValue = newValue; }<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Verdana">And the above class is the one I use as my CMP field for the column that has to map to an Oracle <FONT face="Courier New">XMLTYPE</FONT>. So my entity bean would look like:</FONT></P><FONT face="Verdana"> <P><FONT face="Courier New">&nbsp; public abstract class OurEntityBean implements EntityBean {<BR>&nbsp;&nbsp;&nbsp; </FONT><FONT face="Courier New">// skipped some methods &#8230;. <BR>&nbsp;&nbsp;&nbsp; </FONT><FONT face="Courier New">public abstract void setXmlMessage(MyXmlStringHolder sh);<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp; </FONT><FONT face="Courier New">public abstract MyXmlStringHolder getXmlMessage();<BR>&nbsp;&nbsp;&nbsp; </FONT><FONT face="Courier New">// here xmlMessage is a CMP field that maps to some<BR>&nbsp;&nbsp;&nbsp; </FONT><FONT face="Courier New">// Oracle column of XMLTYPE<BR>&nbsp; </FONT><FONT face="Courier New">}</FONT></P></FONT> <P align="justify"><FONT face="Verdana">Now for the custom JdbcAccesserFactory implementation. This would be along the lines of:</FONT></P> <P align="justify"><FONT face="Courier New">package com.borland.ejb.pm.oracle;</FONT></P> <P align="justify"><FONT face="Courier New">import java.rmi.RemoteException;</FONT></P> <P align="justify"><FONT face="Courier New">import java.sql.PreparedStatement;<BR>import java.sql.ResultSet;<BR>import java.sql.SQLException;<BR>import java.sql.Types;</FONT></P> <P align="justify"><FONT face="Courier New">import com.borland.ejb.pm.JdbcAccesserFactory;<BR>import com.borland.ejb.pm.JdbcGetter;<BR>import com.borland.ejb.pm.JdbcSetter;<BR>import com.inprise.visitransact.jdbc2.PreparedStatementProxy;<BR><BR>import com.whatever.data.MyXmlStringHolder;</FONT></P> <P align="justify"><FONT face="Courier New">import oracle.jdbc.OraclePreparedStatement;<BR>import oracle.jdbc.OracleResultSet;<BR>import oracle.sql.OPAQUE;<BR>import oracle.xdb.XMLType;</FONT></P> <P align="justify"><FONT face="Courier New">public class OracleXmlAccesser implements JdbcAccesserFactory {<BR>&nbsp; public OracleXmlAccesser() {<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; public JdbcGetter getGetter(Class fieldType, String fieldName) throws<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RemoteException {<BR>&nbsp;&nbsp;&nbsp; if (fieldType.getName().equals(MyXmlStringHolder.class.getName())) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new XmlJdbcGetter();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; public JdbcSetter getSetter(Class fieldType, String fieldName) throws<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RemoteException {<BR>&nbsp;&nbsp;&nbsp; if (fieldType.getName().equals(MyXmlStringHolder.class.getName())) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new XmlJdbcSetter();<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; return null;<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; private class XmlJdbcGetter extends JdbcGetter {<BR>&nbsp;&nbsp;&nbsp; public Object get(ResultSet rs, int index, ClassLoader cl) throws<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SQLException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyXmlStringHolder ret = new MyXmlStringHolder();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OracleResultSet oracleRs = (OracleResultSet) rs;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OPAQUE value = oracleRs.getOPAQUE(index);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (oracleRs.wasNull()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ret;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret.setXmlValue(XMLType.createXML(value).getStringVal());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ret;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp; private class XmlJdbcSetter extends JdbcSetter {<BR>&nbsp;&nbsp;&nbsp; public void set(PreparedStatement ps, int index, Object object) throws<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SQLException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyXmlStringHolder&nbsp;holder = (MyXmlStringHolder)object<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (holder.getXmlValue() == null) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PreparedStatementProxy proxy = (PreparedStatementProxy) ps;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OraclePreparedStatement ops = (OraclePreparedStatement) proxy.getPreparedStatement();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ops.setNull(index, Types.VARCHAR);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PreparedStatementProxy proxy = (PreparedStatementProxy) ps;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OraclePreparedStatement ops = (OraclePreparedStatement) proxy.getPreparedStatement();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ops.setObject(index, XMLType.createXML(ps.getConnection(), holder.getXmlValue()));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }</FONT></P> <P align="justify"><FONT face="Courier New">&nbsp;&nbsp;&nbsp; public void set(ResultSet rs, PreparedStatement ps, int index, Object object) throws SQLException {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set(ps, index, object);<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp; }</FONT></P> <P align="justify"><FONT face="Courier New">}</FONT><BR></P> <P align="justify"><FONT face="Verdana">And the above class would be packaged as a library and present on the classpath of BES&#8217;s partition or deployed alongwith the EJB Module in a JAR or EAR. For an entity bean to use the above class to map its&nbsp;CMP field(s)&nbsp;to an Oracle <FONT face="Courier New">XMLTYPE</FONT>, you would need an entry in the <FONT face="Courier New">ejb-borland.xml</FONT> descriptor along the lines of:</FONT></P> <P align="justify"><FONT face="Courier New"><!--StartFragment --><FONT face="Times New Roman"></FONT></P> <P align="justify"><FONT face="Courier New"><!--StartFragment --></P> <P align="justify"><FONT face="Courier New">&nbsp; &lt;table-properties&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;table-name&gt;MyOracleTable&lt;/table-name&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;column-properties&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;column-name&gt;MY_XML_COLUMN&lt;/column-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop-name&gt;ignoreOnInsert&lt;/prop-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop-type&gt;java.lang.Boolean&lt;/prop-type&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop-value&gt;true&lt;/prop-value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/column-properties&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;!&#8211; other entries skipped for brevity&nbsp;&#8211;&gt;</FONT><FONT face="Courier New"><BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop-name&gt;jdbcAccesserFactory&lt;/prop-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop-type&gt;java.lang.String&lt;/prop-type&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop-value&gt;com.borland.ejb.pm.oracle.OracleXmlAccesser&lt;/prop-value&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/property&gt;<BR>&nbsp; &lt;/table-properties&gt;</FONT></FONT><FONT face="Courier New">&nbsp; </TABLE></FONT></P></FONT><FONT face="Courier New"></TABLE></FONT> <P align="justify"><FONT face="Verdana">And&nbsp;that&#8217;s about it!</FONT></P> <P align="justify"><FONT face="Verdana">-krish</FONT>&nbsp;</P></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/krish/?p=2238&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_2238" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Extending%20Container%20Managed%20Persistence%20%28CMP%29%20Types&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fkrish%2F2004%2F12%2F22%2F2238" id="akst_email_2238" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/krish/2004/12/22/2238/feed</wfw:commentRss>
		</item>
		<item>
		<title>Concerns on the EJB 3.0 early draft</title>
		<link>http://blogs.embarcadero.com/krish/2004/11/12/1808</link>
		<comments>http://blogs.embarcadero.com/krish/2004/11/12/1808#comments</comments>
		<pubDate>Fri, 12 Nov 2004 00:51:53 +0000</pubDate>
		<dc:creator>Krishnan Subramanian</dc:creator>
		
		<category><![CDATA[Borland Enterprise Server]]></category>

		<category><![CDATA[J2EE]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/krish/2004/11/12/856/</guid>
		<description><![CDATA[I was going through the EJB 3.0 early draft specification - available at: http://java.sun.com/products/ejb/docs.html And one of the things that struck me was that the specification has changed (yet again) with another incompatible conceptual leap. The move from EJB 1.1 to 2.0 was quite a big one and the move now from 2.x to 3.0&#160;will&#160;be&#160;a [...]]]></description>
			<content:encoded><![CDATA[<p><P><FONT face="Verdana">I was going through the EJB 3.0 early draft specification - available at: <A href="http://java.sun.com/products/ejb/docs.html">http://java.sun.com/products/ejb/docs.html</A></FONT></P> <P><FONT face="Verdana">And one of the things that struck me was that the specification has changed (yet again) with another incompatible conceptual leap. The move from EJB 1.1 to 2.0 was quite a big one and the move now from 2.x to 3.0&nbsp;will&nbsp;be&nbsp;a bigger one from a <STRONG><EM>J2EE Application Developer</EM></STRONG> point of view. From an <STRONG><EM>AppServer</EM></STRONG> <EM><STRONG>implementation</STRONG></EM> (<A href="http://www.borland.com/bes/">Borland Enterprise Server</A>, WebLogic, WebSphere etc) point of view, it looks like the move from 1.1 to 2.0 was probably a bigger one than the one from 2.0 to 3.0. Of course, I&#8217;m not R&amp;D and probably am not best qualified to comment.</FONT></P> <P><FONT face="Verdana">However, having worked on numerous J2EE projects prior to joining Borland (~2 years), and working on customer assignments (both as a developer and a glorified trouble shooter the last 3+ years), I think I have seen enough of the good and bad to pass comment on the technology in general and its direction.</FONT></P> <P><FONT face="Verdana">A striking thing about the draft&nbsp;specification is the introduction of fairly experimental technology. Like <A href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html">annotations</A>. There is nothing wrong with annotations, except that most Java developers are not used to annotating their code. For example, a&nbsp;stateful session bean can be&nbsp;specified as:</FONT></P><FONT face="Courier"> <P align="left">@Target(TYPE) @Retention(RUNTIME)<BR>public @interface Stateful {<BR>&nbsp; String name() default "";<BR>&nbsp; TransactionManagementType transactionManagement()<BR>&nbsp; default CONTAINER;<BR>}</P> <P align="left"><FONT face="Verdana">I&#8217;m not convinced that a normal Java/J2EE developer is going to be comfortable annotating his/her code. It will probably take time getting used to (as with anything). My worry is that you normally would not change enterprise programming models to such an extent. This is not what enterprise software is about. XML descriptors are not out, but you could choose a&nbsp;middle path by reducing the number of required elements in the XML descriptors and having the EJB Container infer these/choose defaults based on (non-annotated) code.</FONT></P> <P align="left"><FONT face="Verdana">The draft specification also looks like it is addressing a problem space it does not own. Namely: the lack of proper tools that manipulate EJBs as first-class citizens (components) rather than as disparate pieces (bean class, home interface, remotable/local interface, XML descriptors). This is probably why the specification requires a J2EE Application Developer to declare his bean class alongwith numerous annotations and then at deploy/runtime generate all the artifacts mentioned above (home interface, remotable/local interface, deployment descriptor settings, stubs, skeletons&nbsp;etc). The idea is not a bad one, except that I feel it is not the specification&#8217;s responsibility to do this. <EM>Would you embark on a enterprise scale ASP.NET project and use wordpad/notepad to write all of your code</EM>? <A href="http://www.borland.com/jbuilder/">JBuilder </A>does a pretty good job of abstracting away all the disparate pieces and treating an EJB as a component in its EJB Designer. And you want to use a Java development tool that does <EM>at least</EM> that.</FONT></P> <P align="left"><FONT face="Verdana">The draft specification also does not require a J2EE application developer to explicitly declare an interface as being a remotable one. Everything is a Plain Old Java Object (POJO). In my opinion, a bad idea. Often declaring an interface to be an explicitly remotable one is not necessarily a bad thing. Especially in a medium/large development team where many members may not realize that they&#8217;re manipulating an object reference as a local one when in reality all calls are being dispatched to a remote server. Location over-transparency? Other technologies require you to explicitly declare an interface as being remotable - example: RMI requires it, CORBA requires it, .NET Remoting requires it (afaik), so why move away from common practise?</FONT></P> <P align="left"><FONT face="Verdana">A plain daft goal of the draft specification is: testability outside of the (EJB) Container. What does this mean? If we take a look at the most popular testing framework for Java code out there, it is <A href="http://www.junit.org/index.htm">junit</A>. JUnit is such a basic framework that you start wondering how you&#8217;d test an <EM>enterprise application </EM>outside of a Container that provides all services&nbsp;essential for an <EM>enterprise class application</EM>. Err, I might as well say - I have a database driven application that I want to test without a database.&nbsp; <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </FONT></P> <P align="left"><FONT face="Verdana">In the draft specification, it also seems like an entity bean is a data transfer object (or value object) is an entity bean. There is &#8216;detached&#8217; model and a &#8216;managed&#8217; model for entity beans when they are used by&nbsp;code in a&nbsp;(remote) client and code inside a container respectively. Often, applying basic modeling concepts tell you that you want to reduce coupling. But in this case, we&#8217;re encouraging client applications to access our domain/persistence model directly - albeit in a &#8216;detached&#8217; mode with outstanding changes to be resolved back later (managed mode). I do not like this idea of blurring of lines between what consitutes your persistence object and what consitutes data objects (that are passed between tiers). And would you want to couple your client applications to your domain model?</FONT></P> <P align="left"><FONT face="Verdana">On a related note, entity beans also expose a number of lifecycle methods to the developer. That is, apart from the EJB Container deciding when to read data from the database and when to write data (depending on transaction boundaries), the developer can choose to&nbsp;control these by calling the lifecycle methods explicitly. This might not be a good thing and might even encourage developers to start thinking about lower abstraction levels and mixing them up with business logic abstractions. Well, if we&#8217;re going to think and control many aspects we might as well go all the way and write our own EJB Container in the meantime <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> These might also interfere with the different <A href="http://www.borland.com/products/white_papers/bes_transaction_commit_options.html">transaction commit options </A>and caching decisions that can be specified for entity EJBs (pure deployment descriptor entries and therefore no touching of code required).</FONT></P> <P align="left"><FONT face="Verdana">The draft specification also introduces the notion of Named Queries that can be specified as:</FONT></P><FONT face="Courier"> <P align="left">@NamedQuery(<BR>&nbsp; name="findAllCustomersWithName",<BR>&nbsp; queryString="SELECT c FROM Customer c WHERE c.name LIKE :custName"<BR>)</P> <P align="left"><FONT face="Verdana">Named queries could be problematic since they are declared by name and called by name. There are possibilities of developers mistyping things. And your application blows up at runtime. Oh wait, I want to test my application outside the Container, err umm uhhh!</FONT></P> <P align="left"><FONT face="Verdana">-krish</FONT></P></FONT></FONT></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/krish/?p=1808&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_1808" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Concerns%20on%20the%20EJB%203.0%20early%20draft&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fkrish%2F2004%2F11%2F12%2F1808" id="akst_email_1808" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/krish/2004/11/12/1808/feed</wfw:commentRss>
		</item>
		<item>
		<title>Re: ECO : Optimistic Locking</title>
		<link>http://blogs.embarcadero.com/krish/2004/07/16/855</link>
		<comments>http://blogs.embarcadero.com/krish/2004/07/16/855#comments</comments>
		<pubDate>Fri, 16 Jul 2004 15:12:59 +0000</pubDate>
		<dc:creator>Krishnan Subramanian</dc:creator>
		
		<category><![CDATA[Borland Enterprise Server]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[J2EE]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/krish/2004/07/16/850/</guid>
		<description><![CDATA[First off, this post is in reply to a blog entry by Malcolm Groves at: http://blogs.codegear.com/malcolmgroves/archive/2004/06/28/659.aspx&#160;on Optimistic Locking done by ECO. I first thought of replying on Malcolm&#8217;s&#160;blog site&#160;but then thought&#160;my entry might deserve a place of its own (presumptuous, but not vain  I also come from the Java, J2EE world&#160;- and I have [...]]]></description>
			<content:encoded><![CDATA[<p><P><FONT face="Verdana" size="2">First off, this post is in reply to a blog entry by Malcolm Groves at: </FONT><FONT face="Verdana" size="2"><A href="http://blogs.codegear.com/malcolmgroves/archive/2004/06/28/659.aspx">http://blogs.codegear.com/malcolmgroves/archive/2004/06/28/659.aspx</A>&nbsp;on Optimistic Locking done by ECO.</FONT></P> <P><FONT face="Verdana"><FONT size="2">I first thought of replying on Malcolm&#8217;s&nbsp;blog site&nbsp;but then thought&nbsp;my entry might deserve a place of its own (presumptuous, but not vain <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> I also come from the Java, J2EE world&nbsp;- and I have a deep&nbsp;respect for a lot of technologies in Delphi and Delphi.NET. Some of views on the topic might be bit off since I might not know how things work exactly (only plain ignorance ;). I have to admit that most of these issues have already been thrashed around in the J2EE world and <A href="http://www.borland.com/bes/">Borland Enterprise Server </A>provides a piece of functionality that is almost identical by name - but differing in its implementation. You will find a link to this functionality&nbsp;at the end of this post.</FONT></FONT></P> <P><FONT face="Verdana"><FONT size="2">Malcolm&#8217;s entry&nbsp;stated how Optimistic&nbsp;Locking behaves when set to ModifiedMembers and when set to AllMembers. What caught my attention was that:</FONT></FONT></P> <UL> <LI><FONT face="Verdana"><FONT size="2">Two SQLs are sent to the database for every update to the database.</FONT></FONT> <LI><FONT face="Verdana"><FONT size="2">The&nbsp;isolation&nbsp;level for the above two SQLs themselves are seemingly undefined.</FONT></FONT></LI></UL> <P><FONT face="Verdana"><FONT size="2">Firstly, it seems like sending two SQLs to the database for every update to the database is not a very scalable solution. One,&nbsp;it introduces more RPCs into the picture if the ECO Server-side application and database are on different machines. Two, it imposes a higher load on the database than necessary. That is, there are now more CPU cycles utilized at the database-tier. This could very quickly lead to the database-tier becoming a performance bottleneck which will then ripple up tiers to manifest itself as a scalability problem. This whole issue of two SQLs seems trivial till you actually consider high-concurrency OLTP-like applications where you want squeeze every little bit of performance out of your tiers since you are typically dealing with&nbsp;large amounts of data.</FONT></FONT></P> <P><FONT face="Verdana"><FONT size="+0"><FONT size="2">Secondly, the last point assumes that the two SQLs will run in proper isolation. What I mean by this - is not whether the two SQLs will run in the same transaction (which they must - else ECO is doing something horribly wrong); but what the <A href="http://www.winnetmag.com/SQLServer/Article/ArticleID/5336/5336.html">isolation level </A>will be of that transaction. Off the top of my head - I would say you atleast need a REPEATABLE READ isolation level (most database default to READ COMMITTED in which case you still have a problem). Imagine, under a high concurrency, T1 and T2 are two transactions:</FONT></FONT></FONT></P> <P><FONT face="Verdana"><FONT size="+0"><FONT size="2">&nbsp;&nbsp;&nbsp; T1 performs a SELECT (prior to its UPDATE)<BR>&nbsp;&nbsp;&nbsp; T2 performs a SELECT (prior to its UPDATE)<BR>&nbsp;&nbsp;&nbsp; T1 assumes it can update the database and issues an UPDATE&nbsp;that succeeds<BR>&nbsp;&nbsp;&nbsp; T2 assumes it can also update the database and issues an UPDATE that also succeeds</FONT></FONT></FONT></P> <P><FONT face="Verdana"><FONT size="+0"><FONT size="2">I believe the above will occur if you select (pun intended) the default READ COMMITTED isolation level.</FONT></FONT></FONT></P> <P><FONT face="Verdana"><FONT size="+0"><FONT size="2">So, what is the solution you may well ask? Or more importantly is there a solution?</FONT></FONT></FONT></P> <P><FONT face="Verdana"><FONT size="+0"><FONT size="2">Yes.</FONT></FONT></FONT></P> <P><FONT face="Verdana"><FONT size="+0"><FONT size="2">The idea is to kill two birds with one stone. Or in this, to just use one SQL in lieu of two. And what kind of an SQL would that be? Let&#8217;s see. In ECO, after the first SQL is executed, it checks to see if the value returned by the database is different from those <STRONG><EM>prior </EM></STRONG>to edits/changes. This implies that ECO is holding this old value somewhere - whether it be an OptimisticLocking mode of ModifiedMembers or AllMembers. So, the smart thing for ECO to do would be to use that information in its WHERE clause. Let me give an example in the context of Malcolm&#8217;s example: </FONT></FONT></FONT><FONT face="Verdana"><FONT size="+0"><FONT size="2">Damien and I are working with&nbsp;a Person whose first name happens to be &#8216;Barney&#8217;.</FONT></FONT></FONT></P> <P><FONT face="Verdana" size="2">Damien makes a change to this Person&#8217;s first name and calls&nbsp;him &#8216;Loony&#8217; and while I make a change and decide to call him &#8216;Goony&#8217;. Assuming the problem in point two (above) does not exist, ECO will issue a SELECT when Damien&#8217;s transaction has to succeed. It will find that the database contains &#8216;Barney&#8217; which is what Damien started out with in the first place. His transaction will succeed.</FONT></P> <P><FONT face="Verdana" size="2">My transaction will then issue a SELECT, find that the person&#8217;s first name is now &#8216;Loony&#8217; and not &#8216;Barney&#8217; - which is not what I received in the first place (I received &#8216;Barney&#8217;) and so my transaction will fail. All well - assuming of course that problem in point 2 above does not exist.</FONT></P> <P><FONT face="Verdana" size="2">The other way of doing things - maybe a bit more efficient - is to let ECO do a bit more work. Since ECO &#8216;knows&#8217; its old values - that is, the values it receives when it issued the request to get the data to the user, it cannot be that hard for ECO to &#8216;diff&#8217; these values with what the user had edited/changed. So, ECO should know what columns have <STRONG><EM>actually </EM></STRONG>changed. In this context of this example, it should know that the only change is one to the firstName column. And it also &#8216;<EM>knows</EM>&#8216; what the old value is (Barney) and new value (either Loony | Goony) is. And it could use this information to construct the WHERE clause.</FONT></P> <P><FONT face="Courier New" size="2">&nbsp;&nbsp;&nbsp; UPDATE Person<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET firstName = &#8216;Loony&#8217;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE Person.BOLD_ID = 3&nbsp;<STRONG>AND Person.firstName = &#8216;Barney&#8217;</STRONG></FONT></P> <P><FONT face="Verdana" size="2">And the other transaction would issue:</FONT></P> <P><FONT face="Courier New" size="2">&nbsp;&nbsp;&nbsp; UPDATE Person<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET firstName = &#8216;Goony&#8217;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE Person.BOLD_ID = 3&nbsp;<STRONG>AND Person.firstName = &#8216;Barney&#8217;</STRONG></FONT></P> <P><FONT face="Verdana"><FONT size="2">In this case, only one of the above two transactions will succeed since the WHERE will fail if it cannot find the given row. And in the case of an Optimistic Concurrency of AllFields, the WHERE clause would contain the values of all columns that the user first read in. So something along the lines of:</FONT></FONT></P> <P><FONT face="Courier New" size="2">&nbsp;&nbsp;&nbsp; UPDATE Person<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SET firstName = &#8216;Goony&#8217;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE Person.BOLD_ID = 3&nbsp;<STRONG>AND Person.firstName = &#8216;Barney&#8217; AND Person.lastName = &#8216;Slater&#8217; AND Person.someField = &#8216;oldValue&#8217; &#8230; </STRONG></FONT></P> <P><FONT face="Verdana"><FONT size="2">So, this approach:</FONT></FONT></P> <UL> <LI><FONT face="Verdana"><FONT size="2">Uses only one SQL</FONT></FONT> <LI><FONT face="Verdana"><FONT size="2">Is&nbsp;the &#8216;correct&#8217; way. No &#8216;holes&#8217; to be punched through it.</FONT></FONT></LI></UL> <P><FONT face="Verdana"><FONT size="2">And also does not suffer from any potential scalability problem (side-effect <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </FONT></FONT></P> <P><FONT face="Verdana" size="2">I&#8217;d be interested in hearing other&#8217;s opinions on this . . . </FONT></P> <P><FONT face="Verdana"><FONT size="2">-krish</FONT></FONT></P> <P><FONT face="Verdana"><FONT size="2">Borland Enterprise Server uses the same approach: <A href="http://info.borland.com/devsupport/bes/faq/all_versions/ejb/cmp.html#_how_optimisitic">http://info.borland.com/devsupport/bes/faq/all_versions/ejb/cmp.html#_how_optimisitic</A></FONT><FONT size="+0"></P></FONT></FONT></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/krish/?p=855&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_855" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Re%3A%20ECO%20%3A%20Optimistic%20Locking&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fkrish%2F2004%2F07%2F16%2F855" id="akst_email_855" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/krish/2004/07/16/855/feed</wfw:commentRss>
		</item>
		<item>
		<title>On Logging and logging in J2EE environments (and in Borland Enterprise Server)</title>
		<link>http://blogs.embarcadero.com/krish/2004/07/16/849</link>
		<comments>http://blogs.embarcadero.com/krish/2004/07/16/849#comments</comments>
		<pubDate>Fri, 16 Jul 2004 07:53:19 +0000</pubDate>
		<dc:creator>Krishnan Subramanian</dc:creator>
		
		<category><![CDATA[Borland Enterprise Server]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[J2EE]]></category>

		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/krish/2004/07/16/845/</guid>
		<description><![CDATA[Almost every non-trivial application - be it J2EE or otherwise includes some kind of a logging functionality. More often than not, this functionality tends to be&#160;some home-grown solution. Some might argue that&#160;popular debuggers (such as those provided&#160;with IDEs like JBuilder, Delphi, C#Builder etc)&#160;provide a better means of tracing through code. However, this argument assumes that: [...]]]></description>
			<content:encoded><![CDATA[<p><P><FONT face="Verdana" size="2">Almost every non-trivial application - be it J2EE or otherwise includes some kind of a logging functionality. More often than not, this functionality tends to be&nbsp;some home-grown solution.</FONT></P> <P><FONT face="Verdana" size="2">Some might argue that&nbsp;popular debuggers (such as those provided&nbsp;with IDEs like JBuilder, Delphi, C#Builder etc)&nbsp;provide a better means of tracing through code. However, this argument assumes that:</FONT></P> <UL> <LI><FONT face="Verdana" size="2">Debuggers are always available</FONT> <LI><FONT face="Verdana" size="2">Debuggers can be used in the <EM>context </EM>of the runtime</FONT></LI></UL> <P><FONT face="Verdana" size="2">Logging on other hand:</FONT></P> <UL> <LI><FONT face="Verdana" size="2">Provides information on the context of execution in the runtime</FONT>&nbsp; <LI><FONT face="Verdana" size="2">Is persistent - while debugging sessions are generally transient</FONT> <LI><FONT face="Verdana" size="2">Requires little or no configuration/setup from a user</FONT> <LI><FONT face="Verdana" size="2">Requires no specialized tools (apart from the logger)</FONT> <LI><FONT face="Verdana" size="2">Is&nbsp;more suited to tracing distributed and/or multi-threaded (i.e. high concurrency) applications</FONT></LI></UL> <P><FONT face="Verdana" size="2">This post of mine does not preclude the use of debuggers. Debuggers have their place, and can be an invaluable tool to the programmer during development. Logging can be used during both development as well as deployment. Logging of course provides its own set of challenges:</FONT></P> <UL> <LI><FONT face="Verdana" size="2">Logging statements should be inserted only where appropriate. That is, where they provide information and not nonsensical information that provides little or no value.</FONT> <LI><FONT face="Verdana" size="2">Logging should not be overly verbose. Keep in mind the manner in which the application will be used in a deployment environment. If 100s or 1000s of concurrent users will be using the system and each action by&nbsp;every user generates a lot of logging information, then imagine the amount of information generated.&nbsp;In which case locating&nbsp;useful/relevant information becomes a challenge in itself.</FONT> <LI><FONT face="Verdana" size="2">Logging should be fast. That is, overhead should be minimal.</FONT></LI></UL> <P><FONT face="Verdana" size="2">Till recently, I was content with using <FONT face="Courier New">System.out.println(&#8220; . . . &#8220;) </FONT>and <FONT face="Courier New">System.err.println(&#8220; . . . &#8220;) </FONT>when I had to quickly prototype things or write a proof-of-concept application for a customer.&nbsp;I&nbsp;had heard&nbsp;about <A href="http://logging.apache.org">log4j </A>- a popular open source project from the <A href="http://www.apache.org/">Apache Group</A>&nbsp;- though I had ignored that for a while - but not for long.</FONT></P> <P><FONT face="Verdana" size="2">log4j has three main components:</FONT></P> <UL> <LI><FONT face="Verdana" size="2">Loggers</FONT> <LI><FONT face="Verdana" size="2">Appenders</FONT> <LI><FONT face="Verdana" size="2">Layouts</FONT></LI></UL> <P><FONT face="Verdana" size="2">An application can make use of multiple <EM>loggers</EM> to log information. Each logger can use multiple <EM>appenders </EM>to service a logging request. An <EM>appender </EM>can be thought of as a simple output destination - such as the console, or a file, or a rolling file, or a socket, or an OS event log etc. Each appender can have a <EM>layout </EM>associated with it that controls how the logging request will be formatted. That said, it is not my intention for this post to be a manual on log4j - which this is quickly becoming <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </FONT></P> <P><FONT face="Verdana" size="2">Borland Enterprise Server 6.0 (BES) uses log4j as its own underlying logging system. Now, that both simplifies and complicates things for the J2EE application you deploy in BES. It <EM>complicates </EM>things because:</FONT></P> <UL> <LI><FONT face="Verdana" size="2">log4j is already bundled with BES, and is used internally by BES partitions to log their own information and statistics.</FONT> <LI><FONT face="Verdana" size="2">The classloader scheme in BES will probably mean that the log4j library bundled with BES (under $BES/lib)&nbsp;will take precedence over log4j classes you may bundle with your J2EE JAR/WAR/EAR.</FONT> <LI><FONT face="Verdana" size="2">log4j Loggers you use within your application code will log to the partition&#8217;s rolling log file - which will now contain both BES partition internal information+statistics as well as logging information from your own application. This problem&nbsp;may be alleviated a little bit -&nbsp;since the partition&#8217;s logger uses the <A href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/xml/XMLLayout.html">XMLLayout </A>class to&nbsp;write&nbsp;to a rolling log file. Using the <A href="http://logging.apache.org/log4j/docs/chainsaw.html">chainsaw browser</A>, you can view/filter out information you do not need.</FONT> <LI><FONT face="Verdana" size="2">It assumes you are familiar with log4j</FONT></LI></UL> <P><FONT face="Verdana" size="2">It <EM>simplifies </EM>things because:</FONT></P> <UL><FONT face="Verdana"> <LI><FONT face="Verdana" size="2">log4j is already bundled with BES, and is used internally by BES partitions to log their own information and statistics.&nbsp; <img src='http://blogs.embarcadero.com/krish/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </FONT> <LI><FONT size="2">You can reuse the XML configuration file that is used internally by that partition without starting from scratch.</FONT> <LI><FONT size="2">The above point implies that logging statements from your J2EE Application can be redirected to another Appender. That is, the logging statements can be redirected to another destination (like a separate log file) instead of the one used by the partition.</FONT></LI></UL> <P><FONT size="2">The XML configuration file <FONT face="Courier New">logConfiguration.xml </FONT>used by BES&#8217;s partition lies under <FONT face="Courier New">$BES/var/domains/base/configurations/[configuration_name]/mos/[partition_name]/adm/properties. </FONT><FONT face="Verdana">The above configuration file is set via the JVM property <FONT face="Courier New">log4j.configuration</FONT> in <FONT face="Courier New">$BES/bin/partition.config</FONT> file and used&nbsp;by that&nbsp;partition.</FONT></FONT></P> <P><FONT size="2">This file contains two appenders called <FONT face="Courier New">PRIMARY</FONT> and <FONT face="Courier New">FALLBACK</FONT>. The <FONT face="Courier New">PRIMARY</FONT> Appender is&nbsp;a rolling file appender that appends to the file &nbsp;<FONT face="Courier New">$BES/var/domains/base/configurations/[configuration_name]/mos/[partition_name]/adm/logs/partition_log.xml</FONT></FONT></P> <P><FONT face="Courier New"><FONT face="Verdana" size="2">The partition writes its logging requests to the above file (using the PRIMARY Appender) using an XMLLayout (by default). This also means that with little or no configuration, your J2EE Application code&nbsp;can issue log4j requests to the PRIMARY Appender which will then log that request in an XMLLayout&nbsp;to the <FONT face="Courier New">partition_log.xml </FONT>file.</FONT></FONT></P> <P><FONT face="Courier New"><FONT face="Verdana" size="2">So, the sample code below should work:</FONT></FONT></P> <P><FONT face="Courier New"><FONT size="2"><STRONG><FONT color="#000080">package</FONT></STRONG> com.krish.myapp.j2ee.ejb;<BR><BR></FONT></FONT><FONT face="Courier New"><FONT size="2"><FONT color="#006400">// imports skipped;</FONT><BR><BR><STRONG><FONT color="#000080">public</FONT></STRONG> <STRONG><FONT color="#000080">class</FONT></STRONG> MySessionBean <STRONG><FONT color="#000080">implements</FONT></STRONG> SessionBean {<BR>&nbsp; <STRONG><FONT color="#000080">private </FONT></STRONG>SessionContext <FONT color="#800080">sessionContext</FONT>;<BR>&nbsp; <STRONG><FONT color="#000080">private static final</FONT></STRONG> Logger <EM>logger</EM> = Logger.getLogger(MySessionBean.class);<BR><BR></FONT></FONT><FONT face="Courier New"><FONT size="2">&nbsp; <FONT color="#000080"><STRONG>public void</STRONG></FONT> doSomeWork(String arg1, Integer arg2) {<BR>&nbsp;&nbsp;&nbsp; <EM>logger</EM>.debug(&#8220;In doSomeWork&#8220;);<BR>&nbsp;&nbsp;&nbsp; <STRONG><FONT color="#000080">try</FONT></STRONG> {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT><FONT size="2"><FONT color="#006400">// do whatever it takes<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // to finish the work<BR></FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <EM>logger</EM>.info(&#8220;Transaction succeeded. Transaction Id is: &#8220; + arg2)</FONT></FONT><FONT face="Courier New"><BR><FONT size="2">&nbsp;&nbsp;&nbsp; <STRONG><FONT color="#000080">catch</FONT></STRONG> (Exception ex) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT color="#800080">sessionContext</FONT>.setRollbackOnly();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <EM>logger</EM>.warn(&#8220;Transaction failed. Args passed were: &#8220; + arg1 + &#8220; &#8220; + arg2, ex);<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp; }<BR><BR>&nbsp; <FONT color="#006400">// other EJB callback methods skipped for brevity</FONT><BR>}<BR></FONT></FONT></P> <P><FONT face="Courier New"><FONT face="Verdana" size="2">Of course, the problem now&nbsp;is that the log requests from our EJB now goes into the same <FONT face="Courier New">partition_log.xml</FONT> file that BES&#8217;s partition uses for its own logging requests. If you want the Application&#8217;s log requests to percolate to a different destination, we need to create a new Appender in the <FONT face="Courier New">logConfiguration.xml</FONT> file. Open up this file in your favourite XML Editor and add a new Appender along the lines of:</FONT></FONT></P> <P><FONT face="Courier New" size="2">&nbsp;&nbsp;&nbsp; &lt;<STRONG><FONT color="#000080"><EM>appender</EM></FONT></STRONG> name="<STRONG><EM><FONT color="#a52a2a">APPLICATION</FONT></EM></STRONG>" class="org.apache.log4j.RollingFileAppender"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">errorHandler </FONT></EM></STRONG>class="org.apache.log4j.varia.FallbackErrorHandler"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<FONT color="#000080"><EM><STRONG>root-ref</STRONG></EM></FONT><FONT color="#000000">/</FONT>&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">appender-ref</FONT></EM></STRONG> ref="FALLBACK"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<EM><FONT color="#000080"><STRONG>errorHandler</STRONG></FONT></EM></STRONG>&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="Threshold" value="ALL"/&gt;<!-- levels this appender emits --><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="File" value="<STRONG><EM><FONT color="#a52a2a">adm/logs/application_log.xml</FONT></EM></STRONG>"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="Append" value="true"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="ImmediateFlush" value="true"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="BufferedIO" value="false"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="BufferSize" value="8192"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="MaxBackupIndex" value="9"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="MaxFileSize" value="5MB"/&gt;<!--  --><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">layout </FONT></EM></STRONG>class="org.apache.log4j.xml.XMLLayout"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">param</FONT></EM></STRONG> name="locationInfo" value="false"/&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<EM><FONT color="#000080"><STRONG>layout</STRONG></FONT></EM></STRONG>&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;<EM><FONT color="#000080"><STRONG>appender</STRONG></FONT></EM></STRONG>&gt;<BR><BR>&nbsp;&nbsp;&nbsp; &lt;<STRONG><EM><FONT color="#000080">category </FONT></EM></STRONG>name="<STRONG><EM><FONT color="#a52a2a">com.krish</FONT></EM></STRONG>" additivity="<STRONG><EM><FONT color="#000080">false</FONT></EM></STRONG>"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;<STRONG><FONT color="#000080"><EM>priority</EM></FONT></STRONG> value="<STRONG><EM><FONT color="#a52a2a">info</FONT></EM></STRONG>" /&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<FONT color="#000080"><STRONG><EM>appender-ref </EM></STRONG></FONT>ref="<STRONG><EM><FONT color="#a52a2a">APPLICATION</FONT></EM></STRONG>" /&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;<EM><FONT color="#000080"><STRONG>category</STRONG></FONT></EM></STRONG>&gt;</FONT></P> <P><FONT size="2">The above entry create a new Appender called <STRONG><EM><FONT color="#a52a2a">APPLICATION</FONT></EM></STRONG> that is utilized by all Loggers that inherit from &#8220;<FONT face="Courier New">com.krish</FONT>&#8221; such as the Logger in our EJB whose name is &#8220;<FONT face="Courier New">com.krish.myapp.j2ee.ejb.MySessionBean</FONT>&#8221;. The <FONT color="#a52a2a"><STRONG><EM>APPLICATION</EM></STRONG> </FONT>Appender appends all log requests to a new file called &#8220;<FONT face="Courier New">application_log.xml</FONT>&#8220; that is created in the same directory as the partition&#8217;s log file. </FONT></P> <P><FONT size="2">Remember that log4j loggers automatically inherit settings from their parent loggers, else they inherit settings from the root logger. Also note the use of the <STRONG><FONT face="Courier New" color="#000080"><EM>additivity</EM></FONT></STRONG> attribute value of <STRONG><FONT face="Courier New" color="#000080"><EM>false</EM></FONT></STRONG> for the <STRONG><EM><FONT color="#000080">category</FONT></EM></STRONG> element. If this is not set, <STRONG><EM><FONT color="#000080">additivity </FONT></EM></STRONG>defaults to <STRONG><EM><FONT color="#000080">true</FONT></EM></STRONG>, in which case the log statements you issue from your J2EE Application will flow to two&nbsp;different Appenders: the <STRONG><EM><FONT color="#a52a2a">PRIMARY</FONT></EM></STRONG> and the <STRONG><EM><FONT color="#a52a2a">APPLICATION</FONT></EM></STRONG>. In other words, the logging requests will appear in both the <FONT face="Courier New">partition_log.xml</FONT> file as well as the <FONT face="Courier New">application_log.xml</FONT> file. This would be a waste of resources and remember that our intention is minimize logging overhead.</FONT></P> <P><FONT size="2">Note that the <STRONG><EM><FONT color="#000080">category</FONT></EM></STRONG> element also defines a <STRONG><EM><FONT color="#000080">priority</FONT></EM></STRONG> value <STRONG><FONT color="#000080"><EM>info</EM></FONT></STRONG>. That is, only requests with a priority <FONT face="Courier New">INFO</FONT> or higher will be logged. In other words, <FONT face="Courier New">DEBUG</FONT> levels will be ignored.</FONT></P> <P><FONT size="2">log4j&#8217;s overhead is minimal, and the logging request itself determines if the request should actually be sent to the Appender(s). For example, if&nbsp;the <FONT face="Courier New">logger.debug(&#8220; . . . &#8220;)</FONT>&nbsp;call were issued and the XML Configuration file allowed only <FONT face="Courier New">INFO</FONT> and higher levels, the overhead of the call to the <FONT face="Courier New">logger.debug</FONT> statement is minimal. However, this does not eliminate&nbsp;the overhead of&nbsp;parameter construction. For example:</FONT></P> <P><FONT face="Courier New"><FONT size="2"><STRONG><FONT color="#000080">public void</FONT></STRONG> doSomething(String arg1, java.sql.Connection conn) {<BR>&nbsp; <EM>logger</EM>.debug(&#8220;<FONT color="#a52a2a">doSomething called with argument: </FONT>&#8220; + arg1 + &#8220; <FONT color="#a52a2a">and using JDBC connection:</FONT> &#8220; + conn.toString());<BR>}</FONT></FONT></P> <P><FONT size="2">Here, the JVM will have to construct the result of: </FONT></P> <P><FONT size="2">&nbsp;&nbsp;&nbsp; <FONT face="Courier New">&#8220;<FONT color="#a52a2a">doSomething called with argument: </FONT>&#8220; + arg1 + &#8220; <FONT color="#a52a2a">and using JDBC connection:</FONT> &#8220; + conn.toString()</FONT></FONT></P> <P><FONT size="2">prior to invoking the <FONT face="Courier New">logger.debug() </FONT>method. In JDK 1.4.2_04 (b05), the byte code generated looks like:</FONT></P> <P><FONT face="Courier New" size="2">&nbsp;&nbsp;&nbsp; 3:&nbsp;&nbsp; new&nbsp;&nbsp;&nbsp;&nbsp; #10; //class StringBuffer<BR>&nbsp;&nbsp;&nbsp; 6:&nbsp;&nbsp; dup<BR>&nbsp;&nbsp;&nbsp; 7:&nbsp;&nbsp; invokespecial&nbsp;&nbsp; #11; //Method java/lang/StringBuffer."":()V<BR>&nbsp;&nbsp;&nbsp; 10:&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #16; //String doSomething called with argument:<BR>&nbsp;&nbsp;&nbsp; 12:&nbsp; invokevirtual&nbsp;&nbsp; #13; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;<BR>&nbsp;&nbsp;&nbsp; 15:&nbsp; aload_1<BR>&nbsp;&nbsp;&nbsp; 16:&nbsp; invokevirtual&nbsp;&nbsp; #13; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;<BR>&nbsp;&nbsp;&nbsp; 19:&nbsp; ldc&nbsp;&nbsp;&nbsp;&nbsp; #17; //String&nbsp; and using JDBC connection:<BR>&nbsp;&nbsp;&nbsp; 21:&nbsp; invokevirtual&nbsp;&nbsp; #13; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;<BR>&nbsp;&nbsp;&nbsp; 24:&nbsp; aload_0<BR>&nbsp;&nbsp;&nbsp; 25:&nbsp; getfield&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #7; //Field conn:Ljava/sql/Connection;<BR>&nbsp;&nbsp;&nbsp; 28:&nbsp; invokevirtual&nbsp;&nbsp; #18; //Method java/lang/Object.toString:()Ljava/lang/String;<BR>&nbsp;&nbsp;&nbsp; 31:&nbsp; invokevirtual&nbsp;&nbsp; #13; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;<BR>&nbsp;&nbsp;&nbsp; 34:&nbsp; invokevirtual&nbsp;&nbsp; #14; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;</FONT></P> <P><FONT size="2">which is some processing overhead due to the construction of a <FONT face="Courier New">StringBuffer</FONT> and multiple calls to the <FONT face="Courier New">StringBuffer.append</FONT> method before returning the value via a call to the&nbsp;<FONT face="Courier New">StringBuffer.toString </FONT>method. In addition, there is an overhead of synchronization (monitor enter/monitor exit) since all&nbsp;the <FONT face="Courier New">append </FONT>methods in the <FONT face="Courier New">StringBuffer</FONT> class are <FONT face="Courier New">synchronized</FONT>.&nbsp;This overhead&nbsp;can be eliminated - if debugging is disabled - via a call to <FONT face="Courier New">logger.isDebugEnabled()</FONT> prior to the call to the <FONT face="Courier New">logger.debug()</FONT></FONT></P> <P><FONT size="2">So, a slightly more optimal logging code might read:</FONT></P> <P><FONT face="Courier New" size="2">&nbsp;&nbsp;<STRONG><FONT color="#000080">public void</FONT></STRONG> doSomeWork(String arg1, java.sql.Connection conn) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (<EM>logger</EM>.isDebugEnabled()) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<EM>logger</EM>.debug(&#8220;<FONT color="#a52a2a">doSomething called with argument: </FONT>&#8220; + arg1 + &#8220; <FONT color="#a52a2a">and using JDBC connection:</FONT> &#8220; + conn.toString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}</FONT></P> <P><FONT size="2">If there are any opinions, feel free to share them with me.</FONT></FONT></P></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/krish/?p=849&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_849" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=On%20Logging%20and%20logging%20in%20J2EE%20environments%20%28and%20in%20Borland%20Enterprise%20Server%29&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fkrish%2F2004%2F07%2F16%2F849" id="akst_email_849" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/krish/2004/07/16/849/feed</wfw:commentRss>
		</item>
		<item>
		<title>Brief Introduction</title>
		<link>http://blogs.embarcadero.com/krish/2004/07/16/844</link>
		<comments>http://blogs.embarcadero.com/krish/2004/07/16/844#comments</comments>
		<pubDate>Fri, 16 Jul 2004 03:39:16 +0000</pubDate>
		<dc:creator>Krishnan Subramanian</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/krish/2004/07/16/1/</guid>
		<description><![CDATA[I&#8217;m Krishnan - a consultant with Borland specializing in Java and J2EE. I joined Borland in mid-2001 and am based in Amsterdam, The Netherlands. My job involves a fair bit of travel - primarily in Europe and an occassional foray into the Middle-East where I help Borland customers, partners and sales teams on technical issues. [...]]]></description>
			<content:encoded><![CDATA[<p><P><FONT size="2"><FONT face="Verdana">I&#8217;m Krishnan -</FONT> <FONT face="Verdana">a consultant with Borland specializing in Java and J2EE. I joined Borland in mid-2001 and am based in Amsterdam, The Netherlands.</FONT></FONT></P> <P><FONT face="Verdana" size="2">My job involves a fair bit of travel - primarily in Europe and an occassional foray into the Middle-East where I help Borland customers, partners and sales teams on technical issues. My work in Borland is a mix&nbsp;- ranging from providing educational and consulting services to delivering presentations, speaking at conferences&nbsp;and authoring technical papers.</FONT></P> <P><FONT face="Verdana" size="2">The opinions expressed in the blog are mine and mine alone.</FONT></P> <P><FONT face="Verdana"></FONT>&nbsp;</P></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/krish/?p=844&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_844" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Brief%20Introduction&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fkrish%2F2004%2F07%2F16%2F844" id="akst_email_844" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/krish/2004/07/16/844/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
