Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, April 17, 2008

Update /etc/hosts with IP address assigned through DHCP

My /etc/hosts file looks something like:

127.0.0.1       localhost
127.0.1.1 shihabpc
The host name shihabpc should be mapped to my network's IP address; not to a loop back IP address like 127.0.1.1. This is some how mandatory for RMI to work properly.
But the problem is that I have used DHCP to assign IP address and that is changed from one boot to another. So I have to change the /etc/hosts file every time my IP address changes.
So, I have written a script to update /etc/hosts:
#!/bin/sh
# /home/shihab/fixhosts.sh

file=/etc/hosts
interface=eth0

ip=`ip addr show $interface`
ip=`echo "$ip" | grep "inet "`
ip=`echo "$ip" | cut -d "i" -f 2`
ip=`echo "$ip" | cut -d " " -f 2`
ip=`echo "$ip" | cut -d / -f 1`

hostname=`hostname`

found=0
while read line
do
if [ "`echo "$line" | grep $hostname`" != "" ]; then
line="$ip $hostname"
found=1
fi
if [ -z "$text" ]; then
text="$line"
else
text="$text\n$line"
fi
done < $file

if [ found = 0 ]; then
text="$text\n$ip $hostname"
fi

echo -e "$text" > $file
And added it as an init.d script:
#!/bin/sh
# /etc/init.d/fixhosts

case "$1" in
start)
/home/shihab/fixhosts.sh
;;
stop)
# do nothing ;)
;;
restart)
$0 stop
$0 start
;;
*)
echo "usage: $0 (start|stop|restart|help)"
esac
$sudo update-rc.d fixhosts defaults 99
That's it! :-)

Sunday, August 12, 2007

Close resource inside and only inside finally block

Always close any resource (network connection, database connection, file stream) inside and only inside finally block. Don't close it inside try block. What is the problem of closing it inside try block? consider the following example:

try {
String fileName = ...;
InputStream input = new FileInputStream(fileName);
// read theContentOfTheFile
input.close();
retrun theContentOfTheFile;
} catch (IOException e) {
// log the exception
return null;
}

If an exception is thrown while reading theContentOfTheFile, the FileInputStream will never be closed.

A better solution but not totally perfect:
InputStream input = null;
try {
String fileName = ...;
input = new FileInputStream(fileName);
// read theContentOfTheFile
input.close();
retrun theContentOfTheFile;
} catch (IOException e) {
// log the exception
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// do nothing
}
}
}

If no exception is thrown inside the try block, then before returning from the method the finally block will also be executed. That means we are trying to close the same stream twice. So, an exception will always be thrown form the input.close() inside the finally block.

The best solution:
InputStream input = null;
try {
String fileName = ...;
input = new FileInputStream(fileName);
// read theContentOfTheFile
retrun theContentOfTheFile;
} catch (IOException e) {
// log the exception
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
// do nothing
}
}
}

In this example the input.close() is granted to be executed once and only once.

Tuesday, July 24, 2007

Use System.currentTimeMillis() instead of Date or Calendar

Always try to use System.currentTimeMillis() instead of java.util.Date or java.util.Calendar.

Why?

Because of performance. Date and Calendar internally calls System.currentTimeMillis(). So, why not use it directly?

A BAD example:

long currentTime = Calendar.getInstance().getTimeInMillis();
So, what does Calendar.getInstance() actually do? Following lines are just copied from the source code of jdk1.5:
public static Calendar getInstance()
{
Calendar cal = createCalendar(TimeZone.getDefaultRef(),
Locale.getDefault());
cal.sharedZone = true;
return cal;
}

private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
if ("th".equals(aLocale.getLanguage()) &&
("TH".equals(aLocale.getCountry()))) {
return new sun.util.BuddhistCalendar(zone, aLocale);
}
return new GregorianCalendar(zone, aLocale);
}

public GregorianCalendar(TimeZone zone, Locale aLocale) {
super(zone, aLocale);
gdate = (BaseCalendar.Date) gcal.newCalendarDate(zone);
setTimeInMillis(System.currentTimeMillis());
}
Have you got it? Calendar.getInstance() checks TimeZone, Locale and of course System.currentTimeMillis(). So, it's an expensive operation.

Another bad example:
Date date = new Date(System.currentTimeMillis());
Why is it bad? Because, it should be as simple as:
Date date = new Date();
And, here is the apidoc of default constructor of Date:
Allocates a Date object and initializes it so that
it represents the time at which it was allocated,
measured to the nearest millisecond.
Yet, another bad example:
Date date = Calendar.getInstance().getTime();
Now, when should we use System.currentTimeMillis():
When we need only the millisecond representation of the current time.

When should we use Date: When we need a date object representing the current time.

When should we use Calendar.getInstance(): When we need TimeZone or Locale specific information. Another use of Calender can be for creating constant Date object:
public static final Date INDEPENDENCE_DAY;

static {
Calendar calendar = Calendar.getInstance();
calendar.set(1971, Calendar.MARCH, 26);
INDEPENDENCE_DAY = calendar.getTime();
}

Friday, June 8, 2007

adding all jar files of a directory to classpath

how do you add all the jar files of your application's lib directory to classpath? probably as follows:

set CLASSPATH=%CLASSPATH%;%LIB_DIR%/activation.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/FTPProtocol.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/jai.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/jakarta-oro.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/jaas.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/log4j.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/mail.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/rmicb.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/Tidy.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/trove.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/xalan.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/xerces.jar
set CLASSPATH=%CLASSPATH%;%LIB_DIR%/xml-apis.jar
but there is a easier way:
SETLOCAL ENABLEDELAYEDEXPANSION
for %%f in (%LIB_DIR%\*.jar) do set CLASSPATH=!CLASSPATH!;%%f
ENDLOCAL
note the ! sign around CLASSPATH and don't miss SETLOCAL/ENDLOCAL commands.

Saturday, May 19, 2007

jgoodies validation (very easy!!!)

for last couple of days i was looking into jgoodies validation. but i found that it doesn't have enough quick start guide or simple sample code. the sample code provided with jgoodies are too complex. i have searched the net but i failed.
then i asked hasan's help. he said, "give me the complex code, i will simplify it". then i think, why don't i do that. so here is my simple code.

first assume you have a domain object as follow:

public interface User {
public String getUserName();
public void setUserName(final String pUserName);
public String getPassword();
public void setPassword(final String pPassword);
}
and it's implementation UserImpl.

you also have a form with two text fields mUserNameTextField and mPasswordField

now first create a Validator class
public class UserValidator extends AbstractValueModel
implements Validator, User {
private User mUser = new UserImpl();
public Object getValue() {
return this;
}
public void setValue(Object pObject) {
// never used
}
public User getUser() {
return mUser;
}
public void setUser(final User pUser) {
mUser = pUser;
}
public ValidationResult validate() {
ValidationResult result = new ValidationResult();
if (ValidationUtils.isEmpty(mUser.getUserName())) {
result.addError("User name is required");
}
if (ValidationUtils.isEmpty(mUser.getPassword())) {
result.addError("Password is required");
}
return result;
}
public String getUserName() {
return mUser.getUserName();
}
public void setUserName(final String pUserName) {
mUser.setUserName(pUserName);
}
public String getPassword() {
return mUser.getPassword();
}
public void setPassword(final String pPassword) {
mUser.setPassword(pPassword);
}
}
in the form class create there fields
private ValidationResultModel mValidationResultModel =
new DefaultValidationResultModel();
private PresentationModel mPresentationModel =
new PresentationModel(new UserValidator());
private JLabel mMessageLabel = ValidationResultViewFactory.
createReportIconAndTextLabel(mValidationResultModel);
after initializing the form
Bindings.bind(userNameTextField,
mPresentationModel.getBufferedModel("userName"));
Bindings.bind(passwordTextField,
mPresentationModel.getBufferedModel("password"));
here "userName" and "password" are the properties of your domain class.

finally in the action handler for form submit
mPresentationModel.triggerCommit();
UserValidator validator =
(UserValidator) mPresentationModel.getBean();
ValidationResult result = validator.validate();
mValidationResultModel.setResult(result);
if (result.isEmpty()) {
// do your action handling here
}
isn't it very easy!!!