Eclipse Tips and Tricks

Eclipse is such a great tool for Java developer, but many of its feature is hidden and could be a while for a newbie to uncover it. Following is my favourite tips and tricks.

Note: The shortcuts in this post is applicable to Windows only

Type / Resource Searching

With a large project, often it’s tricky to find a particular class, XML file or other resources. Use CTRL+Shift+T to show the Open Type box, or CTRL+Shift+R for Open Resource box. Open types allows you to search for Java classes while open resources behaves more like a filesystem search, typically you would use this to look for XML, HTML, javascript, properties and so on.

You can also do wildcard searching. For example if you’re trying to find a class related to the keyword “Cat”, you can search *Cat*

Declaration /References Searching

While looking at existing program, It’s very common we need to lookup the declaration or a class or variable or search all locations where a particular class or variable is used (reference searching).

To open a declaration of a variable/type: highlight a variable or class/type reference and press F3 or right-click -> Go to declaration

To find references of a variable/type: right click a variable/type and go to the references menu

Keyboard Shortcuts

When you’re doing the same task a million times, cutting the cost of few extra mouse clicks does matter! Shortcuts in eclipse can be viewed/configured via Preferences (General -> Keys). Following are some of my favourite shortcuts:

Action Windows Shortcut Mac Shortcut Note
Toggle comment (on highlighted text) Ctrl+Shift+C Command+C In java this will toggle double forward-slashes comment (//), in XML the <!– comment –> syntax per-line
Toggle block comment (on highlighted text) Ctrl+Shift+/ Command+/ In java, enclose the highlighted text with /* comment */, in XML <!– comment –>
Switch active view Ctrl+F7 Ctrl+F7 Allow you to switch from Editor to Console, or any other open Views
Switch perspective Ctrl+F8 Ctrl+F8
Run preconfigured maven goals Alt+Shift+X, M Alt+Shit+X, M You can configure the maven goals via Run configuration (Run -> Run Configuration…). You have to focus on a project on the Project Explorer, or an editor window of the project’s resource
Run Unit Test Alt+Shift+X, T Alt+Shit+X, T

* Function keys on Mac require “fn” modifier. Eg: to press F6, press fn+F6

Method Call Hierarchy

This feature allows you to see what other classes calls a particular method. This is very useful when tracing down an exception, or listing the potentially impacted classes when refactoring a method.

Right click on a method, choose open call hierarchy or use CTRL+Alt+H shortcut. When you open the call hierarchy window, you can also expand each node to further drill down who called that method.

Code Generation

Eclipse came with pretty impressive code generation support. Some of my favourites are: getters/setters generators, toString generators, constructor generators, exeception try/catch block generators.

Most of this code generators feature can be accessed via Source menu or CTRL+Alt+S shortcut.

Java Code Template

If you have to include your company’s copyright policy, or some open source license header on every new java class you create, you can setup a code template. From Preferences, go to Java -> Code Style -> Code Template. On “Configure generated code and comments” select box, go to Code -> New Java files. You can insert additional comments on the top.

Configure SVN support

Eclipse doesn’t come with SVN support by default (due to some licensing restriction I think), and configuring one isn’t a straight forward task. Eclipse come with a concept of SVN provider and connector which has to be installed separately, and there are plenty possible options out there (which don’t always work).

To configure SVN support with Subversive provider and SVNKit connector:

  1. Go to Help -> Install New Software -> Select “Indigo” from “work with” dropdown list. This will cause Eclipse to first check all available plugins, and what has already installed (could take 15 min+)
  2. Open the “Collaboration” tree, and search for “Subversive SVN Team Provider”. Tick and continue with the installation process. Eclipse will ask for a restart when it’s done
  3. Installing the provider it’s a bit tricky. Once eclipse has restarted, open the “SVN Repositories” view by going to Windows -> Show View ->Other -> Search for SVN Repositories, and attempt to register / checkout a new repository. Subversive will realize you haven’t got any connector installed, and will show connector installation dialog. Pick the latest version SVNKit connector and install it

Optimistic Locking with JPA

A pretty common web-application problem is concurrent transaction handling. If you have a form to view and edit an entity, you need to consider if multiple user is going to be editing at the same time, and how to handle them

There are two popular approaches of solving concurrency problem: pessimistic locking, and optimistic locking. Pessimistic locking means access to shared resources is explicitly restricted until the transaction finishes. This is commonly achieved using two-phase locking algorithm found in most database products.

Consider one bank account owned jointly by one lovely couple Jim and Sue. Jim walk into an ATM wanting to see how much money he got, then withdraw $10 (represented by T1). About the same time Sue also want to withdraw $20 from another ATM. (It is assumed both T1 and T2 uses READ COMITTED isolation level which is the default level of many dbms, and the first select acquires exclusive write, eg: select-for-update in Oracle):

Time Jim (T1) Sue (T2)
t=1 select balance from account where account_id = 1
t=2 select balance from account where account_id = 1
t=3 * ATM waits for Jim to input how much he would like to withdraw * * blocked waiting T1 to commit *
t=4 update account set balance = balance – 10 where account_id = 1 * blocked waiting T1 to commit *
t=5 commit
t=6 * ATM waits for Sue to input how much she would like to withdraw *
t=7 update account set balance = balance – 20 where account_id = 1

At t=2 T2 will be blocked waiting until T1 commits. This is because T2 tries to read accound id 1 which had been changed by T1 but not yet comitted. Only by t=5 T2 is able to progress again. This might not be ideal, especially if Jim takes a while to think how much money he would like to withdraw, Sue might not be very happy thinking why her ATM machine just seem to hung.

With optimistic locking, as the terminology says, we’re being an optimist. We just simply assume a best case scenario where no other transaction is going to modify the object except us. However if another transaction happen to execute on the same time, only by then we do something about it.

Row versioning is a common strategy to achieve optimistic locking. With row versioning, each row is given a version number which gets incremented everytime it’s updated. Each transaction that performs read-then-update operation remembers the version of the row it’s reading, and perform a check on the update that it’s indeed still the same version.

The same example would look like following with row versioning optimistic locking:

Time Jim (T1) Sue (T2)
t=1 select balance, version from account where account_id = 1 (retrieved version = 0)
t=2 select balance, version from account where account_id = 1 (retrieved version = 0)
t=3 * ATM waits for Jim to input how much he would like to withdraw * * ATM waits for Sue to input how much she would like to withdraw *
t=4 update account set balance = balance – 10, version = version + 1 where account_id = 1 and version = 0 (update count = 1, version updated to 1)
t=5  update account set balance = balance – 20, version = version + 1 where account_id = 1 and version = 0 (this will wait until T1 commits)
t=6  commit
t=7 Update count of the update at t=5 is 0 beacuse T1 got in first. ATM could inform Sue that the account balance has changed since she checked it, and she should get the latest balance and try again.

Note that the most important thing here is Sue (T2) doesn’t have to wait Jim (T1) for his input — which can potentially be a long time.

JPA provide automatic support of row versioning via the @Version annotation. When you have entity with @Version annotated field or property, optimistic locking will be enabled automatically.

Following is example of a simplified bank account JPA entity with version field:

@Entity
public class Account {
  @Id @GeneratedValue private long id;
  private String name;
  private double balance;
  @Version long version;

  // Getters and setters omitted for brevity
}

Having a @Version annotated field allow JPA to detect if the entity is stale when it’s about to synchronize the change back to database. An OptimisticLockException will be thrown if update to a stale entity is made:

public void withdraw (long accountId, double amount) {
  em.getTransaction().begin();

  // Retrieve the account row from the database
  Account account = em.find(Account.class, accountId);

  // Check the account has enough money. Let's assume another transaction had updated the account at this point, and our account entity object is now stale
  Assert.isTrue(amount
  // Withdraw the amount from the account
  account.setBalance(account.getBalance() - amount);

  // OptimisticLockException will be thrown here because we're trying to update stale object
  em.getTransaction().commit();
}

Building a JBoss Ready Spring MVC Web App

Spring is a really cool J2EE extension framework incorporating Inversion of Control and Aspect Oriented Programming techniques, and JBoss is one of the first open-source J2EE container well-known in the community. However building a Spring based application to fit for a JBoss deployment isn’t always a straightforward task.

Spring provides an easy-to-use rapid code generation tool called “Spring Roo” so you don’t have to start from scratch to achieve most of the configuration plumbing. However the code generated by Roo assumes a minimalistic web container (such as tomcat) where almost all Java EE API modules are deployed on the application side — not on the container.

Although this topic is still widely open for discussion, the benefit of using a container managed modules includes ease of configuration, operation and maintenance. For example if you deploy your datasource on JBoss, it would provide you with the connection pool usage statistics.

This guide demonstrate process of developing a simple Phonebook application where user can list and add contacts. Following are the goals we’re trying to achieve:

  • Spring-based application generated by Spring Roo which should be suitable to deploy to JBoss container.
  • Minimal (none if possible) JBoss customization. The web-app we’ll create should deploy straight into a fresh-install JBoss container. Only stuff like datasources should need configuration on JBoss
  • Use JBoss provided Java EE API modules whenever possible. The JBoss server profile we’ll use is ‘default’ which already provide a lot of stuff, including servlet, JSP, JSTL, EL, JTA, EJB3, JPA and Hibernate.

This guide and the demo source code is written against following versions:

  • JBoss 6.0.0.Final & 7.1.1.Final
  • Spring Roo 1.2.2.RELEASE
  • JDK 6
  • Apache Maven 3.0.3

Let’s Start the Rapid Code Generation

Start the Spring Roo shell (either via command line or your favourite IDE) and use following commands:

  1. Create new war project. Adjust project name and top level package to your liking. IDE such as eclipse provide a dialog box to create a new project, feel free to use it instead.
     project --topLevelPackage com.wordpress.gerrytan.springjboss --projectName spring-jboss --packaging war 
  2. Setup JPA persistence. JBoss came with pre-installed HSQL datasource available via JNDI under the name java:/DefaultDS, so we’ll leverage this. Feel free to install and use another database if you want to. (If you use JBoss 7, the sample datasource JNDI name is java:/jboss/datasources/ExampleDS)
     jpa setup --database HYPERSONIC_PERSISTENT --provider HIBERNATE --jndiDataSource java:/DefaultDS 

    After you run this command, Roo will create a Spring applicationContext.xml configuration file that will scan and contain your data and business layer beans and JPA persistence.xml persistence unit configuration.

  3. Setup Spring MVC controller. If this is the first time you hear about Spring MVC, you might want to read their manual (or keep going — trust me, Spring MVC provides a powerful API for your web-app 🙂 )
     web mvc setup 

    After you run this command Roo will create a web.xml with Spring MVC DispatcherServlet configured, and a webmvc-config.xml that will scan and contain your Controller beans. Note that the webmvc-config.xml context will be set as a child of applicationContext.xml context so that your data layer beans will be instantiated first, and then injected to your controller beans. Roo will also configure JSP + Apache Tiles based views for you which we’ll cover later.

Great! At this point you have almost all the boilerplate and plumbing you need to start writing your web-app.

Start Writing the Web App

The small web app we’re going to write has one page with two panels, one for add-contact form, and the other for listing and deleting contacts:

  1. Create a new Contact entity with firstName, lastName and phoneNumber fields. We’ll again leverage Roo to do this. Issue following command on a Roo shell:
    entity jpa --class ~.Contact
    field string --fieldName firstName --notNull
    field string --fieldName lastName --notNull
    field string --fieldName phoneNumber --notNull
    
  2. Create (manually) a new Controller. I won’t use Roo this time because the controller code generation feature of Roo provides us more than we need, so we’ll just create a simple Spring MVC controller here. The controller has all handlers method to perform addition, listing and deletion. Familiarize yourself with Spring MVC Controller if this is the first time you see it.
    @Controller
    @RequestMapping("/contact")
    public class ContactController {
    
      @RequestMapping(method = RequestMethod.GET)
      public String get(@ModelAttribute("newContact") Contact contact) {
        return "contact/index";
      }
    
      @RequestMapping(method = RequestMethod.POST, params="deleteId")
      @Transactional
      public String delete(@RequestParam long deleteId) {
        Contact contact = Contact.findContact(deleteId);
        contact.remove();
        return "redirect:/contact";
      }
    
      @RequestMapping(method = RequestMethod.POST)
      public String add(@ModelAttribute("newContact") @Valid Contact contact, BindingResult bindingResult) {
        if (!bindingResult.hasErrors()) {
          contact.persist();
          return "redirect:/contact";
        }
        return "contact/index";
      }
    
      @ModelAttribute("contacts")
      public List getContactList() {
        List result = Contact.findAllContacts();
        return result;
      }
    }
    
  3. Create the view, we’ll leverage the Apache Tiles API provided by Roo. Tiles adds much-needed templating and inheritance feature to JSP so it’s easy for you to reuse parts of your presentation code in multiple place. Have a look at their manual page for more info. Create a jspx file src/main/webapp/WEB-INF/views/contact/index.jspx which will contain our jsp view presentation code to list Contacts and add a new one:
        <!-- HTML headers and other stuffs omitted for brevity -->
    
        <!-- Add Contact Form --></pre>
    <div><span class="label">First Name</span>
    
     <span class="label">Last Name</span>
    
     <span class="label">Phone Number</span>
    
     <input type="submit" value="Add Contact" /></div>
    <pre>
        <!-- List Contacts --></pre>
    <div>
    
     You have no contacts in your phone book. Add a new contact using the form above.
    
    <table>
    <thead>
    <tr>
    <th>Id</th>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Phone Number</th>
    <th><!-- empty column --></th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <td>${contact.id}</td>
    <td>${contact.firstName}</td>
    <td>${contact.lastName}</td>
    <td>${contact.phoneNumber}</td>
    <td><form method="POST"><input type="hidden" name="deleteId" value="${contact.id}" />
     <input type="submit" value="Delete" /></form></td>
    </tr>
    </tbody>
    </table>
    </div>
    <pre>
        <!-- HTML footers and other stuffs omitted for brevity -->
    

    And create a views.xml tiles configuration file. This file contains metadata information about template, inheritance, and other tiles feature. Since this is just a simple web-app, I’m not superclassing any other page or template, but just create a new standalone jsp page

    <tiles-definitions>
      <definition name="contact/index" template="/WEB-INF/views/contact/index.jspx">
      </definition>
    </tiles-definitions>
    

That’s about all the code we’ll need for this web-app. Now is the slightly tricker part, plumbing Spring into JBoss.

EntityManagerFactory Plumbing

When you setup JPA using Roo, it gives you a Spring-managed persistence unit via LocalContainerEntityManagerFactoryBean. However when you deploy your app to JBoss, the presence of META-INF/persistence.xml also causes JBoss to create its own persistence unit, causing conflict. Of course you can avoid JBoss from creating a persistence unit and keep the Spring-managed ones if you want, but the approach we’ll take here is to use the JBoss provided:

  1. Configure the JNDI name of the JBoss-provided persistence unit. Add following element to your web.xml. <persistence-unit-ref-name>persistence/spring-jboss-emf</persistence-unit-ref-name> will be the JNDI name of the JBoss provided persistence unit, and <persistence-unit-name>persistenceUnit</persistence-unit-name> is the name Roo give to the persistence unit configuration file (META-INF/persistence.xml)
      <persistence-unit-ref>
        <persistence-unit-ref-name>persistence/spring-jboss-emf</persistence-unit-ref-name>
        <persistence-unit-name>persistenceUnit</persistence-unit-name>
      </persistence-unit-ref>
    
  2. Replace LocalContainerEntityManagerFactoryBean with JNDI lookup on applicationContext.xml
    <!-- <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
            <property name="persistenceUnitName" value="persistenceUnit"/>
            <property name="dataSource" ref="dataSource"/>
        </bean> -->
    
    
  3. Let the persistence unit know what the datasource JNDI name is. We’ll just use the sample HSQL datasource which came with out-of-the-box JBoss install (java:DefaultDS on JBoss 6 and java:jboss/datasources/ExampleDS on JBoss 7). Add <non-jta-data-source> element to your META-INF/persistence.xml file:
    <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <non-jta-data-source>java:DefaultDS</non-jta-data-source>
                <!-- remaining code truncated for brevity -->
    
    

    We didn’t have to do this with Spring-managed persistence unit because LocalContainerEntityManagerFactoryBean already done it for us. Change java:DefaultDS into java:jboss/datasources/ExampleDS if deploying into JBoss 7.

  4. And since we already done step 3, we no longer need to keep the datasource bean on applicationContext.xml. Feel free if you want to keep it though
     <!-- <jee:jndi-lookup id="dataSource" jndi-name="java:DefaultDS"/> --> 

Maven Fine Tuning

We’re nearly there. This last bit is related to Maven (the build, packaging, and dependency management tool):

  1. (Only if you use eclipse) Change java.version properties on pom.xml from 6 into 1.6. You might not need to do this but I use eclipse and somehow I couldn’t get it to run in jdk 6 mode unless I change it. Right click on your project –> choose Maven –> Update project configuration once you’ve done this
  2.  Change the scope of following Maven dependencies into “provided”. These are the dependencies that will be provided by JBoss, so unless you mark it as so, Maven will include it on the war file (and potentially causing classpath conflict)
    hibernate-core
    hibernate-entitymanager
    hibernate-jpa-2.0-api
    hibernate-validator
    validation-api
    jta
    jstl-api
    jstl-impl
    slf4j-api
    slf4j-log4j12
    log4j
    jcl-over-slf4j
    

    You can change the scope of a dependency by adding <scope>provided</scope> element. The default if not provided is “compile”

        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>3.6.9.Final</version>
          <scope>provided</scope>
        </dependency>
    

Compile, Deploy and Cross Your Fingers

Here comes the moment of truth!

  1. Run mvn clean package command to compile and package your war file. Once it completes you will get a target/spring-jboss-1.0-SNAPSHOT.war file. Deploy this file by placing it to your %JBOSS_HOME%\server\default\deploy folder
  2. Start your JBoss server
  3. Open http://localhost:8080/spring-jboss-1.0-SNAPSHOT/contact on your web browser
  4. Enjoy your JBoss-ready Spring MVC web-app 🙂

Check the Demo Sourcecode

The demo sourcecode for this blog post is available here:

Note that if your code output some logging content, it’s best to use the slf4j logging API. Slf4j provides an abstraction of all other available logging APIs so your code will still work regardless of which logging implementation is used.

It Doesn’t Work!

Relax, it does take time to get everything in place. Here are few tips for troubleshooting JBoss deployed Spring web app (apart from the obvious: inspecting the exception, stack trace, logs, etc):

  1. Review all the ‘plumbing’ work, make sure there’s no leak on the pipe! Following are the list of all the configurations file we’ve touched in this guide:
    pom.xml
    src/main/resources/META-INF/spring/applicationContext.xml
    src/main/resources/META-INF/persistence.xml
    src/main/web-app/WEB-INF/spring/webmvc-config.xml
    src/main/web-app/WEB-INF/web.xml
    
  2.  Review the jars included inside your war file against the one provided by JBoss. If you think you’re packaging something already provided by JBoss, maybe you should mark the dependency as “provided”
  3. Consult the manuals, reference guide, and ask the community