Tuesday, May 26, 2009

GWT with maven and eclipse

Setting up a latest GWT project in eclipse along with Maven was not straight forward. Here is step-by-step guide on how I managed to setup my environment.

I assume you have Eclipse installed with m2eclipse plugin. Also Maven installed and its maven executable is in your environment PATH.

Run the below maven archetype to create a project shell. I named my project gwttest.

mvn archetype:create -DarchetypeGroupId=com.totsp.gwt -DarchetypeArtifactId=maven-googlewebtoolkit2-archetype -DarchetypeVersion=1.0.4 -DgroupId=com.gwttest -DartifactId=gwttest

The above command will create a directory "gwttest".

In the generated pom.xml, change the gwt version to the version you are using. The version should be available in the maven repository. I used latest GWT version 1.6.4. Also remove the pluginRepositories and unpack plugin from the pom.xml as that it is not required.

Create an Application.launch file in your project with the below content. Launch file is required to run the project from Eclipse.

<?xml version="1.0" encoding="UTF-8"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER" javaProject="gwttest" path="1" type="4"/> "/>
<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry internalArchive="gwttest/src/main/java" path="3" type="2"/> "/>
<listEntry value="<?xml version="1.0" encoding="UTF-8"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento project="gwttest"/> </runtimeClasspathEntry> "/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="gwttest"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.HostedMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war target\gwttest-1.0-SNAPSHOT com.gwttest.Application"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256M"/>
<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
</launchConfiguration>


In Eclipse go to File > Import > General > Maven Projects. Select the directory "gwttest" and finish.

To generate a war file right click on the project > Run As > Maven package. The war file will be created under gwttest\target folder.

To test right click on the Application.launch file > Run As > Application. The sample GWT application will start in hosted mode.

To debug right click on the Application.launch file > Debug As > Application.

Thursday, May 21, 2009

Maven web application

As mentioned in my POC, I used maven to develop the sample application.

You need latest maven installed on your system.

Execute this command to create a web application structure.

mvn archetype:create -DgroupId=com.travel -DartifactId=travel -DarchetypeArtifactId=maven-archetype-webapp

Replace the pom.xml with this xml. This is the final pom of my POC. Notice the exclusion of asm and cglib libraries in hibernate dependency and explicitly defining asm version 2.2.3 and cglib 2.1_3. It's because there was confict between asm library versions required by hibernate and cxf.


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.travel</groupId>
<artifactId>travel</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>travel Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.3.1.GA</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
</exclusion>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.1_3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.1.GA</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
</exclusion>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.6.SEC01</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-core</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
<build>
<finalName>travel</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>


After this you can import this project in Eclipse. Go to File > Import > General > Maven Projects. For this m2eclipse plugin needs to be installed in your Eclipse.

Apache cxf using annotations and integration with Spring

Today I will show you how you can create a webservice using Apache CXF version 2.2.1. I will be building this webservice on top of my previous application.

Create a interface AirlineManager to expose methods over webservice. The create method takes airline code and name to create a Airline record in database. Annotation @WebService tells that this is a interface for webservice.

package com.travel;

import javax.jws.WebService;

@WebService
public interface AirlineManager {
public void create(String code, String name);
}

Implement the above webservice interface. We are using AirlineDao created in earlier post. Notice the @WebService(endpointInterface = "com.travel.AirlineManager") which tells that this implementation is for AirlineManager interface.

package com.travel;

import com.travel.dao.AirlineDao;
import javax.jws.WebService;

@WebService(endpointInterface = "com.travel.AirlineManager")
public class AirlineManagerImpl implements AirlineManager {
private AirlineDao airlineDao;

public AirlineManagerImpl(AirlineDao aAirlineDao) {
airlineDao = aAirlineDao;
}

@Override
public void create(String code, String name) {
airlineDao.create(code, name);
}
}

Add this in the spring-context.xml. Here we are importing some cxf beans, defining bean AirlineManagerImpl and creating airlineManagerService webservice.

<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<bean id="airlineManager" class="com.kaleconsultants.travel.AirlineManagerImpl">
<constructor-arg><ref bean="airlineDao"/></constructor-arg>
</bean>

<jaxws:endpoint id="airlineManagerService" implementor="#airlineManager" address="/AirlineManagerService" />

Add this in your web.xml.

<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

Deploy the application in tomcat and your webservice is ready. You can check the wsdl http://host:port/travel/AirlineManagerService?wsdl.

To test the webservice, you need to create a client. You can use wsdl2java available in the bin directory of cxf.

Execute this command, this will generate the wsdl stubs.
wsdl2java http://host:port/travel/AirlineManagerService?wsdl

Write a client like this and there you go.......

package com.travel;

public class ClientTest {
public static void main(String[] args) {
AirlineManagerImplService service = new AirlineManagerImplService();
AirlineManager airlineManager = service.getAirlineManagerImplPort();
airlineManager.create("IC", "Indian");
}
}

Wednesday, May 20, 2009

Hibernate integration with Spring

In my last post Basic Hibernate Annotations example, I wrote about a simple hibernate example. Today I will take that example forward and show you how you can integrate hibernate with Spring. I used Spring version 2.5.6.SEC01.

Create spring-context.xml file. We define a spring datasource, hibernate session factory, hibernate template(spring wrapper api of hibernate session), transaction manager. Bean airlineDao is configured to use annotation based transaction handling. The "<tx:annotation-driven/>" actually enables Spring container to execute methods under transaction, if transaction annotations are used.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/travel"/>
<property name="resourceRef" value="true" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="configLocation"><value>classpath:hibernate.cfg.xml</value></property>
<property name="configurationClass"><value>org.hibernate.cfg.AnnotationConfiguration</value></property>
</bean>

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>

<tx:annotation-driven/>

<bean id="airlineDao" class="com.travel.dao.AirlineDao">
<property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property>
</bean>
</beans>

Create AirlineDao class. Notice the @Transactional (readOnly = true) annotation which brings the execution of this class under transaction. The create method have (readOnly = false) because in this method we are actually updating the table.

package com.travel.dao;

import com.travel.domain.Airline;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Transactional (readOnly = true)
public class AirlineDao extends HibernateDaoSupport {
@Override
@Transactional (readOnly = false)
public void create(String code, String name) {
Airline airline = new Airline();
airline.setCode(code);
airline.setName(name);
getHibernateTemplate().save(airline);
}
}

Add the below xml in your web.xml. This Spring ContextLoaderListener initializes the spring beans defined in file spring-context.xml (we created above).

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring-context.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Create a simple servlet to test the DAO. The execution of this servlet will create a new airline record in airline table.

package com.travel.servlet;

import com.kaleconsultants.travel.dao.AirlineDao;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AirlineServlet extends HttpServlet {
private static final long serialVersionUID = 2409603422056073641L;

protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

String code = request.getParameter("code");
String name = request.getParameter("name");
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
AirlineDao airlineDao = (AirlineDao) context.getBean("airlineDao");
airlineDao.create(code, name);
}
}

Monday, May 18, 2009

Basic Hibernate Annotations example

As part of my POC, today I developed a simple hibernate annotations based example. To run this example, you need JDK 5.0 or higher and hibernate 3.2.0.GA or above. I am using JDK 1.6, MySql 5.1, Tomcat 6.0.18 and Hibernate 3.3.1.GA.

Create hibernate.cfg.xml file. This file should be available in the classpath at runtime. I developed this example as part of a web application and I am using a datasource defined in my container. See my earlier post on How to configure a datasource in Tomcat


<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/travel</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="show_sql">true</property>
<mapping class="com.travel.domain.Airline"/>
</session-factory>
</hibernate-configuration>


This example needs following table in your database.


CREATE TABLE airline (
code char(2) PRIMARY KEY,
name varchar(50) NOT NULL,
created timestamp DEFAULT NOW() NOT NULL
);


Create HibernateUtil class which provides Hibernate session to interact with database. new AnnotationConfiguration().configure() looks for hibernate.cfg.xml in the classpath, so make sure to deploy the file in WEB-INF/classes directory.


package com.travel.hibernate.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtil {
private static final SessionFactory sessionFactory;

static {
try {
sessionFactory = new AnnotationConfiguration().configure()
.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}


Airline class maps with the airline table we created above. Notice the annotations used to define the mapping.


package com.travel.domain;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "airline")
public class Airline implements Serializable {
private static final long serialVersionUID = 6864693643526282786L;
@Id
@Column(name = "code")
private String code;
@Column(name = "name")
private String name;
@Column(name = "created")
private Date createdTime;

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Date getCreatedTime() {
return createdTime;
}
}


Simple servlet to test the application. I used the hibernate code directly in my servlet for simplicity. You should define one DAO layer to encapsulate the hibernate code. To test acccess your servelt use url like http://host:port/travel/AirlineServlet?code=LH&name=Lufthansa


package com.travel.servlet;

import com.travel.domain.Airline;
import com.travel.hibernate.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AirlineServlet extends HttpServlet {
private static final long serialVersionUID = 2409603422056073641L;

protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
SessionFactory session = HibernateUtil.getSessionFactory();
Session sess = session.getCurrentSession();
Transaction tx = sess.beginTransaction();
// Get the airline code and name
String airlineCode = request.getParameter("code");
String airlineName = request.getParameter("name");
// Create Airline object
Airline airline = new Airline();
airline.setCode(airlineCode);
airline.setName(airlineName);
// Save the record in database
sess.save(airline);
tx.commit();
session.close();
}
}

How to configure a datasource in Apache Tomcat

I have to build a POC (proof of concept) using JDK6, Spring, Hibernate and Apache CXF on Apache Tomcat. I will be using Maven build tool and Nexus repository. My IDE is Eclipse with m2eclipse and spring IDE plugin. In a nutshell we need a webservice application and I have chosen these technologies to develop the solution. I thought it would be a good idea if I blog on how I developed this POC. I will do step-by-step development.

Lets start with "How to configure a datasource in Apache Tomcat".

There is another way of configuring datasource in Tomcat, but I prefer this solution as the configuration resides in the application war file. Simply copy your war file in a tomcat server along with the required jdbc jar and your application is up and running. I wish I can bundle the jdbc jar also in war but unfortunately it doesn't work.

Create a file name "context.xml" (any other name will not work) in META-INF directory of your war file. The content of the context.xml will look like this -

<Context path="/travel" debug="5" reloadable="true" crossContext="true">
<Resource name="jdbc/travel" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="user" password="password" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/travel?autoReconnect=true"/>
</Context>

Add this in the web.xml of your war -

<resource-ref>
<description>Datasource</description>
<res-ref-name>jdbc/travel</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

The res-ref-name should match the //Resource@name defined in the context.xml

Copy the required jdbc driver jar in $TOMCAT_HOME/lib directory. In this case its mysql-connector-java-5.1.6.jar for mysql database.

Friday, May 15, 2009

Project Euler Problem 3

Problem 3

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

The solution is to find a factor and check if its a prime number. Since we need largest prime factor, run the for loop in reverse direction. Also a prime factor of a number cannot be greater than the square root of the number.


public class ProblemThree {
public static void main(String[] args) {
long range = (long) Math.sqrt(600851475143L);

for (long i = range; i > 1; --i) {
if ((0 == (number % i)) && isPrimeNumber(i)) {
System.out.println(i);

break;
}
}
}

public static boolean isPrimeNumber(long number) {
long halfRange = number / 2;

for (long i = 2; i <= halfRange; ++i) {
if (0 == (number % i)) {
return false;
}
}

return true;
}
}

Thursday, May 14, 2009

Rich Internet application

Web based application having desktop like GUI is popularly known as RIA(Rich Internet Application). I need to develop such a rich interactive web based application. In old days we used to have only few solutions - Java applet, Flash, Dynamic html. Nowadays there are loads of frameworks which provide desktop like experience. These frameworks are based on ajax technology.

I thought it would be easy to select the best framework for my need. But on the contrary the choices are many, that its difficult to choose. The best part of open source technology is for every problem there are numerous solutions. But the worst part is choosing the right technology for your need. I wish, I can find an easy comparison chart somewhere.

I did some search and found these frameworks - Adobe Flex, extJS, Jboss Richfaces, IceFaces, Oracle ADF, JavaFX, Silverlight, GWT, IT Mill Toolkit, ZK, OpenLaszlo, BackBase, Echo, Morfik, Haxe, YUI, pyjamas, DWR, Prototype. There could be many more frameworks available. Over the next few days I will be evaluating these list to find the popularity, support, out-of-the-box GUI components, underlying technology and any other parameter which helps in selecting few solutions. Once I am down to two or three solutions, I would like to develop a simple application to select the right solution.

Wednesday, May 13, 2009

Project Euler Problem 2

Today I got some time to look at Euler Problem 2.

Problem 2

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

The solution is to run a loop to find the next term in Fibonacci series. Check the evenness of the term and add to the sum.


public class ProblemTwo {
public static void main(String[] args) {
int firstTerm = 0;
int secondTerm = 1;
int newTerm = 0;
int sum = 0;

while (secondTerm <= 4000000) {
newTerm = firstTerm + secondTerm;

if (0 == (newTerm % 2)) {
sum += newTerm;
}

firstTerm = secondTerm;
secondTerm = newTerm;
}

System.out.print(sum);
}
}

Monday, May 11, 2009

Project Euler Problem 1

Recently I came across Project Euler web site. This is what the site has to say

"Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve. Although mathematics will help you arrive at elegant and efficient methods, the use of a computer and programming skills will be required to solve most problems. The motivation for starting Project Euler, and its continuation, is to provide a platform for the inquiring mind to delve into unfamiliar areas and learn new concepts in a fun and recreational context."

I quickly registered to check what kind of mathematical problems are asked. I couldn't resist myself to start solving the problems. I chose Java to solve the problems as this is the only language I know ;)

Problem 1

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.

The solution is very simple and the code is self explanatory.

public class ProblemOne {
public static void main(String[] args) {
int result = 0;

for (int i = 1; i < 1000; ++i) {
if ((0 == (i % 3)) || (0 == (i % 5))) {
result += i;
}
}

System.out.println(result);
}
}

Wednesday, May 6, 2009

.equals Vs == in Java

Recently a Java developer asked for help in a J2EE application. He was stuck in a bug for the past two days. The development environment was Windows, Eclipse IDE and Tomcat server. He was using old mill fashion of debugging by adding System.out.println in his code. Before anything else I asked him to setup debugger in Eclipse. The debugger made his life easy and helped him quickly figure out the problem area. But he couldn't understand why a particular if condition not behaving correctly. As you can guess from the title of this blog, it was the same age old problem of == and .equals().

In Java == is used to compare variables of primitive data types (byte, short, int, long, float, double, boolean, char). If == is used to compare two objects then it compares the object reference and not the values. An object in Java stores the memory reference where the object data is stored. In order to compare the values you need to use object1.equals(object2). Lets learn the difference with simple example -

String s1 = new String("test");
String s2 = new String("test");

Here we have defined two String objects s1 and s2. Value of both the variable is same "test", so we expect the variables to be equal.

if (s1 == s2) {
  System.out.println("Strings are equal");
} else {
  System.out.println("Strings are not equal");
}

Surprised to see that it prints "Strings are not equal". Well its correct as both s1 and s2 are referring to two different memory references.

if (s1.equals(s2)) {
  System.out.println("Strings are equal");
} else {
  System.out.println("Strings are not equal");
}

The above code is correct way of comparing String values. This code will print "Strings are equal". Now consider this below code -

String s1 = "test";
String s2 = "test";

if (s1 == s2) {
  System.out.println("Strings are equal");
} else {
  System.out.println("Strings are not equal");
}

Another surprise, it prints "Strings are equal". Its because Java compiler does the optimization. Notice the way s1 and s2 are defined. In earlier code we used new String("test") which makes sure new object gets created. But in this code compiler uses the same reference to define the two variables.

== and .equals() usage holds true for objects of any class. Remember every Java class implicitly extends Object class. Most of the Java core classes like Integer, Long, Double, Boolean, etc have .equals() method implemented. For your own class don't forget to implement the .equals() otherwise .equals() will behave same as ==.

Tuesday, May 5, 2009

Configure Eclipse for Remote Debugging

A J2EE developer always finds it difficult to debug a web application. The developer has to rely on log4j logging to understand what is happening. Although exception stack trace provides valuable info but at times it's not enough to debug a problem. Even for a trivial problem sometimes debugging takes ages. What if a developer can follow the execution in real-time and able to see the flow, values assigned to the variables, etc. Well a Java debugger is there to make debugging comfortable and quick. My favorite Eclipse IDE provides the remote debugging with lots of useful features.

But first we need to know how to enable a JVM to be debugged remotely. Any application server like JBoss, Tomcat, Weblogic, etc. or a simple JVM instance can be debugged remotely. Pass the following arguments to a JVM to enable remote debugging.

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n

If both the debugger and target JVM is 5.0 and above then the preferred way is given below, although the above will also work.

-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n

More information of Java debugger is available here

To enable Jboss or Tomcat for remote debugging, you need to set JAVA_OPTS environment variable with the above arguments. Start the server, the Java Debugger is ready to listen on the defined port.

Follow the below steps to configure Eclipse for debugging -

  • In Eclipse go to Run > Debug Configurations..., a popup will open.

  • Right click on "Remote Java Application" and select New.

  • Give some name so that you can identify this debugger.

  • Select a project which you want to debug.

  • Select "Standard (Socket Attach)" as Connection Type.

  • Provide the host and port details where the remote JVM is running. For the above example port number will be 8787.

  • Click on Debug and Eclipse will open the Debug perspective which provides lots of helpful features.


  • The first task to debug a problem is to set breakpoints in the code where you think the problem persists. Eclipse allows conditional breakpoints which gets triggered when the defined condition evaluates to true. At runtime value of a variable can be changed to debug the code. Another useful functionality is to add a Java exception breakpoint, which gets triggered when the said exception is thrown.