I have published this info on the internet and you can view them at http://www.kengsi.com/jdbcwiz.html. Hope this will help few others by having this information in one single place. I will add more databases as time goes on so if you don't see information about a database driver you are interested in, please do let me know.
Tuesday, February 7, 2012
JDBC Driver Class Names and URL Formats For Popular Databases
I have published this info on the internet and you can view them at http://www.kengsi.com/jdbcwiz.html. Hope this will help few others by having this information in one single place. I will add more databases as time goes on so if you don't see information about a database driver you are interested in, please do let me know.
Don' forget to click the +1 button below if this post was helpful.
Friday, January 27, 2012
Quick and Simple LRU Cache in Java
- LinkedHashMap from JDK
- LRUMap from Commons Collections
- ConcurrentLinkedHashMap on Google Code (Winner)
As you can see it's pretty simple to create a cache and you can use the put an get methods from the Map interface to add and retrieve entries from the cache
Don' forget to click the +1 button below if this post was helpful.
Thursday, January 26, 2012
Few Easy Steps to Install Sun/Oracle JDK on EC2 Linux
Update:
Oracle doesn't provide direct download URLs for JDKs anymore. I have updated the steps with the trick mentioned here to get the installation file with wget
Run java -version to make sure you have the Sun/Oracle JDK as your default jvm now.
Don' forget to click the +1 button below if this post was helpful.
Monday, January 23, 2012
Servlet Filter to Set Response Headers
It's basically the same thing but just setting different response header values. So I decided to write a general purpose Servlet filter to achieve this in a few lines.
We configure the filter in web.xml and set the required response header / value pair as init params
Here we are setting the Cache-Control response header and setting the expiry date to 1 year from request time. Now we add the appropriate filter mapping to apply the filter to static content we are interested in.
And we are done. In summary all we are doing here is setting cache headers to all static content like .js, .css etc... so they will be cached by the client browsers for a very long time making the pages load faster and reducing the bandwidth usage / load on the server significantly.
Please note you shouldn't add far future cache expiration dates if you plan to make changes to the static content at any time as the modified content might not be downloaded by client browsers. The strategy we take is to make a new copy of the file when we modify and link to the new file. e.g. style-1.1.css when modified will be made site-1.2.css,
Don' forget to click the +1 button below if this post was helpful.
Wednesday, November 16, 2011
Why Developers Shouldn't Be Using JDBC Connections, Statements and PreparedStatements
I truly believe in this day and age you shouldn't be working directly with these low level interfaces and the associated boiler plate code you eventually end up writing. Basically you will have to get the connection, create statements or prepared statements, get the result set and once you are done close everything in a finally clause. This will not only create long, ugly and hard to read code but will make it very easy to introduce errors by say forgetting to close a connection.
So if you are not building a toy Java application you should really be using a high level API that automatically handles these tasks for you. I am not a very big fan of fancy ORM libraries and my preferred data access library has been Spring JDBC for the last two years or so. It gives you the full power of raw SQLs while making it easy do what you want to do with minimum coding. End result is simple, readable and most importantly maintainable and less error prone data access code.
Once you have configured Spring JDBC, an update or a select can be done in one line of code.
So if you are still using low level JDBC code in your applications, its time to consider moving to something like Spring JDBC. You can move your code gradually to the new APIs as Spring JDBC can and will coexist with low level JDBC code.
Take a look at the Spring documentation to get a more in depth idea of all available features of Spring JDBC
Don' forget to click the +1 button below if this post was helpful.
Friday, November 11, 2011
Reading All Items from an Amazon SimpleDB Query Result
The variable sdb is the AmazonSimpleDB implementation class which in my case is the AmazonSimpleDBClient initialized and injected using Spring. Following is the relevant Spring configuration section (I am initializing an AmazonS3Client too which is not required if you are only using SimpleDB).
AWS ID and Secret values are read from the aws.properties file in the classpath, which looks like below.
Don' forget to click the +1 button below if this post was helpful.
Friday, September 7, 2007
Speed up MockStruts Test Execution by Caching Spring Context
This is true if you use Spring's ContextLoaderPlugIn, where it tries to initialize a custom spring context using the parent context.
Spring will look for the parent context in the ServletContext object where it store it. Since MockStruts will create a new ServletContext for each test method Spring will try to create the context each time. This results in addition of about 4 second per test method (on my workstation).
Note: I'm using MappingDispatchAction with multiple actions in a single Action class, therefore I have mutiple test methods in a single test class too.
The above 4 second penalty per test method can be removed by simply caching and storing the Spring context in ServletContext object before each test execution. This reduced the execution time of the whole test suite drastically in the application I was working on.
In order to achieve the above I used a base class extending MockStrutsTestCase as shown below and used it as the parent class for all the Struts test cases
|
Also remember to set forkMode to perBatch or once in ants junit task as shown below if you have set the fork attribute to true.
<junit fork="true" forkmode="once" haltonfailure="">
...
</junit>
Don' forget to click the +1 button below if this post was helpful.
Friday, July 27, 2007
How to Properly Iterate a Collection in Java
I came across a code base of a project that was developed mostly by a bunch of junior developers and most of the code that iterates a collection was in the following format
List administrators = getAdministrators();
if (administrators.size() > 0) {
Iterator administratorsItr = administrators.iterator();
Administrator administrator = null;
while (administratorsItr.hasNext()) {
administrator = (Administrator) administratorsItr.next();
//rest of the code block removed
}
}
}
Just looking at that piece of code made my head spin :). The worst part was that this is the style most of the junior developers had adopted and could be seen all over the code base.
Just for the record I would have written it in the following way (actually would have let the IDE write it for me)
The above two code blocks achieve the same thing, the difference been, first is 9 lines long and the second is 4 lines. Most importantly you can figure out whats going on easily by looking at the second code block.
List administrators = getAdministrators();
for (Iterator iter = administrators.iterator(); iter.hasNext();) {
Administrator administrator = (Administrator) iter.next();
//rest of the code block removed
}
The worst part is IDEs like IntelliJ IDEA will write it for you. All you have to do is type itco and press ctrl + space keys just after the List administrators = ... line.
I don't know if there is something similar on Eclipse but you can import all these nifty IDEA Live Templates into Eclipse. Just head over to this page where you can find the xml file and instructions on how to import the file.
Don' forget to click the +1 button below if this post was helpful.
Monday, June 25, 2007
Save Time Fixing Ant Errors With -verbose Switch
BUILD FAILED
C:\work\builds\build.xml:58: Process fork failed.
I wasted a couple of hours on google looking for an answer and after failing to fix the issue with several suggested solutions, I stumbled upon one post that suggested enabling the verbose output of Ant. All you had to do was pass -verbose as a command line parameter to ant
ant -verbose <target>
That made ant display lot of details including the actual exception. In my case it was:
C:\work\build\build.xml:58: Process fork failed.
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeAsForked(JUnitTask.java:871)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:679)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:1413)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:633)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
at org.apache.tools.ant.Task.perform(Task.java:364)
at org.apache.tools.ant.Target.execute(Target.java:341)
at org.apache.tools.ant.Target.performTasks(Target.java:369)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)
at org.apache.tools.ant.Project.executeTarget(Project.java:1185)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)
at org.apache.tools.ant.Project.executeTargets(Project.java:1068)
at org.apache.tools.ant.Main.runBuild(Main.java:668)
at org.apache.tools.ant.Main.startAnt(Main.java:187)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)
Caused by: java.io.IOException: CreateProcess: C:\bea92\jdk150_04\jre\bin\java.exe ...
I found the issue a little bit above the exception on the console and it was the massive classpath value passed into the java.exe. Obviously the Windows command line has a limitation on the length of command line arguments and the value for classpath was exceeding it.
When I checked the build file I found the error, where it was adding the files in a directory instead of the directory into the classpath. Fixed that small error and all was fine again.
Anyway glad I got to know about the verbose switch in Ant and hopefully I wouldn't have to waste a lot of time again fixing ant issues again.
Don' forget to click the +1 button below if this post was helpful.
Tuesday, June 12, 2007
Why would anyone want to buy a commercial JDBC driver?
We bought a driver from i-net software (Opta if I remember correctly) which I guess was the best commercial driver available at that time. Later on the application was ported to Oracle and we were happy to use the Oracle thin driver instead of bothering to buy another commercial implementation.
Since then I have worked for several big enterprise clients, developing Java web applications that connected to Oracle, MS SQL Server and DB2 (ver 7.2) databases. All these applications were using the database vendor provided drivers and all was well except for the DB2 driver (net driver).
I used to visit i-net software web site frequently as their Crystal Clear reporting tool was used in some earlier projects. Today I stumbled upon their site again after a long time and I started wondering why no one even considers using commercial drivers anymore including myself.
I could think up of a few possible reasons to shell out few bucks for a JDBC driver.
1. Performance
2. Reliability
3. Available features (JDBC 3.0, XA support etc...)
Now if we take Oracle thin driver and the above list, I don't see how a third party driver can provide significant performance and reliability over the thin driver.
As for features, thin driver has every thing you would need on an average project. Commercial implementations usually have few additional bells and whistles (e.g. i-net Opta driver supports SSL encryption and implements JDBC 4.0 API) which usually are not that important.
I guess same could be said for the SQL Server drivers from Microsoft and hopefully the new DB2 drivers from IBM, that is they does the job for your average project.
Also given the fact that application servers like BEA Weblogic includes its own drivers for all major databases including SQL Server, DB2, Sybase and Informix, I really don't see a reason to buy a JDBC driver from a third party.
Having said that, I would love to know about instances where a commercial driver was used and the reasons behind it.
P.S. Elaborating on the issue with the older DB2 driver:
DB2 v7.2 didn't come with a type 4 JDBC driver and we had to use what was called the net driver. There was this funny problem where it failed to see some records in a table. Select queries would not return these records when connected through the net driver. We never figured out why and only solution was to delete the record and insert them back. Luckily for us it only happened in the QA server :). Anyhoo the database was upgraded to DB2 version 8 and the driver to the type 4 version that came with it.
Don' forget to click the +1 button below if this post was helpful.
Tuesday, May 29, 2007
Myth - Defining loop variables inside the loop is bad for performance
I like to define loop variables inside the loop on the line where the assignment is happening. For example if I was iterating through a String collection I would do it like below
private void test() {
for (Iterator iter = list.iterator(); iter.hasNext();) {
String str = (String) iter.next();
System.out.println(str);
}
}
The other day a colleague of mine was doing a peer review and he said this was bad and I should have defined the String variable str outside the loop. What he suggested was something like below.
private void test() {
String str;
for (Iterator iter = list.iterator(); iter.hasNext();) {
str = (String) iter.next();
System.out.println(str);
}
}
When I questioned the logic behind it he said something like
If you define str inside the loop it will get initialized in each iteration and that’s bad for performance.
Or something like that… and so the argument started. I mean str is a frigging variable not an object that would get initialized or anything. The compiler wouldn’t go allocating memory to str in each iteration and my belief was that it didn’t matter whether you declare str inside the loop or outside the loop. The compiler wouldn’t care and would generate the same byte code in either case.
I did some googling around and came across this blog which discusses the same thing though his preference was to declare the variable outside the loop. The first example was very similar to what I had in mind but it was with primitives. The second example with StringBuffer is a totally different story from mine.
So I had to do my own test, I wrote another class with the str declared outside the loop and compiled them both. Then using javap utility that comes with the JDK printed the byte code for both implementations (ie. javap –c –private <classname>)
Byte Code genarated when the variable is declared inside the loop:
private void test();
Code:
0: aload_0
1: getfield #15;
4: invokevirtual #22;
7: astore_1
8: goto 28
11: aload_1
12: invokeinterface #26,
17: checkcast #32;
20: astore_2
21: getstatic #34;
24: aload_2
25: invokevirtual #40;
28: aload_1
29: invokeinterface #46,
34: ifne 11
37: return
}
Byte Code genarated when the variable is declared outside the loop:
private void test();
Code:
0: aload_0
1: getfield #15;
4: invokevirtual #22;
7: astore_2
8: goto 28
11: aload_2
12: invokeinterface #26,
17: checkcast #32;
20: astore_1
21: getstatic #34;
24: aload_1
25: invokevirtual #40;
28: aload_2
29: invokeinterface #46,
34: ifne 11
37: return
}
Basically it’s the same byte code except the variable numbers are switched (ie. line 11 aload_1 become aload_2). So it really doesn't make a difference and where you declare the variable is a just a matter of taste.
Don' forget to click the +1 button below if this post was helpful.
Thursday, May 24, 2007
How to notify JavaBlogs.com about blog updates with XML-RPC
Did a search for XML-RPC clients on the web and I found this open source Java library from Redstone. Downloaded the jar file and followed the instructions on Redstone page and the page describing the Weblogs API. I have to say when I started on this I didn't think it would be this easy but after about 10 minutes I had it working :).
Just add the following lines inside a main method and execute:
String weblogName = "Living Tao"; |
{flError=0, message=Success. 1 blogs have been queued for update}
Don' forget to click the +1 button below if this post was helpful.
Wednesday, May 23, 2007
final - Least used keyword in Java development?
So far our development team has not looked at the correct usage of final keyword during peer reviews, but going forward it will be added to the peer review guideline document. Hope I'll see more finals in our code after that [if anyone follows the guideline that is :) ]
Anyway here is a link to a good explanation on final keyword: The Final Word on the final Keyword
Don' forget to click the +1 button below if this post was helpful.
Monday, May 21, 2007
Testing application generated emails with Apache James server
We needed an easy way to test them locally in developer machines without using an external SMTP server.
The plan was to run a James server in every developer machine which forwarded all the emails it receives to an email account on the same server.
Following were the steps followed to achieve this:
1. Download and Run James Server
Downloaded the latest zip bundle from apache site (ver 2.3.1). Extracted to a folder and executed run.bat in the bin directory to start the server for the first time. This will extract the james.sar file in apps directory to the apps/james directory. Now you will be able to modify the configuration file (config.xml) in apps/james/SAR-INF.
2. Create a local email account.
Open a command window and type telnet localhost 4555. When asked for the user name and password type root for both. Now you will be in the admin console and create a email account by typing adduser test test. This will create an email account named test with the password set to test.
3. Delete remote delivery mailet.
Open up the config.xml and locate the RemoteDelivery mailet section <mailet match="All" class="RemoteDelivery">...</mailet> and remove the tag including all its content.
4. Add a forward mailet to forward all mails
Insert the following mailet in the place where the RemoteDelivery mailet was.
<mailet match="All" class="Forward">
<forwardto>test@localhost</forwardto>
</mailet>
5. Save config.xml and Restart the James Server
Now all emails generated by the application (which is configured to use the SMTP server on localhost) will be handled by the James server running in the local machine and it will forward all emails to the test@localhost email account regardless of recipient addresses in email messages.
You can configure Outlook Express or any other client to read the mails sent to test@localhost.
Don' forget to click the +1 button below if this post was helpful.
Friday, May 18, 2007
When to call isDebugEnabled() before writing debug messages
logger.debug("Saved order successfully. Order ID : " + order.getId() +
" items in order " + order.getItems().size());In the above case there is a new string object created by concatenating all the parameters before making the call to debug method. This is done regardless of debug is enabled or not which will be a unnecessary performance overhead if debug is disabled.
if( logger.isDebugEnabled()){
logger.debug("Before saving the order");
}In the above code section the if condition is not necessary as there is no String concatenations involved and ends up adding two redundant lines of code.
Therefore the rule would be to do a isDebugEnabled check only if there is any String concatenation involved in the call to debug. This seems to be obvious but developers somehow keep getting this wrong.
Don' forget to click the +1 button below if this post was helpful.
Reduce logger initialization code in your Java applications
An application using log4j logging framework will initialize the logger in a class as
private static final Logger logger = Logger.getInstance(TestAction.getClass());This is done in each and every class which needs to use a logger. Now if we use a base class for lets say all Struts Actions called BaseAction, it can contain the logger initialization code as below.
package com.test.web;
import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
public abstract class BaseAction extends Action{
//initializes the logger object
protected final Logger logger = Logger.getInstance(this.getClass());
}Now all sub classes that extends from BaseAction (implementation action classes) will have the logger object created on initialization with the proper class name. Even though in theory this creates a new logger object per instance of TestAction class, it wont be an issue since Struts will maintain only a single instance of TestAction to serve all requests mapped to it.
This could be applied to all Service, DAO classes as well if you are using a framework like Spring to manage them, where only one instance per implementation class will be created.
P.S. This post was modified as per comments by fabien...
Don' forget to click the +1 button below if this post was helpful.
Thursday, May 17, 2007
Global Exception Handling for Struts and Tiles Applications
I was looking at implementing a global error page for unhandled exceptions in a Struts / Tiles application. Normally this was achieved by adding a
This would forward to the error page if an unhandled exception was thrown from the Struts action but will not do so if the exception occurred in one of the tiles JSPs. An exception in a tile would result in a partly rendered page but this was fine in previous app as there were hardly any logic in JSP files and it was very rare to have an exception at the JSP level in production.
In the new app though this wasn’t the case as there were lot of logic that went in to JSPs in the form of custom tags etc… that could potentially throw all sorts of exceptions at run time and I wanted to handle all these exceptions in a unified manner.
New Solution
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error </location>
</error-page>
Then added a servlet and a servlet mapping to the /error URL
<servlet>
<servlet-name>exceptionHandler</servlet-name>
<servlet-class>com.test.ExceptionHandlerServlet</servlet-class>
<init-param>
<param-name>errorPageURL</param-name>
<param-value>error.html</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>exceptionHandler</servlet-name>
<url-pattern>/error</url-pattern>
</servlet-mapping>
The ExceptionHandlerServlet would log the exception and redirect the browser to the URL defined in the servlet configuration (error.html).
ExceptionHandlerServlet Code:
|
This was due to tiles flushing content to the response buffer before the whole page was rendered. In such a situation the browser will happily display what it received and the redirect to the error page will have no effect.
In order to prevent or minimize the flushing of response buffer:
1. Set flush attribute to false in all tiles insert tags
2. Increase the response buffer size to minimize auto flushing
This was achieved by modifying the tiles layout jsp page.
<!-- sets the response buffer size to 64kb -->
<%@ page buffer="64kb"%>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles"%>
…
<tiles:insert attribute="header" flush="false" />
<tiles:insert attribute="leftnav" flush="false" />
<tiles:insert attribute="body" flush="false" />
<tiles:insert attribute="footer" flush="false" />
In the above code segment all html formatting was removed for clarity. The response buffer was set to 64 kilobytes and this value should be decide based on the average page size of the application and the performance impact of the increased memory usage.
Don' forget to click the +1 button below if this post was helpful.
