Monday, November 16, 2009

What to throw, Checked or Unchecked Exceptions?

If you throw a checked exception (and don't catch it), you will need to declare the exception in your method's throws clause. Client programmers who wish to call your method will then need to either catch and handle the exception within the body of their methods, or declare the exception in the throws clause of their methods. Making an exception checked forces client programmers to deal with the possibility that the exception will be thrown.

If you throw an unchecked exception, client programmers can decide whether to catch or disregard the exception, just as with checked exceptions. With an unchecked exception, however, the compiler doesn't force client programmers either to catch the exception or declare it in a throws clause. In fact, client programmers may not even know that the exception could be thrown. Either way, client programmers are less likely to think about what they should do in the event of an unchecked exception than they are in the case of an checked exception.

The simple guideline is:
If you are throwing an exception for an abnormal condition that you feel client programmers should consciously decide how to handle, throw a checked exception.

Note that when String.charAt(int index) receives a bad input, it doesn't throw RuntimeException or even IllegalArgumentException. It throws StringIndexOutOfBoundsException. The type name indicates that the problem was a string index, and the program can query the object to find out what the bad index was.

Here is a collection of the exception guidelines put forth by an article:
  • If your method encounters an abnormal condition that it can't handle, it should throw an exception.
  • Avoid using exceptions to indicate conditions that can reasonably be expected as part of the normal functioning of the method.
  • If your method discovers that the client has breached its contractual obligations (for example, by passing in bad input data), throw an unchecked exception.
  • If your method is unable to fulfill its contract, throw either a checked or unchecked exception.
  • If you are throwing an exception for an abnormal condition that you feel client programmers should consciously decide how to handle, throw a checked exception.
  • Define or choose an already existing exception class for each kind of abnormal condition that may cause your method to throw an exception.
Here's a summary of the mechanical aspects of exceptions:

Runtime exceptions
  • A method signature does not need to declare runtime exceptions
  • A caller to a method that throws a runtime exception is not forced to catch the runtime exception
  • Runtime exceptions extend from RuntimeException or Error

Checked exceptions
  • A method must declare each checked exception it throws
  • A caller to a method that throws a checked exception must either catch the exception or throw the exception itself
  • Checked exceptions extend from Exception

Java Checked vs Unchecked Exception

Some guidelines about check and uncheck exception:
  • Only exceptions that will cause a method to complete abruptly should appear in its throws clause.
  • There are two kinds of exceptions in Java, checked and unchecked, and only checked exceptions need appear in throws clauses.
  • Any checked exceptions that may be thrown in a method must either be caught or declared in the method's throws clause.
  • Whether or not an exception is "checked" is determined by its position in the hierarchy of throwable classes.
  • To create a new checked exception, you simply extend another checked exception. All throwables that are subclasses of Exception, but not subclasses of RuntimeException are checked exceptions.
  • Most unchecked throwables declared in java.lang (subclasses of Error and RuntimeException) are problems that would be detected by the Java virtual machine.
  • Errors usually signal abnormal conditions that you wouldn't want a program to handle.
  • If you are throwing an exception to indicate an improper use of your class, you are signalling a software bug. The class of exception you throw probably should descend from RuntimeException, which will make it unchecked. Otherwise, if you are throwing an exception to indicate not a software bug but an abnormal condition that client programmers should deal with every time they use your method, your exception should be checked.
  • At least one clause, either catch or finally, must be associated with each try block. If you have both catch clauses and a finally clause with the same try block, you must put the finally clause after all the catch clauses

Monday, August 31, 2009

Why set download header to x-download?

It’s important to set the Content-Type header to a non-standard value such as application/x-download because, although the HTTP specification provides a mechanism for file downloads, many browsers second-guess the server's directives and do what they think is best rather than what they're told.

These browsers--including Microsoft Internet Explorer and Opera--look at the file extension and "sniff" the incoming content. If they see HTML or image content, they inline-display the file contents instead of offering a Save As dialog. Turns out there are no 100% reliable ways to download a file across all browsers.

According to a reference site, the HTTP specification recommends setting the Content-Type to application/octet-stream. Unfortunately, this causes problems with Opera 6 on Windows (which will display the raw bytes for any file whose extension it doesn't recognize) and on Internet Explorer 5.1 on the Mac (which will display inline content that would be downloaded if sent with an unrecognized type). So, the best way to cater for max scenario case coverage will be to set to application/x-download.

Some Java String & Collections API notes

Some summary of String and Collections API usage to remind myself :)

Criteria to choose among String, StringBuffer and StringBuilder:
1. If your text is not going to change use a string Class because a String object is immutable.

2. If your text can change and will only be accessed from a single thread, use a StringBuilder because StringBuilder is unsynchronized.

3. If your text can changes, and will be accessed from multiple threads, use a StringBuffer because StringBuffer is synchronous.


Collections API:
1. Vectors and Hashtable classes are available from the initial JDK 1.0. But, ArrayList and HashMap are added as a part of new Collections API since JDK 1.2.

2. Vectors and Hashtable are synchronized where as ArrayList and HashMap are unsynchronized.

3. Use Vector if there are multiple threads and ArrayList if there is only a single thread.

4. Use Hashtable if there are multiple threads and HashMap if there is only a single thread.

Tuesday, January 6, 2009

Merge log files and sort the records in Linux

Recently I need to do merging of log files and sort the records according to timestamp. This is what I did, use the bulk replace file extension way to change the log files to .txt files, then applied the following command through Shell script.

#!/bin/sh

export MFILE=merge_file.txt
export SFILE=complete_file.txt

for file in `ls *.txt`
do

cat $file >> $MFILE

done
sort -k4,4 $MFILE > $SFILE
rm $MFILE


Note:
Log files are expected to have same format, otherwise the sorting will not be possible.

-k, --key = POS1[,POS2], means sorting by start a key at POS1, end it at POS2 (which is where the timestamp position in my log files)

Sunday, June 29, 2008

Bulk replace file extension in Linux

Recently need to do a mass rename of files extension to another in Linux environment. I rename them one by one using "mv" command, which is super slow if talking about 200 over files. Thanks to Sunny who provide me the following solution:

Replace all '.txt' file extension to '.log' extension and display "rename" command in console:
ls *.txt |awk ' {s=substr($1, 1, length($1) - 4); print "mv " s ".txt " s ".log"}'

Executable mode of bulk replace file extension from '.txt' to '.log':
ls *.txt |awk ' {s=substr($0, 1, length($0) - 4); system("mv " s ".txt " s ".log")}'

This save me lots of time, probably yours too. :)

Thanks again, Sunny!

Wicket training over the weekend in UK

Never thought would have a chance to attend any training while in an oversea trip. First time ever to travel 6500 miles, and had the opportunity to take part in a JWeekend Wicket 2 days course. The course was held by Al Maw and Cemal on Fri & Sat, 21st to 22nd March in London.

Normally when I attend trainings back in Malaysia, I experienced lots of "theory" poet reader, which nicely shutdown people's attention, or "here's-the-point-and-i'll-read-it-to-you" type of training. This time, I had lots of practical in the training which firmly sets the experience of using wicket in real. This really helps a lot for an entry level user like me.

The training pace is just nice for me to catch up though on the second day find it a little difficult to digest after the nice Thai lunch! Thanks to Al and Cemal's patience, slowly guide me through all the exercises, make me excited to continue explore the wicket feature.

The training breakdown into modules which easy for me to know what are the topics to be covered. To understand all in a day or 2 is definitely not easy, however, again, emphasized on the experience that Al had, able to explain something in different angle should he finds me not able to understand it. Thanks to his patience to guide me through until I get it!

I'm really grateful to Cemal as well who's willing to setup a laptop for my hand's on lab session. I couldn't bring mine due to my shoulder's injury and was a last minute decision which I did not inform JWeekend prior to the training. This really shows their commitment to take care of their students. So, thanks again, Cemal!

All in all, I enjoyed the training, moreover, I've gained the knowledge that could help me get started in using wicket. Definitely something that you might want to go for if you're looking for a wicket training.

Create/Drop DB in Oracle

Create DB

1) Create file init[dbname].ora to the directory /u01/app/oracle/xxx/xxx/dbs folder (change db_name=[dbname])

2) Create directory /u01/app/oracle/admin/[dbname]

3) Create the directories bdump, cdump and udump in the /u01/app/oracle/admin/[dbname] directory

4) Do a chmod 777 on the /u01/app/oracle/admin/[dbname] directory and sub directories.

5) Prepared the createdb.sql script. Sample script as follow:

CREATE DATABASE dbx
USER SYS IDENTIFIED BY sys
USER SYSTEM IDENTIFIED BY system
LOGFILE GROUP 1 ('/u01/app/oracle/oradata/dbx/redo01.log') SIZE 100M,
GROUP 2 ('/u01/app/oracle/oradata/dbx/redo02.log') SIZE 100M,
GROUP 3 ('/u01/app/oracle/oradata/dbx/redo03.log') SIZE 100M
MAXLOGFILES 5
MAXLOGMEMBERS 5
MAXLOGHISTORY 1
MAXDATAFILES 100
MAXINSTANCES 1
CHARACTER SET WE8ISO8859P15
DATAFILE '/u01/app/oracle/oradata/dbx/system01.dbf' SIZE 325M REUSE
EXTENT MANAGEMENT LOCAL
SYSAUX DATAFILE '/u01/app/oracle/oradata/dbx/sysaux01.dbf' SIZE 325M REUSE
DEFAULT TEMPORARY TABLESPACE tempts1 TEMPFILE '/u01/app/oracle/oradata/dbx/temp01.dbf' SIZE 20M REUSE
UNDO TABLESPACE undotbs01 DATAFILE '/u01/app/oracle/oradata/dbx/undotbs01.dbf' SIZE 200M;

6) Make these files executable (chmod 755 createdb.sql)

7) Switch to user oracle su – oracle

8) Type export ORACLE_SID=[dbname]

9) Type sqlplus /nolog

10) Connect as sysdba

11) get SQL>Connected to an idle instance.

12) Type startup pfile=init[dbname].ora nomount

Should get ORACLE instance started with output as following:

Total System Global Area 707335948 bytes
Fixed Size 452364 bytes
Variable Size 134217728 bytes
Database Buffers 570425344 bytes
Redo Buffers 2240512 bytes

13) Execute the script @/oracle/createdb.sql

14) Run @/u01/app/oracle/product/xxx/rdbms/admin/catalog.sql

Before run the following script, make sure to check the SYSTEM tablespace size whether it is sufficient or not. If not, add datafiles to it, alter the datafile to be auto extend, to resize the tablespace.

15) Run @/u01/app/oracle/product/xxx/rdbms/admin/catproc.sql

After 15) step, check if there's any invalid objects with the following sql (should returns no rows):
SELECT owner, object_name, object_type FROM dba_objects WHERE status='INVALID' ORDER BY owner, object_type, object_name;

16) Connect as user System (sqlplus system/system_password)

17) Run @/u01/app/oracle/product/xxx/sqlplus/admin/pupbld.sql

18) Create Tablespace needed for the database

19) Create User + grantprovide necessary privilege


Drop DB

$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on Fri Feb 18 20:15:26 2005

Copyright (c) 1982, 2004, Oracle. All rights reserved.

SQL> connect / as sysdba
Connected to an idle instance.

SQL> shutdown abort;
ORACLE instance shut down.

SQL> startup nomount;
ORACLE instance started.

Total System Global Area 612368384 bytes
Fixed Size 790352 bytes
Variable Size 174321840 bytes
Database Buffers 436207616 bytes
Redo Buffers 1048576 bytes

SQL> alter database mount exclusive;

Database altered.

SQL> alter system enable restricted session;

System altered.

SQL> drop database;

Database dropped.

Oracle EE Installation Part II

Let's continue with the second and third section of the Oracle EE Installation.

After all the pre-installation preparation, you can start install Oracle EE by issuing the following command:

$ /directory_path/runInstaller [-silent] [-noconfig] -responseFile responsefilename

For example,
./runInstaller -silent -responseFile /home/oracle/source/database/response/enterprise.rsp

You should be able to see the similar result during the installation:

oracle@linux:~/source/database> ./runInstaller -silent -responseFile /home/oracle/source/database/response/enterprise.rsp
Starting Oracle Universal Installer...
Checking installer requirements...

Checking operating system version:
must be redhat-3, SuSE-9, redhat-4, UnitedLinux-1.0, asianux-1 or asianux-2 Passed
All installer requirements met.

Checking Temp space: must be greater than 80 MB. Actual 337313 MB Passed
Checking swap space: must be greater than 150 MB. Actual 1027 MB Passed
Preparing to launch Oracle Universal Installer from /tmp/OraInstall2007-01-16_11-09-35AM. Please wait ...oracle@raja:~/source/database> Oracle Universal Installer, Version 10.2.0.1.0 Production
Copyright (C) 1999, 2005, Oracle. All rights reserved.

You can find a log of this install session at:
/u01/app/oracle/oraInventory/logs/installActions2007-01-16_11-09-35AM.log
.................................................................................................... 100% Done.
Loading Product Information
................................................................................................................... 100% Done.
Analyzing dependencies
.........................................................................
Starting execution of Prerequisites...
Total No of checks: 11
Performing check for CertifiedVersions
Checking operating system requirements ...
Expected result: One of redhat-3,redhat-4,SuSE-9,asianux-1,asianux-2
Actual Result: SuSE-9
Check complete. The overall result of this check is: Passed
Check complete: Passed
=======================================================================
Performing check for Packages
Checking operating system package requirements ...
Checking for make-3.79; found make-3.80-184.1. Passed
Checking for binutils-2.14; found binutils-2.15.90.0.1.1-32.5. Passed
Checking for gcc-3.2; found Not found. Failed <<<< semmsl="250;" semmsl="250." semmns="32000;" semmns="32000." semopm="100;" semopm="100." semmni="128;" semmni="128." shmmax="536870912;" shmmax="536870912." shmmni="4096;" shmmni="4096." shmall="2097152;" shmall="2097152." max="65536;" max="209689." version="2.6.5-7.97;" version="2.6.5-7.97-smp." ip_local_port_range="1024" ip_local_port_range="1024" rmem_default="262144;" rmem_default="262144." rmem_max="262144;" rmem_max="262144." wmem_default="262144;" wmem_default="262144." wmem_max="262144;" wmem_max="262144." passed ==================================================== atleast="2.3.3-98.28"
passed ====================================================
passed ====================================================
passed ====================================================
passed ====================================================
passed ====================================================
passed ====================================================

Post Installation
After the installation, below are the steps you need to do for post installation:

Make sure ORACLE_HOME environment variable is set

Run the following configuration scripts:
a) Execute as root, /u01/app/oracle/product/xxx/xxx/root.sh

b) Goto sqlplus and login as SYSTEM
# sqlplus /nolog
SQL>connect as sysdba
SQL>system/system
SQL>@/u01/app/oracle/product/10.2.0/rdbms/admin/utlrp.sql

c) At command prompt, run the following script
$ $ORACLE_HOME/bin/genclntst

Phew.. that's all for Silent Mode Oracle EE Installation. There are other places to look into as well, but will save it for other days. ^_^