<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8396383771129062296</id><updated>2012-02-16T07:45:18.891-06:00</updated><category term='A DB Observer in your J2EE App'/><category term='Logging'/><category term='Performance'/><category term='Heap Management'/><category term='Class Loading'/><category term='HTTP Sessions'/><category term='Connection Pool Settings'/><category term='Availability'/><category term='Java I/O'/><category term='DB Design'/><category term='Clearcase'/><title type='text'>Practical Java/J2EE Software Architecture</title><subtitle type='html'>This is intended to share my experiences of joining B2B J2EE application projects in their mid-life --  -- and doing what I can/could to improve their stability and performance as well as making major ongoing enhancements to it.

I am going to try and keep my posts to material that is not easily found on the internet.  

I intend to respond to comments/questions. So feel free to post them.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-358523528289444745</id><published>2010-03-13T08:30:00.000-06:00</published><updated>2010-03-13T08:31:32.367-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Clearcase'/><title type='text'>Saving checked out clear case files.</title><content type='html'>Do you use Clearcase for source code control?   If so, you likely have a lot of work in your snapshot view that is not backed up.  So, if your hard drive fails or your PC is stolen, you would lose a lot of work.&lt;br /&gt;&lt;br /&gt;Here is a little script for Windows that I run at the end of each day that will copy all checked-out files to a location of your choice.&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;c:&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cd &lt;/span&gt;&lt;/span&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;span style="font-size: small;"&gt;snapshotViewFolder&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; del networkLocation&lt;/span&gt;&lt;/span&gt;&lt;network location=""&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;\*.*&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; FOR /F "usebackQ" %%i in (`cleartool lsc -short -cview -me -r`) do copy %%i "networkLocation&lt;/span&gt;&lt;/span&gt;&lt;network location=""&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;create a &lt;filename&gt;.bat file with these commands. then run it.  all files checked out in the folder = snapshotViewFolder &lt;folder of="" snapshot="" view=""&gt; will be copied to networkLocation.&amp;nbsp; &lt;network location=""&gt;&lt;br /&gt;&lt;br /&gt;In practice, I put this batch file in c:\windows\system32, and  append the following command at the end of it.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;shutdown -s -t 10&lt;/span&gt;&lt;br /&gt;&lt;/network&gt;&lt;/folder&gt;&lt;/filename&gt;&lt;/network&gt;&lt;/network&gt;&lt;/folder&gt;&lt;br /&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;network location=""&gt;&lt;filename&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;br /&gt;&lt;/network&gt;&lt;/folder&gt;&lt;/filename&gt;&lt;/network&gt;&lt;/network&gt;&lt;/folder&gt;&lt;br /&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;network location=""&gt;&lt;filename&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;then, at the end of the day, I just run the batch file from the run-command window.&lt;/network&gt;&lt;/folder&gt;&lt;/filename&gt;&lt;/network&gt;&lt;/network&gt;&lt;/folder&gt;&lt;br /&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;network location=""&gt;&lt;filename&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;br /&gt;&lt;/network&gt;&lt;/folder&gt;&lt;/filename&gt;&lt;/network&gt;&lt;/network&gt;&lt;/folder&gt;&lt;br /&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;network location=""&gt;&lt;filename&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;If you want to run the FOR command directly from the command line, replace each %% with just one %.&lt;/network&gt;&lt;/folder&gt;&lt;/filename&gt;&lt;/network&gt;&lt;/network&gt;&lt;/folder&gt;&lt;br /&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;network location=""&gt;&lt;filename&gt;&lt;folder of="" snapshot="" view=""&gt;&lt;network location=""&gt;&lt;br /&gt;&lt;/network&gt;&lt;/folder&gt;&lt;/filename&gt;&lt;/network&gt;&lt;/network&gt;&lt;/folder&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-358523528289444745?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/358523528289444745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2010/03/saving-checked-out-clear-case-files.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/358523528289444745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/358523528289444745'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2010/03/saving-checked-out-clear-case-files.html' title='Saving checked out clear case files.'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-6863424321445206437</id><published>2009-12-10T22:39:00.000-06:00</published><updated>2009-12-10T22:39:22.188-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Availability'/><title type='text'>Protecting your Application from other Applications</title><content type='html'>Scenario: While servicing a HTTP request, you call an external Application via a plain old HTTP Post of an XML String.&lt;br /&gt;&lt;br /&gt;During testing etc. everything goes swimmingly.  However in production, this other service gets super slow -- and worse yet, hangs -- so -- in effect the Thread servicing your HTTP request is hung.  Your end users' browsers are just spinning away.  They happen to be a persistent bunch, they close their browser and retry again and again -- until your server simply ups and dies :(&lt;br /&gt;&lt;br /&gt;You'll probably agree that is not a good scenario. Particularly in today's world with its emphasis on availability.&lt;br /&gt;&lt;br /&gt;(Question: What is the timeout in IE before it times out? Answer at the end of the post.)&lt;br /&gt;&lt;br /&gt;You can/should take precaution against this scenario.  First, investigate the possibility of setting a timeout on your HTTP Post.  If you are using java.net.HttpURLConnection you can set timeouts in Java 1.5 and on. &lt;br /&gt;&lt;br /&gt;Second -- consider limiting the number of threads engaged at any one time in this activity.  Here is the outline of a simple technique to do this --Assuming you are using the same multi-threaded instance to do your service call.  Again, this is not meant to be working code:&lt;br /&gt;&lt;br /&gt;public class ServiceImpl {&lt;br /&gt;    ConcurrentHashMap map = new ConcurrentHashMap();&lt;br /&gt;  &lt;br /&gt;    public String send(....) {&lt;br /&gt;    if (map.size() &gt; 25) throw new RuntimeException("Max Threads exceeded");&lt;br /&gt;    try {&lt;br /&gt;        map.put(Thread.currentThread(),start);&lt;br /&gt;        ... call service..&lt;br /&gt;        return response;&lt;br /&gt;        } &lt;br /&gt;    finally {&lt;br /&gt;        map.remove(Thread.currentThread());&lt;br /&gt;        }              &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;In practice you could also keep counts on the number of times the service was called, threw an exception etc. and use a restricted jsp to examine these values etc.  If you 'practice' AOP, this would be a a great application of it.&lt;br /&gt;&lt;br /&gt;If you are wondering how to arrive at the max number of threads to allow for a specific service -- ask this question -- what is the maximum percentage of total threads am I willing to dedicate to this part of my application? If the max number of threads in your container is configured at say 500 and your answer is 5%, then this number would be 25.  In practice you would make this value configurable.&lt;br /&gt;&lt;br /&gt;I actually implemented some counters in the above algorithm, including a 'max concurrent request' counter -- so I did get an idea of what the number could be for a specific back-end service call.&lt;br /&gt;&lt;br /&gt;(Answer to the question posed earlier -- Five Minutes)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-6863424321445206437?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/6863424321445206437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/12/protecting-your-application-from-other.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6863424321445206437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6863424321445206437'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/12/protecting-your-application-from-other.html' title='Protecting your Application from other Applications'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-3942835421183585886</id><published>2009-12-10T21:04:00.000-06:00</published><updated>2009-12-12T17:22:46.904-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Low priority high volume database writes killing you?</title><content type='html'>Scenario: Your application has some very high volume -- and perhaps large -- writes to the database that are low priority.  A perfect example would be a log that contains a CLOB.&lt;br /&gt;&lt;br /&gt;Perhaps this is clogging up your database manager to the point it is affecting the performance of your app itself.   Your instinct would be to perhaps defer the write of these log records to a background app perhaps via a JMS queue. &lt;br /&gt;&lt;br /&gt;However, Oracle 10g+ has a most excellent feature that lets you implement similar functionality just by modifying your 'COMMIT' statement at the end of your insert.&lt;br /&gt;&lt;br /&gt;Instead of doing a 'COMMIT', you do a 'COMMIT WRITE BATCH NOWAIT'.  BATCH grants the database manager the permission to batch up the writes and write them out at its convenience -- and the NOWAIT instructs to return control to your app immediately.   So, by adding just a few words to your 'COMMIT', you would have effectually implemented a queuing solution!&lt;br /&gt;&lt;br /&gt;However, nothing is ever that simple.  java.sql.Connection().commit(); is not going to accomplish this. You would have to do something like:&lt;br /&gt;&lt;br /&gt;Connection c = DataSource.getConnection();&lt;br /&gt;c.setAutocommit(false);&lt;br /&gt;...prepare statement, insert, close prepared statement;&lt;br /&gt;Statement s = java.Sql.Connection.createStatement();&lt;br /&gt;s.execute("COMMIT WRITE BATCH NOWAIT");&lt;br /&gt;s.close();&lt;br /&gt;c.close();&lt;br /&gt;&lt;br /&gt;Just double check to see if perhaps your DBA changed the system wide parameter COMMIT_WRITE .  Its default is 'IMMEDIATE,WAIT'.  Leave it that way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-3942835421183585886?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/3942835421183585886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/12/low-priority-high-volume-database.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3942835421183585886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3942835421183585886'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/12/low-priority-high-volume-database.html' title='Low priority high volume database writes killing you?'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-3413805932462285737</id><published>2009-12-10T20:40:00.000-06:00</published><updated>2009-12-12T17:24:02.595-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='A DB Observer in your J2EE App'/><title type='text'>A db trigger that executes java code inside your J2EE app</title><content type='html'>Yes, this is possible, at least in Oracle Enterprise Edition.&lt;br /&gt;&lt;br /&gt;Do you need to take some action each time a database record is inserted/updated. The answer is Triggers of course, but then you are locked into either SQL or a Java Stored Proc -- with their attendant deployment issues.  These may not solve your problem if you have to communicate with your JVM, say, to update a cache you are maintaining in your heap.&lt;br /&gt;&lt;br /&gt;Ideally, you'd just like some code in your J2EE code to be executed.  This gives you the ability to leverage your software infrastructure (code reuse) and not really limit you in what can or cannot be done.&lt;br /&gt;&lt;br /&gt;Oracle has this very nice feature called Advanced Queueing.  You can simply configure a JMS queue on your Oracle server -- no JVM necessary.  Then you can write a trigger to put -- say the primary key of the record that was inserted/updated onto it.&lt;br /&gt;&lt;br /&gt;Then within your J2EE code, you can simply service this queue like any other JMS queue.  This has the added advantage of you being able to have multiple (clustered) receivers on the queue. Other Enterprise Integration patterns, such as selective receivers etc. are also supported.&lt;br /&gt;&lt;br /&gt;Oracle does seem to live in its own world -- so I could not find a lot of documentation on this to implement in a non-Oracle App Server like Websphere.  I don't think that you can configure such a queue on Websphere and use a Message Driven Bean.. you have to service this queue directly within your J2EE code base, perhaps via a Quartz job.&lt;br /&gt;&lt;br /&gt;The steps you have to do are:&lt;br /&gt;&lt;br /&gt;Start a background job via Quartz, then within it get a standard connection to the database.  It has to be an Oracle Connection, not the WSJdbcConnection you would get via a DataSource.getConnection().  I later found out that you could use WSJdbcUtil.getNativeConnection((WSJdbcConnection)DataSource.getConnection()); to get this, but too late to implement in production, so I cannot vouch for it.&lt;br /&gt;&lt;br /&gt;Then AQjmsQueueConnectionFactory.createQueueConnection(connection); will get you a JMS queueConnection.&lt;br /&gt;&lt;br /&gt;There is more to this -- your DBA will provide you with the Java Object that the message is going to be packaged in. But, from here on it is not that different from servicing any other JMS queue.&lt;br /&gt;&lt;br /&gt;I did implement this for a intensive mission critical application and it worked quite well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-3413805932462285737?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/3413805932462285737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/12/db-trigger-that-executes-java-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3413805932462285737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3413805932462285737'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/12/db-trigger-that-executes-java-code.html' title='A db trigger that executes java code inside your J2EE app'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-3777145300377601159</id><published>2009-12-09T20:56:00.000-06:00</published><updated>2009-12-12T17:23:12.689-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DB Design'/><title type='text'>Storing dates/timestamps in the database</title><content type='html'>One principle I like to follow is to have the database stand on its own as much as possible.  So, if you use the standard date or even timestamp in Oracle at least, you have no means to tell what the time zone for it.  &lt;br /&gt;&lt;br /&gt;One would think that if you used the Oracle Date with Timestamp datatype, it would resolve your problem.  However, jdbc (unless I missed something) does not recognize the timezone in this field.  It is simply ignored. And, all times are assumed to be in the time zone of the JVM.  &lt;br /&gt;&lt;br /&gt;At least in one project I was involved with, I saw code where the programmer had misunderstood how it all works and introduced a bug where the time when it was read in was two hours earlier than the time that was written out.&lt;br /&gt;&lt;br /&gt;If you have multiple app servers in different time zones updating the database, this would be a real issue.  Ideally of course, your code/database should be independent of the timezone of the JVM.&lt;br /&gt;&lt;br /&gt;As you can imagine, archiving the data or feeding it to secondary systems would be more problematic if one had to guess at or otherwise determine the timezone of the field.&lt;br /&gt;&lt;br /&gt;I have two solutions to this problem.  One is a little more cumbersome than the other -- but a little more database browsing friendly.&lt;br /&gt;&lt;br /&gt;First you need to understand java.util.Calendar.  My understanding of it is that the core value of this object is the time in milliseconds since the epoch in GMT.  This is a cardinal value -- it is completely unaffected by the time zone of the JVM etc.&lt;br /&gt;&lt;br /&gt;And java.util.Calendar is very sophisticated.  It knows all the time zones in the world, but even more impressively knows whether or when daylight savings is observed in that time zone, further -- it also knows if and when the dates of the switchovers were changed.&lt;br /&gt;&lt;br /&gt;So, once you have the cardinal value from the database, you can create a new java.util.Calendar object, setTimeInMillis(thatValue), and you are in business. Say you want to display the time in Central.  You set the timezone of the Calendar object by something like setTimeZone(new TimeZone("America/Chicago")); and now you can display it using either SimpleDateFormat or FastDateFormat, using a formatter like "MM/dd/yyyy HH:mm:ss Z" -- and can rest assured that the correct time zone for that specific date will be displayed -- CDT or CST.&lt;br /&gt;&lt;br /&gt;In summary:&lt;br /&gt;&lt;br /&gt;Store the time in the database as a long integer -- from java.util.Calendar.getTimeInMillis().  Then when you read it back:&lt;br /&gt;&lt;br /&gt;Calendar cal = Calendar.createInstance();&lt;br /&gt;cal.setTimeInMillis(rs.getLong("fieldName");&lt;br /&gt;&lt;br /&gt;Now, if and when you want to display this -- I think you should always show the timezone -- and you should pick one and not let it default to the timezone of the JVM.&lt;br /&gt;&lt;br /&gt;so, then&lt;br /&gt;&lt;br /&gt;TimeZone tz = TimeZone.getTimeZone("America/Chicago");&lt;br /&gt;cal.setTimeZone(tz);&lt;br /&gt;org.apache.commons.lang.time.FastDateFormat fdf = FastDateFormat.getInstance("MM/dd/yyyy hh:mm a z",Locale.US);&lt;br /&gt;String displayValue = fdf.format(cal);&lt;br /&gt;&lt;br /&gt;One drawback of this scheme is that you don't know the timezone of the original timezone.  If you needed to know it for some reason, you could store it in a separate field.  I recommend a GMT-HH:MM format, as not all timezones translate easily to something like "America/Chicago";&lt;br /&gt;&lt;br /&gt;The second option is a little more complex.  You can use the Oracle DATETIME with TIMEZONE data type.  But now you cannot use the standard java.sql.PreparedStatement.setDate(java.sql.Date) or java.sql.ResultSet.getDate() functions.&lt;br /&gt;&lt;br /&gt;Instead you would need to do something like this:&lt;br /&gt;&lt;br /&gt;Update tablename set fieldName = TO_TIMESTAMP(?,"YYYY-MM-DD HH24:MI:SS.FF TZR") where primaryKeyFieldName = ?&lt;br /&gt;&lt;br /&gt;you'd prepare a statement with the above string then:&lt;br /&gt;FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss:SSS Z");&lt;br /&gt;ps.setString(1, fdf.format(cal));&lt;br /&gt;ps.setString(2, keyValue);&lt;br /&gt;ps.executeUpdate();&lt;br /&gt;&lt;br /&gt;When reading it, you'd do the reverse:&lt;br /&gt;&lt;br /&gt;select to_char(fieldname,"YYYY-MM-DD HH24:MI:SS.FF TZR") from tableName where keyFieldName = keyValue;&lt;br /&gt;&lt;br /&gt;then String charValue = rs.getString(1);&lt;br /&gt;Calendar cal = Calendar.getInstance();&lt;br /&gt;SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS Z");&lt;br /&gt;java.util.Date date = sdf.parse(charValue);&lt;br /&gt;cal.setTime(date);&lt;br /&gt;&lt;br /&gt;The nice part of this technique is that the database contains the relevant information in one field and it is easy to read.&lt;br /&gt;&lt;br /&gt;This is not meant to be working code--I've typed this mostly from memory. But should give you enough information to use the technique in your code.  Note that SimpleDateFormat.parse() is not threadsafe. It would need further refinement if i18n.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-3777145300377601159?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/3777145300377601159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/12/storing-datestimestamps-in-database.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3777145300377601159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3777145300377601159'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/12/storing-datestimestamps-in-database.html' title='Storing dates/timestamps in the database'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-7441265181638119375</id><published>2009-12-04T19:53:00.000-06:00</published><updated>2009-12-05T10:00:44.738-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java I/O'/><title type='text'>Character Set Encoding Issues.</title><content type='html'>Character Set encoding can become an issue in some scenarios.  Migrating an App from one OS to another with different default character set encoding would need some examining.&lt;br /&gt;&lt;br /&gt;Developing/Compiling on an OS with a different encoding than the one you are running your app on would be another.&lt;br /&gt;&lt;br /&gt;This should be a consideration anytime you are communicating with an OS with a different character set encoding. Either if you are receiving files, or perhaps communicating via a message queue or just HTTP.&lt;br /&gt;&lt;br /&gt;The default character set encoding on common OSs (Windows, AIX, Linux) may be different but they are mostly compatible and most likely this doesn't lead to issues.&lt;br /&gt;&lt;br /&gt;This is a red flag for me. Anytime I see the potential for subtle and hard to recreate issues -- I like to be proactive in making sure they do not occur to begin with.&lt;br /&gt;&lt;br /&gt;To specify the character set encoding in Java -- wrap the java.io.InputStream with java.io.InputStreamReader.   &lt;br /&gt;&lt;br /&gt;Charset cs = Charset.forName("ISO-8859-1");&lt;br /&gt;InputStreamReader reader = new InputStreamReader(inputStream,cs);&lt;br /&gt;&lt;br /&gt;e.g. if you are reading a file: -- inputStream would be:&lt;br /&gt;&lt;br /&gt;InputStream inputStream = new FileInputStream(fileName);&lt;br /&gt;&lt;br /&gt;In practice you would probably have the file encoding somehow configurable, so if the source system for your file changes, you could just make a config change and not have to make a coding change.&lt;br /&gt;&lt;br /&gt;----------------------&lt;br /&gt;&lt;br /&gt;If developing on one system and deploying on another with a different character set encoding -- you will need to learn up on Java's handling of character set encoding.  There is easily found and good information on this on the internet.  The point of this post is to simply alert you that this is/could be an issue.&lt;br /&gt;&lt;br /&gt;My instinct would be to compile/build on the target system and specify the character set encoding of the source files to the javac compiler.&lt;br /&gt;&lt;br /&gt;The issue isn't so much with the compiled code itself, but with String constants and the like.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-7441265181638119375?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/7441265181638119375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/12/character-set-encoding-issues.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7441265181638119375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7441265181638119375'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/12/character-set-encoding-issues.html' title='Character Set Encoding Issues.'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-7086746015900468276</id><published>2009-11-29T20:42:00.000-06:00</published><updated>2009-12-05T10:00:58.958-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java I/O'/><title type='text'>A  java I/o anti-pattern</title><content type='html'>A server (Websphere AS) crashed with an 'Out of Memory' error.  Asked to investigate it I somehow came to this piece of code..(I think it was either or both the heap and thread dumps).&lt;br /&gt;&lt;br /&gt;HttpURLConnection conn = new URL("some url").openConnection();&lt;br /&gt;.. post some data to conn.. then..&lt;br /&gt;StringBuffer sb = new StringBuffer();&lt;br /&gt;InputStream is = conn.getInputStream();&lt;br /&gt;while (true) {&lt;br /&gt;int i = is.read();&lt;br /&gt;if (i == -1) break;&lt;br /&gt;sb.append(i);&lt;br /&gt;}&lt;br /&gt;clean up etc..&lt;br /&gt;&lt;br /&gt;I saw two problems with this code:&lt;br /&gt;1) If the system we were reading from went into some kind of loop, and kept feeding us data, we would keep reading it into our heap and ultimately crash when we ran out of heap-memory.&lt;br /&gt;&lt;br /&gt;2) Reading one char at a time is not particularly efficient.  A bufferedInputStream would be more appropriate. I ran some benchmarks and found that to read a 2240 bytes, the time fell from about 140ms to about 40ms with a 1024 byte readbuffer.  This is pretty much all raw CPU time. So, if you are doing a lot of this, it would make a difference.&lt;br /&gt;&lt;br /&gt;So, to prevent the crash put in some limit (whatever is reasonable in your case) into your read loop (break and throw an exception if the read exceeds a certain size), and to improve performance -- use BufferedInputStream to do your reading.  Use 1024 bytes to start with, but the size of your buffer would depend on your application of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-7086746015900468276?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/7086746015900468276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/11/java-io-anti-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7086746015900468276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7086746015900468276'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/11/java-io-anti-pattern.html' title='A  java I/o anti-pattern'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-2561432494003319094</id><published>2009-11-23T19:48:00.000-06:00</published><updated>2009-12-05T09:59:19.544-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP Sessions'/><title type='text'>Websphere -- maximum # of sessions</title><content type='html'>Have you ever wondered what happens if, for whatever reason, there is a runaway amount of logins into your application.&lt;br /&gt;&lt;br /&gt;The answer probably is -- not good things.  Especially if you have any amount of data in your session, your server is going to struggle with managing the memory, i/o for session persistence etc.&lt;br /&gt;&lt;br /&gt;So, on the assumption you agree with the premise:  'Do three things well -- instead of ten things badly'. You'll want to do something about this.  &lt;br /&gt;&lt;br /&gt;For Websphere at least there is a setting in the administrative console to set the maximum number of sessions on the server.  &lt;br /&gt;&lt;br /&gt;First of all you'll have to decide what this number should be.  Only you really know the answer.   Set this (or have this set) via the administrative console. 'Application Servers &gt; serverName &gt; Web Container &gt; Session Management'.  The 'Allow overflow' checkbox needs to be unchecked of course.&lt;br /&gt;&lt;br /&gt;Your job is not done.  You should be asking, what happens when this maximum is reached.   Perhaps 'request.getSession(true);' will return null, or throw an exception?  The answer is neither of those.  Websphere will return you a session, but it will be an invalid one.&lt;br /&gt;&lt;br /&gt;So, you will have to add this code to wherever you do a getSession(true) or a getSession().  Hopefully (presumably?) this isn't in more than a few places in your code.&lt;br /&gt;&lt;br /&gt;HttpSession session = request.getSession(true);&lt;br /&gt;IBMSession ibmSession = (IBMSession)session;&lt;br /&gt;if (ibmSession.isOverflow()) {&lt;br /&gt;... appropriate action ..&lt;br /&gt;&lt;br /&gt;} else {&lt;br /&gt;&lt;br /&gt;.. continue normally ..&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Most likely you are going to want to simply redirect them to a simple html page with a message to the effect 'Server Busy, please retry later'.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-2561432494003319094?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/2561432494003319094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/11/websphere-maximum-of-sessions.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/2561432494003319094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/2561432494003319094'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/11/websphere-maximum-of-sessions.html' title='Websphere -- maximum # of sessions'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-6878598434483256253</id><published>2009-11-18T20:34:00.000-06:00</published><updated>2009-12-05T09:59:05.848-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP Sessions'/><title type='text'>Conserving Sessions</title><content type='html'>Sessions are somewhat precious.  And it is a good idea to conserve them.  If you agree with that premise -- and your site requires logging in just to enter it at all -- read on.&lt;br /&gt;&lt;br /&gt;Are you aware of this JSP directive?&lt;br /&gt;&lt;br /&gt;&amp;LT;%@ page session="false"%&amp;GT;&lt;br /&gt;&lt;br /&gt;This instructs the JSP not to automatically create a session when this JSP is invoked.  In the absence of this directive, a session will be created.&lt;br /&gt;&lt;br /&gt;So, as you can imagine, if you have a page such as a Log In page that is a JSP, this directive needs be included in that JSP.&lt;br /&gt;&lt;br /&gt;Otherwise, someone simply getting to this page is going to create a session on your server.  And, if they choose to not Log In --- this session is going to live on your server until it reaches the session timeout value.  &lt;br /&gt;&lt;br /&gt;Corollaries:&lt;br /&gt;&lt;br /&gt;1) The page they land on after you do a 'session.invalidate()' needs to have this directive&lt;br /&gt;&lt;br /&gt;2) If the log in fails, make sure you have not created a session while processing the log in request, or if you have, invalidate it.&lt;br /&gt;&lt;br /&gt;3) The 'Session Expired' page would need this too.&lt;br /&gt;&lt;br /&gt;4) Make sure that you do not create a session while processing a 'Log Out' request from an expired session.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-6878598434483256253?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/6878598434483256253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/11/conserving-sessions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6878598434483256253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6878598434483256253'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/11/conserving-sessions.html' title='Conserving Sessions'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-7593904420746362316</id><published>2009-11-11T20:30:00.000-06:00</published><updated>2009-12-12T17:26:27.702-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Heap Management'/><title type='text'>To Cache or not to Cache</title><content type='html'>Caches are seductive.  For some reason Programmers love to write/use them.  Though, in my opinion, they should only be used after careful thought.  I am talking about the home-made caches written with the J2EE application itself -- not the ones written within system software such as database managers.&lt;br /&gt;&lt;br /&gt;Here are my thoughts on the subject.&lt;br /&gt;&lt;br /&gt;a)Make sure that the puts/gets from/to the cache are thread safe.  java.util.HashMap is not thread safe.  java.util.Hashtable is, but it is slow.  Here is an excellent article that recommends the use of java.util.ConcurrentHashMap.&lt;br /&gt;&lt;br /&gt;http://www.ibm.com/developerworks/java/library/j-jtp07233.html&lt;br /&gt;&lt;br /&gt;b)Make sure that the cache cannot grow indefinitely.  You need to somehow limit the maximum number of entries in the cache - lest it crash your server due to an 'out of memory error' from the JVM.  &lt;br /&gt;&lt;br /&gt;You'll have to decide how to manage the situation when the max number of entries is reached.  Some entries will need to be discarded.  Least Recently Used is one option, oldest is another option.  This of course means you will have to track that somehow.&lt;br /&gt;&lt;br /&gt;c)More likely than not, the cache entries are going to get stale at some point.  Ideally you can somehow get notified of this event and remove the corresponding entry from the cache.  If not, you may decide that you can live with say a four hour age.  If you find an entry in your cache and determine it older than that age, you will discard it and refresh the value.  This alogrithm has a number of disadvantages:&lt;br /&gt;&lt;br /&gt;i) You could of course be working against a stale entry.&lt;br /&gt;&lt;br /&gt;ii) If your servers are in a cluster, you could have different values for a particular key in each server -- This alone has a smell to it.&lt;br /&gt;&lt;br /&gt;iii) You need to somehow delete entries in your cache that are stale or just be carrying deadweight in your JVM.   &lt;br /&gt;&lt;br /&gt;d) Related to b) but worth emphasizing. You'll be using up valuable space in your Heap for your cache.  &lt;br /&gt;&lt;br /&gt;If you've covered all the bases described above -- weigh the cost of all that, the additional risk from the complexity and the use of the very valuable Heap space against the performance improvements.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-7593904420746362316?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/7593904420746362316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/11/to-cache-or-not-to-cache.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7593904420746362316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7593904420746362316'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/11/to-cache-or-not-to-cache.html' title='To Cache or not to Cache'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-3886936218019060113</id><published>2009-11-03T20:03:00.000-06:00</published><updated>2009-12-05T10:03:32.448-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HTTP Sessions'/><title type='text'>Websphere plugin:Counter intiutive behavior in clustered environments</title><content type='html'>If you are not using session persistence, but getting by just turning on Session Affinity in the Websphere Plug-in -- you may believe that if you restart just one server out of your cluster -- you would only affect the sessions on that server.&lt;br /&gt;&lt;br /&gt;However you would be wrong.  If you restart one server, say out of four -- all end-users on that server would of course lose their sessions.  However, when the server comes back on line, the Websphere plug-in suspends its 'session affinity' and will direct sessions from other servers to the new server.&lt;br /&gt;&lt;br /&gt;This, of course, would be no particular big deal if you had session persistence across your cluster, but if you didn't -- some of the end-users on the other servers will lose their sessions.  &lt;br /&gt;&lt;br /&gt;The plug-in just assumes you have session persistence and values balancing the load over the cluster over and above affinity when a new server comes on line.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-3886936218019060113?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/3886936218019060113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/11/websphere-plugincounter-intiutive.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3886936218019060113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3886936218019060113'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/11/websphere-plugincounter-intiutive.html' title='Websphere plugin:Counter intiutive behavior in clustered environments'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-6678408770036983297</id><published>2009-11-03T19:49:00.000-06:00</published><updated>2009-12-05T09:58:19.389-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Logging'/><title type='text'>Websphere and Commons Logging: Oil &amp; Water</title><content type='html'>Are you using Apache's Commons logging and are perplexed as to why you cannot control this logging when running inside a Websphere server?  The reason is that Commons is just a thin wrapper around (in theory) a logging system of your choice.  Many people choose the log4j logger of course.&lt;br /&gt;&lt;br /&gt;However, IBM sees fit to direct Commons to its own logger - so, you can configure commons logging all you want, IBM forces it to its own implementation -- the one used to log to the console.   &lt;br /&gt;&lt;br /&gt;This behavior was impossible to change in 5.1 and it is supposed to be able to change it in 6.x and beyond -- though I don't believe it is simple to do so.  I spent a lot of time trying to get around it when our organization was on Websphere 5.1 -- and we started using the log4j logger directly -- so I haven't spent much time investigating it in 6.1.  &lt;br /&gt;&lt;br /&gt;I don't see any particular advantage to using Commons.. Unless there are very specialized requirements -- don't see any real argument against log4j.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-6678408770036983297?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/6678408770036983297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/11/websphere-and-commons-logging-oil-water.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6678408770036983297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6678408770036983297'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/11/websphere-and-commons-logging-oil-water.html' title='Websphere and Commons Logging: Oil &amp; Water'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-5633965166464163991</id><published>2009-10-22T21:34:00.000-05:00</published><updated>2009-12-05T09:57:45.331-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>J2EE Application improving performance.</title><content type='html'>Here is a little anti-pattern -- that depending on your application -- could be costing you.&lt;br /&gt;&lt;br /&gt;While learning up on my legacy J2EE app.  I noticed a lot of:&lt;br /&gt;&lt;br /&gt;SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");&lt;br /&gt;String dateString = sdf.format(someDate);&lt;br /&gt;and/or&lt;br /&gt;Date date = sdf.parse(someString);&lt;br /&gt;&lt;br /&gt;since these statements were inside the execute method of a Struts action, each HttpRequest was creating an instance of SimpleDateFormat -- and shortly thereafter discarding it..&lt;br /&gt;&lt;br /&gt;Now SimpleDateFormat.parse() is not threadSafe.. so this is not all bad if you ARE parsing -- however, nine times out of ten, you will be just formatting. in which case you should create the SimpleDateFormat as an instance variable like so:&lt;br /&gt;&lt;br /&gt;private static final SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");&lt;br /&gt;&lt;br /&gt;If you already have apache-commons in your project, use FastDateFormat -- like so:&lt;br /&gt;&lt;br /&gt;private static final FastDateFormat basicDateFormat = FastDateFormat.getInstance( "MM/dd/yyyy", Locale.US );&lt;br /&gt;&lt;br /&gt;Now this leads to an important question.  If you are not already using apache-commons -- should you?&lt;br /&gt;&lt;br /&gt;Not for just this one option.  In my opinion, unless a) you intend to use more than a few functions b) everyone in your project is familiar and willing to use them and most important c) someone takes ownership of maintaining this 'third party library'.  i.e. resolving issues, downloading fixes, updates as and when necessary etc.  &lt;br /&gt;&lt;br /&gt;And, keep in mind that you WILL be introducing a dependency -- so if and when you migrate your appserver say from one that uses Java 1.5 to Java 1.6, it will be one more thing to check and confirm and perhaps upgrade and test.  So, though it is easy enough to download and throw this library into WEB-INF/lib, there is an ongoing cost to use it -- make sure it is worth it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-5633965166464163991?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/5633965166464163991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/10/j2ee-application-improving-performance.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/5633965166464163991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/5633965166464163991'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/10/j2ee-application-improving-performance.html' title='J2EE Application improving performance.'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-7453955968993541909</id><published>2009-10-22T18:48:00.000-05:00</published><updated>2009-12-05T09:57:28.031-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Class Loading'/><title type='text'>Websphere -- shared class cache by the JVMs</title><content type='html'>If you are running multiple JVMs inside your Websphere 6.x+ server -- you may be surprised to learn that the JVMs share Classes in a common Class cache.  Before you freak -- note that only System classes, i.e. those that are part of the jre itself are the ones that are shared. Your Classes are not.&lt;br /&gt;&lt;br /&gt;This is actually a feature of the IBM version of the jre/jdk 1.5 and onwards.&lt;br /&gt;&lt;br /&gt;To turn this off:  set the JVM argument -Xshareclasses:none&lt;br /&gt;&lt;br /&gt;If you are getting weird class loading errors -- and cannot figure out why -- try shutting off this cache.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-7453955968993541909?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/7453955968993541909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/10/websphere-shared-class-cache-by-jvms.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7453955968993541909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7453955968993541909'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/10/websphere-shared-class-cache-by-jvms.html' title='Websphere -- shared class cache by the JVMs'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-5117286437966290418</id><published>2009-10-20T21:15:00.000-05:00</published><updated>2009-12-05T09:56:14.868-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Connection Pool Settings'/><title type='text'>Application server connection pool settings that are of concern to the Software Architect:Shared Connections</title><content type='html'>IBM Websphere: 'Shared Connections' is the setting in Websphere Application Server by default and, at least in my experience, is a setting that is little known about -- and, depending on your application -- can have a major impact on your design.&lt;br /&gt;&lt;br /&gt;What it means is that the same connection is shared by all J2EE components during an HTTP request.  At least that is what I think it means.  However, I do know for sure the practical result of this setting..&lt;br /&gt;&lt;br /&gt;Say you have a Servlet/Struts action or whatever server side component that gets executed to service an HTTP request: (not intended to be working code).&lt;br /&gt;&lt;br /&gt;public void doGet(HttpServletRequest req, HttpServletResponse resp) {&lt;br /&gt;&lt;br /&gt;java.sql.Connection conn = null;&lt;br /&gt;try {&lt;br /&gt;dataSource.getConnection();&lt;br /&gt;... do stuff...&lt;br /&gt;} &lt;br /&gt;finally {&lt;br /&gt;conn.close():&lt;br /&gt;}&lt;br /&gt;.. do some other stuff, perhaps a call to a backend service..then&lt;br /&gt;req.getRequestDispatcher("some.jsp").forward(req,resp);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;You may (understandably) believe that the connection is returned to the pool, right after you called Connection.close().  However, if the Connection Pool is set to 'Shared' (the default), you would be wrong.  Websphere will hold onto the connection through the call to the backend service and until it finishes servicing the http request.&lt;br /&gt;&lt;br /&gt;So, if you have an Application that has the above pattern -- you should definitely consider changing the datasource setting from 'Shareable' to 'Unshareable'. &lt;br /&gt;&lt;br /&gt;You do this in the web deployment descriptor. Reference tab in the Websphere Administrative console.. or:&lt;br /&gt;&lt;br /&gt;&lt;resource-ref id="ResourceRef_1256088138520"&gt;&lt;br /&gt;&lt;description&gt;&lt;br /&gt;&lt;/description&gt;&lt;br /&gt;&lt;res-ref-name&gt;jdbc/ds1&lt;/res-ref-name&gt;&lt;br /&gt;&lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;&lt;br /&gt;&lt;res-auth&gt;Container&lt;/res-auth&gt;&lt;br /&gt;&lt;res-sharing-scope&gt;Unshareable&lt;/res-sharing-scope&gt;&lt;br /&gt;&lt;/resource-ref&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-5117286437966290418?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/5117286437966290418/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/10/application-server-connection-pool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/5117286437966290418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/5117286437966290418'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/10/application-server-connection-pool.html' title='Application server connection pool settings that are of concern to the Software Architect:Shared Connections'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-7851074275663646939</id><published>2009-10-14T20:47:00.000-05:00</published><updated>2010-03-13T08:32:49.228-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Connection Pool Settings'/><title type='text'>Application server connection pool settings that are of concern to the Software Architect:Aged Timeout</title><content type='html'>&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Aged Timeout&lt;/b&gt;: default value is zero which implies no timeout.This is the maximum time that Websphere will use a  given connection.&amp;nbsp; So, if a connection stays in use past this time, without an intervening idle window &amp;gt;= the Unused timeout -- Websphere will simply recycle this connection.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;Again this setting depends on your application, but 9000 seconds or 2.5 hours is a good starting point.&amp;nbsp; No specific reason, it just feels good to know that connections are getting closed every so often so any memory leak in the connection either in Websphere or in Oracle is getting cleared.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;It also flags any connections on the db server that are older than this timeout for further investigation.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: Arial,Helvetica,sans-serif;"&gt;&lt;span style="font-size: small;"&gt;I am presuming you are well aware that ResultSets, Prepared Statements. Callable Statements are to be closed after use.&amp;nbsp; Closing the connection will not necessarily close them.&amp;nbsp; These timeouts will &lt;u&gt;not&lt;/u&gt; protect you in the event you are not doing this.&amp;nbsp; I don't even mention the vanilla Statement, on the assumption that you are savvy enough to never use it in your J2EE application.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: x-small;"&gt; &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: x-small;"&gt; &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;span style="font-family: Arial; font-size: x-small;"&gt; &lt;/span&gt; &lt;span style="font-family: Arial; font-size: x-small;"&gt; &lt;/span&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-7851074275663646939?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/7851074275663646939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/10/aged-timeout.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7851074275663646939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/7851074275663646939'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/10/aged-timeout.html' title='Application server connection pool settings that are of concern to the Software Architect:Aged Timeout'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-6148632718026229002</id><published>2009-10-13T21:37:00.000-05:00</published><updated>2009-12-05T09:55:49.780-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Connection Pool Settings'/><title type='text'>Application server connection pool settings that are of concern to the Software Architect:Unused Timeout</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Unused Timeout:&lt;/span&gt;   This is how long &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Websphere&lt;/span&gt; will keep a connection idle in the pool. That is, say there is a sudden demand for connections and the total # of connections in the pool climbs to say 100.   Now, there is a decrease in web traffic.   The connections in use at any time are now about 50 and stay there for a while. With the default timeout of 1800, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Websphere&lt;/span&gt; will wait a half hour before releasing the excess 50 connections.&lt;br /&gt;&lt;br /&gt;Another way to look at it is that if any one connection is in the pool and idle for 1800 seconds or 30 minutes -- it will be closed and removed from the pool.&lt;br /&gt;&lt;br /&gt;I think 30 minutes is excessive. I recommend 300 seconds or five minutes as a starting point. Adjust depending on your application and other constraints. Closing the connection will ensure all associated result sets etc. will get cleared and Garbage Collected. The db server will be able to clear up the memory at its end as well.&lt;br /&gt;&lt;br /&gt;If you have multiple applications or application servers (as in a cluster) connecting to the same database, this may result in a lower maximum # of connections in use at the database server over a given period of time.    This would provide relief to your database server and, if it is licensed by max # of connections, may save you money as well.&lt;br /&gt;&lt;br /&gt;There are two drawbacks to these connections being closed.   It will clear the 'Prepared Statement Cache' and there will be some overhead of re-acquiring this connection if and when demand rises again.    So you don't want to set this to too low a value.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-6148632718026229002?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/6148632718026229002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/10/websphere-connection-pooling-unused.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6148632718026229002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/6148632718026229002'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/10/websphere-connection-pooling-unused.html' title='Application server connection pool settings that are of concern to the Software Architect:Unused Timeout'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8396383771129062296.post-3966426093715257970</id><published>2009-10-13T00:28:00.000-05:00</published><updated>2009-12-05T09:55:33.218-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Connection Pool Settings'/><title type='text'>Application server connection pool settings that are of concern to the Software Architect:Connection Timeout</title><content type='html'>If you have any responsibility for the stability/performance of your application -- there are some settings you need to be concerned about.   I am familiar with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Websphere&lt;/span&gt; and most likely there are comparable settings for its competitors.    In &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Websphere's&lt;/span&gt; case at least, these settings are not very well documented and it is easy to misunderstand them.  In this post, I will address 'Connection Timeout'.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Connection Timeout:&lt;/span&gt;If you do a javax.sql.DataSource.getConnection() and there are no connections available -- this is how long &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Websphere&lt;/span&gt; will wait until it throws a timeout exception.  The default value is 180 seconds and this is a bad setting.&lt;br /&gt;&lt;br /&gt;Why?  Because while you are waiting, you are using up a thread in the web-container and this thread will stay active and waiting in line for the next available connection even if the end-user abandons the transaction by hitting stop, back buttons on his browser or even just closing the browser.&lt;br /&gt;&lt;br /&gt;You and I may be patient folks (particularly with our own applications) -- but the rest of the world is not.&lt;br /&gt;&lt;br /&gt;For a B2C application,  and depending on how invested the end-user is in the transaction -- I wouldn't invest a thread past 3 seconds, five at the very most.   For Intranet or B2B applications you can increase this -- but I wouldn't go past 15 seconds. &lt;br /&gt;&lt;br /&gt;Chances are that the end-user is going to abandon his transaction after waiting the above mentioned times.&lt;br /&gt;&lt;br /&gt;What can &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;exacerbate&lt;/span&gt; the situation is that after abandoning the transaction, the end-user can keep repeating/retrying -- just chewing up threads on your server.  Worse yet,  these threads are going to live at least 180 seconds on your server!!&lt;br /&gt;&lt;br /&gt;You can easily imagine that with enough users, this can snowball to the point of bringing your server to a complete halt.&lt;br /&gt;&lt;br /&gt;You can/should, of course, trap this exception and display some appropriate message to the end-user -- like 'System is busy, please retry later'..  You need to log this event of course.   Goes without saying that this logging should in no way be directed to the same database :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary:&lt;/span&gt;  Will depend on your application -- but set it as low as you can get away with.  Don't exceed 3, 5 at the very most for a B2C application -- 15 for Intranet/B2B applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8396383771129062296-3966426093715257970?l=bcharan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bcharan.blogspot.com/feeds/3966426093715257970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bcharan.blogspot.com/2009/10/application-server-connction-pool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3966426093715257970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8396383771129062296/posts/default/3966426093715257970'/><link rel='alternate' type='text/html' href='http://bcharan.blogspot.com/2009/10/application-server-connction-pool.html' title='Application server connection pool settings that are of concern to the Software Architect:Connection Timeout'/><author><name>Brad Charan</name><uri>http://www.blogger.com/profile/13743391971467720353</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
