Guava Splitter

Guava Splitter is a utility class that is offering roughly speaking the opposite of what the Joiner utility class does.

You can have a read at my previous quick article about Guava Joiner.

Splitter is offering similar look-and-feel as Joiner: the on method serves as a static factory method, subsequent method calls are following the builder pattern returning a wrapped this (therefore need to be packed prior the final split method call). Finally it doesn’t try to be complicated returning an Iterable of Strings. It is aspiring in replacing the usage of String.split method.

Its usage when we want to get back an Iterable of Strings looks like:

 
Splitter.on(",").trimResults().split("my,string,to,split")

When we want to perform the operation retrieving a Map out of its String representation:

Splitter.on(",").trimResults().omitEmptyStrings().withKeyValueSeparator("->").split("one->1,two->2,three->3")

In this instance the call to withKeyValueSeparator is yielding a Splitter.MapSplitter inner class that is adding the map context to the splitter.

Advertisements

Guava Joiner

Guava Joiner is a nice utility class that is String-ing data structure contents, useful for debugging, logging, reporting or toString-ing activities in a flexible, builder pattern-esque and fluent way.

What we used to achieve with this conventional code:

public static final String joinIterable(final Iterable iterable, String delimiter){
   if(iterable == null)
      throw new IllegalArgumentException();
   StringBuilder result = new StringBuilder("Conventional iterable join: ");
   for(T elem : iterable){
      result.append(elem).append(delimiter);
   }
   result.setLength(result.length() - 1);
   return result.toString();
}

public static final String join(final List list, String delimiter){
   return joinIterable(list, delimiter);
}

can now be achieved with:

Joiner.on(",").useForNull("null").join(list)

The Joiner class is a utility class and the on method represents a static factory method that returns a new Joiner. The useForNull method follows the builder pattern returning a wrapped version of this (therefore need to be packed prior the final join method call). Be carefull that this call is needed otherwise null elements will throw a NPE. The join method is passing the Iterable in this case data structure.

Similarly for maps, what we used to achieve with this:

    public static final <K,V> String join(final Map<K,V> map, String delimiter){
        if(map == null)
            throw new IllegalArgumentException();
        StringBuilder result = new StringBuilder("Conventional map join: ");
        for(K key : map.keySet()){
            result.append(key).append("->").append(map.get(key)).append(delimiter);
        }
        result.setLength(result.length() - 1);
        return result.toString();
    }

can now be achieved by:

Joiner.on(",").withKeyValueSeparator("->").useForNull("null").join(map)

In this instance, the withKeyValueSeparator method call is returning a Joiner.MapJoiner that is a static class that is adding the map context to the Joiner class.

Spring, JdbcTemplate, Oracle example

This is a demonstration of how Spring and Oracle are playing happily together via JdbcTemplate.

Prerequisites:

Let’s start from the end: this is how the JUnit 4 test case looks like for the DAO of our domain object for all its CRUD operations armored with rollback functionality so our database data are not being altered after our transactional operations. Notice the use of matchers and the spring-context-enabling annotation of the test class:

package com.dimitrisli.springJdbcOracle.dao.impl;

import com.dimitrisli.springJdbcOracle.dao.LocationDao;
import com.dimitrisli.springJdbcOracle.model.Location;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/spring/context/applicationContext.xml")
@TransactionConfiguration(transactionManager = "jdbcTransactionManager", defaultRollback = true)
@Transactional
public class LocationDaoTest {

    @Inject private LocationDao locationDao;

    @Test
    public void testSelectAllLocations(){
    List<Location> locations = locationDao.getLocations();
    assertThat(locations.size(), is(23));
    }

    @Test
    public void testSelectOneLocation(){
      Location location = locationDao.getLocation(1000L);
      assertNotNull("test entry not found", location);
    }

    @Test
    public void testDeleteLocation(){
        assertNotNull("entry for test should be there", locationDao.getLocation(1000L));
        locationDao.deleteLocation(1000L);
        assertNull("entry wasn't successfully deleted", locationDao.getLocation(1000L));
    }

    @Test
    public void testInsertLocation(){
        Location location = new Location(1000L,"test","11111","athens","athens","IT");
        int sizeBeforeInsert = locationDao.getLocations().size();
        locationDao.createLocation(location);
        assertThat(locationDao.getLocations().size(),is(sizeBeforeInsert + 1));
    }

    @Test
    public void testUpdateLocation(){
        Location newLocation = new Location(1000L,"test","11111","athens","athens","IT");
        locationDao.updateLocation(newLocation);
        Location changedLocation = locationDao.getLocation(1000L);
        assertThat(changedLocation.getStreetAddress(), is("test"));
    }

}

The POM looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>SpringJdbcOracle</groupId>
    <artifactId>SpringJdbcOracle</artifactId>
    <version>1.0</version>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

            <!--Logging related plugin
                this plugin breaks the build if non-wanted logging frameworks are spotted in the classpath
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>1.0.1</version>
                <executions>
                    <execution>
                        <id>enforce-versions</id>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <bannedDependencies>
                                    <excludes>
                                        <exclude>commons-logging:commons-logging</exclude>
                                        <exclude>log4j:log4j</exclude>
                                    </excludes>
                                </bannedDependencies>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!--Spring related dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>


        <!--Oracle jdbc driver-->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>

        <!-- DB Connection Pool -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

        <!--Logging related dependencies
            Further info: http://www.slf4j.org/faq.html#excludingJCL and
                          http://blog.frankel.ch/configuring-maven-to-use-slf4j
        -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <!--scope should be runtime but applied at compile time
                to get autocompletion visibility at logback.xml-->
            <!--scope>runtime</scope-->
            <version>0.9.24</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.2</version>
        </dependency>

        <!-- JUnit 4 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

        <!-- Misc -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
            <scope>runtime</scope>
        </dependency>


    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>3.1.2.RELEASE</spring.version>
     </properties>


</project>

Notes:
– Note how we explicitly piping any commons logging or log4j logging through our logback slf4j wrapper
– Notice how we are declaring our Oracle driver dependency given that it’s already installed in our local Maven repo (see prerequisites section)

The applicationContext:

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <import resource="classpath*:spring/database/database.xml"/>
    <context:component-scan base-package="com.dimitrisli.springJdbcOracle" />
</beans>

The imported database context above is:

<?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:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
           p:location="properties/database.properties" />

    <bean  id="dataSource"
           class="org.apache.commons.dbcp.BasicDataSource"
           destroy-method="close"
           p:driverClassName="${jdbc.driverClassName}"
           p:url="${jdbc.url}"
           p:username="${jdbc.username}"
           p:password="${jdbc.password}" />

    <bean  class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"
           c:dataSource-ref="dataSource"  />

    <bean  id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
            p:dataSource-ref="dataSource"/>
    <tx:annotation-driven transaction-manager="jdbcTransactionManager"/>

</beans>

Notes:

– We are using DBCP for our DB connection pool datasource
– We are using the parameter namespace to save on some attribute injection open-close xml characters
– We are explicitly stating NamedParameterJdbcTemplate as our jdbcTemplate and inject it with the needed datasource so we can have it available for injection conveniently in our DAOs.

The domain POJO object we are about to play with is the Location object that corresponds to the Locations table on the Oracle HR schema:


package com.dimitrisli.springJdbcOracle.model;

public class Location {

    private Long locationId;
    private String streetAddress;
    private String postalCode;
    private String city;
    private String stateProvince;
    private String countryId;

    public Location(Long locationId, String streetAddress, String postalCode, String city, String stateProvince, String countryId) {
        this.locationId = locationId;
        this.streetAddress = streetAddress;
        this.postalCode = postalCode;
        this.city = city;
        this.stateProvince = stateProvince;
        this.countryId = countryId;
    }

//getters, hashcode(), equals(), toString() ignored for brevity

The RowMapper that will provide Location objects having resultSets coming from the DB. It’s a factory method (although not static but stateless by our design) used internally from Spring per DB line result returned:

package com.dimitrisli.springJdbcOracle.orm;

import com.dimitrisli.springJdbcOracle.model.Location;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;

@Component
public class LocationRowMapper implements RowMapper<Location> {

    @Override
    public Location mapRow(ResultSet rs, int rowNum) throws SQLException {
        return  new Location(rs.getLong("LOCATION_ID"),
                             rs.getString("STREET_ADDRESS"),
                             rs.getString("POSTAL_CODE"),
                             rs.getString("CITY"),
                             rs.getString("STATE_PROVINCE"),
                             rs.getString("COUNTRY_ID"));
    }
}

Here’s the DAO interface responsible for the CRUD operations:

package com.dimitrisli.springJdbcOracle.dao;

import com.dimitrisli.springJdbcOracle.model.Location;

import java.util.List;

public interface LocationDao {

    public void createLocation(Location location);
    public List<Location> getLocations();
    public Location getLocation(Long locationId);
    public void updateLocation(Location location);
    public void deleteLocation(Long locationId);

}

and its implementation looks like this:


package com.dimitrisli.springJdbcOracle.dao.impl;

import com.dimitrisli.springJdbcOracle.dao.LocationDao;
import com.dimitrisli.springJdbcOracle.model.Location;
import com.dimitrisli.springJdbcOracle.orm.LocationRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;

@Repository("locationDao")
public class LocationDaoImpl implements LocationDao {

    private static final String CREATE_SQL = "INSERT INTO LOCATIONS( LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, " +
                                             "STATE_PROVINCE, COUNTRY_ID) " +
                                             "VALUES (LOCATIONS_SEQ.NEXTVAL, :streetAddress, :postalCode, :city, " +
                                             ":stateProvince, :countryId)";

    private static final String GET_ALL_SQL = "SELECT LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, STATE_PROVINCE, COUNTRY_ID " +
                                              "FROM LOCATIONS";

    private static final String GET_SQL = "SELECT LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, STATE_PROVINCE, COUNTRY_ID " +
                                          "FROM LOCATIONS WHERE LOCATION_ID = :locationId";

    private static final String DELETE_SQL = "DELETE LOCATIONS WHERE LOCATION_ID = :locationId";

    private static final String UPDATE_SQL = "UPDATE LOCATIONS SET STREET_ADDRESS = :streetAddress, POSTAL_CODE=:postalCode, " +
                                            "CITY = :city, STATE_PROVINCE = :stateProvince, COUNTRY_ID = :countryId " +
                                            "WHERE LOCATION_ID = :locationId";

    @Inject private NamedParameterJdbcOperations jdbcTemplate;
    @Inject private LocationRowMapper locationRowMapper;

    @Override
    public void createLocation(Location location) {
        SqlParameterSource params = new MapSqlParameterSource()
                .addValue("streetAddress", location.getStreetAddress())
                .addValue("postalCode", location.getPostalCode())
                .addValue("city", location.getCity())
                .addValue("stateProvince", location.getStateProvince())
                .addValue("countryId", location.getCountryId());
        jdbcTemplate.update(CREATE_SQL, params);
    }

    @Override
    public List<Location> getLocations() {
        return jdbcTemplate.query(GET_ALL_SQL, new HashMap<String, Object>(), locationRowMapper);
    }

    @Override
    public Location getLocation(Long locationId) {
        SqlParameterSource params = new MapSqlParameterSource()
                .addValue("locationId", locationId);
        List<Location> locations = jdbcTemplate.query(GET_SQL, params, locationRowMapper);
        return locations.isEmpty()?null:locations.get(0);
    }

    @Override
    public void updateLocation(Location location) {
        SqlParameterSource params = new MapSqlParameterSource()
                .addValue("locationId", location.getLocationId())
                .addValue("streetAddress", location.getStreetAddress())
                .addValue("postalCode", location.getPostalCode())
                .addValue("city", location.getCity())
                .addValue("stateProvince", location.getStateProvince())
                .addValue("countryId", location.getCountryId());
        jdbcTemplate.update(UPDATE_SQL, params);
    }

    @Override
    public void deleteLocation(Long locationId) {
        jdbcTemplate.update(DELETE_SQL, new MapSqlParameterSource("locationId",locationId));
    }
}

Notes:
– Notice how we inject the JdbcTemplate and not fetching it from this class directly
– Notice how we inject the RowMapper and we don’t anonymous-class-it from this class directly
– The CRUD operations are setup parameterized in the top of the file as private static finals
– In all the CRUD operations we are using either jdbcTemplate.update() or jdbcTemplate.query() methods

Here’s the Github repo of the project

Install Java 6,7,8 on Mac OS X

Here’s a quick guide to have Java versions 6,7,8 installed on Mac OS X above and beyond.

Java 6

Java 6 is the last supported version provided by Apple. Therefore we’ll follow the Apple way to install the JDK although Java 1.6 can be branched out from Oracle or the OpenJDK project.

Successful installation will place Java 6 under /Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/. Following that you can mark JAVA_HOME or point your IDE towards /Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Home/. Also to browse the JDK under an IDE point your editor to the JDK sources found in /Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Home/src.jar

Java 7

We need to go out in the wild to get JDK 7 installed on Mac OS X since mother-Apple doesn’t support it. We can download it either from Oracle or OpenJDK:

Successful installation will place Java 7 under /Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/. Following that you can mark JAVA_HOME or point your IDE towards /Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/Contents/Home/. Also to browse the JDK under an IDE point your editor to the JDK sources found in /Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/Contents/Home/src.jar

Java 8

We can get a copy of the latest snapshot of JDK 8 to play around with the lambda expressions (natively supported on IntelliJ IDEA) if you haven’t tried already closures in Groovy, Scala or just Predicates/Functions in Google Guava from this download resource

Successful installation will place Java 8 under /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/. Following that you can mark JAVA_HOME or point your IDE towards /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/. Also to browse the JDK under an IDE point your editor to the JDK sources found in /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/src.jar

Groovy, Scala closures demonstration

This is a quick demo of closures usage for Groovy and Scala side-by-side.

Let’s get an easy study case where we are trying to identify whether a string contains unique characters. Starting with Java we would have:

Java

public class StringAllUniqueChars {

    public static boolean hasStringAllUniqueChars(String str){

        //cache data structure
        final HashSet<Character> stackConfinedCache = new HashSet<Character>();
        //imperative iteration
        for(Character c : str.toCharArray()){
            if(stackConfinedCache.remove(c))
                //fail fast
                return false;
            else
                stackConfinedCache.add(c);
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println("hello\t" + StringAllUniqueChars.hasStringAllUniqueChars("hello"));
        System.out.println("helo\t" + StringAllUniqueChars.hasStringAllUniqueChars("helo"));
    }
}

Keypoints:

  • We create a data structure to store the findings along the way and fail fast in case of the first dup char found
  • We iterate over the chars of the string using a for loop

Groovy

def hasStringAllUniqueChars(str){

    str.collect {         //in a collection
            str.count(it)    //the occurrences of each char
        }
        .findAll {
            it>1    //filter those with more than one occurrences
        }
        .size()==0  //make sure they don't exist
}

def hasStringAllUniqueChars2(str){
    !   //if we don't
    str.any{       //find any
        str.count(it)>1    //character occurrence in string more than once
    }
}

println "hello\t" + hasStringAllUniqueChars2("hello")
println "hello\t" + hasStringAllUniqueChars("helo")

Keypoints:

  • We are running it in a form of Groovy script
  • We are making use of the default it reference while being on a closure
  • In the first implementation we are first transforming the string characters into a collection of corresponding character sizes. Then we are filtering only duplicate characters and finally we are taking the decision based on whether we have any dups across all chars.
  • In the second implementation we are taking a shortcut using Groovy’s any method hand-picking in its closure only dup characters

Scala

object StringAllUniqueChars {

  def hasStringAllUniqueChars(str: String) =

    !str.exists{  //if we don't find any case where
      c =>    //each character's
        str.count(_==c)>1       //count in the string is greater than 1
    }

  def main(args: Array[String]){
    println("hello\t"+hasStringAllUniqueChars("hello"))
    println("helo\t"+hasStringAllUniqueChars("helo"))
  }

}

Keypoints:

  • We are using an Object since we want to host our main method somewhere. It’s Scala’s way to address static and normally the so-called companion object is grouping all the static content of its corresponding class.
  • We are employing closures in a similar way as the second Groovy implementation using Groovy’s exists and count methods

For a matter of completeness this is how Scala, Groovy and Java are co-existing happily together during compile/run time under the Maven umbrella:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ScalaGroovyClosures</groupId>
    <artifactId>ScalaGroovyClosures</artifactId>
    <version>1.0</version>

    <build>
        <plugins>
            <!--java compiler-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>

            <!--scala compiler-->
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!--groovy compiler-->
            <plugin>
                <groupId>org.codehaus.groovy.maven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <version>1.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy.maven.runtime</groupId>
            <artifactId>gmaven-runtime-1.6</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

Java Swing Scrollbar

This is a quick demo on how to add a Java Swing scrollbar following the footpaths of this previous example if you need detailed explanation on the Swing construct so far.

Without further ado the code looks like so:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SwingScrollBarDemo {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MyFrame("Hello Swing World!");
            }
        });
    }
}

//Branching out of a JPanel to create our more complicated
//component which for now will only serve as a wrapper around
//JTextArea, with its own layout and its scrollable functionality
class MyTextComponent extends JPanel {

    //state of our custom text
    private final JTextArea text = new JTextArea();

    MyTextComponent(){
       //this component has a layout in its own right
       setLayout(new BorderLayout());
       add(getScrollable(), BorderLayout.CENTER);
    }

    //A fancy way to confine in a method the sole purpose
    //of this whole exercise: to wrap JTextArea around a
    //JScrollPane, serving when we are adding the
    //component into the panel
    private JScrollPane getScrollable(){
        //this is where the magic happens wrapping JScrollPane
        //around JTextArea
        return new JScrollPane(this.text);
    }

    void append(String text){
        this.text.append(text);
        this.text.append("\n");
    }
}

//Pay attention on that we are implementing ActionListener
//More comments to follow below on that
class MyFrame extends JFrame implements ActionListener {

    //state of the frame: a button and some text
    private final JButton button = new JButton("Click me!");
    private final MyTextComponent text = new MyTextComponent();

    MyFrame(String title){
        //boilerplate begins
        super(title);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200,300);
        setLocationRelativeTo(null);
        //boilerplate ends

        //Setting an easy Layout that is positioning components based
        //on intuitive compass signs
        setLayout(new BorderLayout());

        //Pay attention that the class is implementing ActionListener
        //therefore the button is adding this to its action listener.
        //This practically means every time the button is clicked
        //the overriden actionPerformed method of this class will be
        //called and will append some text to the text component
        button.addActionListener(this);

        //Last but not least adding the two components into the
        //frame passing as well as a second parameter their
        //position inside the layout
        add(text, BorderLayout.CENTER);
        add(button, BorderLayout.SOUTH);
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        //If we are here it's because the button was clicked
        //therefore it's time to do something exciting with the
        //text component
        text.append("Button Clicked!");
    }
}
  • All we are doing in this example following incrementally this previous example so far (you can follow the comments if you want to skip reading the article) is to add a separate class to wrap around a JTextArea component.
  • The sole state of the new class is the JTextArea and in its constructor includes a separate BorderLayout. Before adding the JTextArea into its own layout it is wrapping it around JScrollPane which gives the effect of horizontal/vertical side scrolls effect into our text area inside of the broader frame.

Java Swing Components and Layout basic example

This is a basic example demonstrating a Swing frame with two components and a basic interaction between them.

You might also want to take a look at the bare minimum Swing app that is demonstrating all the boilerplate needed code demonstrated in this article.

The source code looks like this:


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class BasicComponentsLayouts {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new InnerFrame("Hello Swing World!");
            }
        });
    }
}

//Pay attention on that we are implementing ActionListener
//More comments to follow below on that
class InnerFrame extends JFrame implements ActionListener {

    //state of the frame: a button and some text
    private JButton button = new JButton("Click me!");
    private JTextArea text = new JTextArea();

    InnerFrame(String title){
        //boilerplate begins
        super(title);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200,300);
        setLocationRelativeTo(null);
        //boilerplate ends

        //Setting an easy Layout that is positioning components based
        //on intuitive compass signs
        setLayout(new BorderLayout());

        //Pay attention that the class is implementing ActionListener
        //therefore the button is adding this to its action listener.
        //This practically means every time the button is clicked
        //the overriden actionPerformed method of this class will be
        //called and will append some text to the text component
        button.addActionListener(this);

        //Last but not least adding the two components into the
        //frame passing as well as a second parameter their
        //position inside the layout
        add(text, BorderLayout.NORTH);
        add(button, BorderLayout.SOUTH);
    }

    @Override
    public void actionPerformed(ActionEvent actionEvent) {
       //If we are here it's because the button was clicked
       //therefore it's time to do something exciting with the
       //text component
       text.append("Button Clicked!");
       text.append("\n");
    }
}

Some comments:

  • This time we have a state in our frame, namely a button and a text area
  • Pay attention that our JFrame child is implementing ActionListener. This interface brings us the actionPerformed() overriden method that fires when this frame is used as a listener somewhere.
  • Other than the ceremonial code of frame visibility etc we have the setLayout() method where we define a nice basic BorderLayout(). For more information on layouts please have a look at this useful link.
  • Next stop is where we are adding our frame using its identity as ActionListener (we are implementing this interface remember?) to the button component. This effectively means that when the button gets clicked the ActionListener overriden method will fire.
  • Last piece of the puzzle before the end of the frame constructor and effectively completing the initialisation it’s the addition of both components to the frame using BorderLayout compass points depicted through static intuitive fields.
  • Finally we have the sole method of ActionListener which gets overriden in the Frame child class where we are not using its parameter but rather grabbing the text field (part of the frame state remember?) and appending a basic message that will reflect in a text string every time the listener gets invoked.

Java Swing basic example

This is the bare minimum that we need in order to have a Java Swing application up and running.

The code looks like this:

import javax.swing.*;

public class BasicFirstExample {

    public static void  main(String ... args){
        //Avoiding threading issues by invoking the frame through an anonymous
        //inner class via the static Swing Utilities method as follows
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Initialization the frame with a title as parameter
                //in the constructor
                JFrame myFirstFrame = new JFrame("Hello Frame World!");
                
                //Here comes the boilerplate code:
                
                //Setting the frame as visible. If it was not there
                //we wouldn't see the frame
                myFirstFrame.setVisible(true);
                //Setting the close-down of the application upon clicking the
                //close button in the swing frame. If it was not there, the JVM
                //would be holding on there even after closing down the swing through the button
                myFirstFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                //Setting the size of the frame according to our needs. If this
                //wasn't there the default width is non-existant and the length barely visible
                //for a couple of chars of title
                myFirstFrame.setSize(200,100);
                //Setting the default position of the frame in the center of the screen.
                //If that wasn't there it will be initialized at the top left of the screen
                myFirstFrame.setLocationRelativeTo(null);
            }
        });
    }
}

Things to note:

  • We are first creating a JFrame instance call the constructor with a String as a parameter representing it’s title bar inscription.
  • We are are then calling setVisible(true) on the instance because surprisingly enough by default the visibility is set to false then non-visible.
  • We are then setting setDefaultCloseOperation() method because if we are not then after we close the little swing app from the close button the java application will still remain alive and running although counter-intuitive.
  • We are then setting setSize() because the default values are barely living any space for the title and almost non width space.
  • We are then calling setLocalisationRelativeTo() because otherwise our little Swing app will reside on the top left corner of our screen by default. Calling this method with null parameter will initialise it in the center of the screen.
  • All of the above are found in the body of an anonymous inner Runnable#run() call that is passed as a parameter inside the static SwingUtilities#invokeLater() method as per the suggestions of Sun in order for us not to run into unwanted exceptions following the rule of thumb of not setting state to components from within threads we are instantiating.

Performing a bit of housekeeping, namely including all the JFrame specific actions on a separate child class we could deduce the clutter inside the Runnable#run() method and extract it on the constructor of the child JFrame class. Besides all these actions we’ve seen (setting visibility, setting size, setting exit on close, setting relative position) are integral parts of the initialization of the frame and this makes total sense to include them within the constructor:

import javax.swing.*;

public class BasicFirstExample2 {

    public static void main(String ... args) {
         SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
                 new MyFrame("Hello Frame World!");
             }
         });
    }

}

class MyFrame extends JFrame{

    MyFrame(String title) {
        super(title);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200,100);
        setLocationRelativeTo(null);
    }
}

How to postpone Spring Application Context instantiation

We are first calling the two args application context constructor passing false as a flag:

 ApplicationContext context = new ClassPathXmlApplicationContext( new String[] {"config/myApplicationContext.xml"}, false );

then whenever we are done with our processing we handpick and load the beans we are interested to include:

context.getBeanFactory().registerSingleton("dataSource", myTestDataSource);

finally we initialise manually:

context.refresh();

Spring, EHCache, Maven Integration

Here’s a quick Maven project with the absolute minimal for a “hello world” EHCache example.

EHCache exists as a dependency in the central Maven repo so no need to add additional repo information. Also this is a special dependency that requires dependency.type to be specified as pom. Finally the only dependency is on SLF4J for logging purposes so I’ve added LOGBack. The POM looks like this:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dimitrisli</groupId>
  <artifactId>ehcacheFirstExample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>2.5.0</version>
      <type>pom</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>ch.qos.logback</groupId>
    	<artifactId>logback-classic</artifactId>
    	<version>1.0.0</version>
    </dependency>
  </dependencies>
</project>

The EHCache configuration file served in xml flavor has the default name ehcache.xml and looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
	<cache name="sampleCacheFromEhcacheXml"
	    maxElementsInMemory="500"
	    eternal="false"
	    timeToIdleSeconds="300"
	    timeToLiveSeconds="300"
	    overflowToDisk="false">
	 </cache>
</ehcache>

Some things to notice:

  • The generic ehcache tag includes the cache tag with all its parameters as attributes.
  • maxElementsInMemory: this is the max number of elements that the cache can hold.
  • timeToIdleSeconds: this is the number of seconds elements can live in the cache without being requested.
  • timeToLiveSeconds: this is the number of seconds elements can reside inside the cache.
  • eternal: this is overriding both the two previous parameters if set to true and it does what it says in the box, it keeps the elements for the length the cache lives into the memory.
  • A nice alternative is the parameter overflowToOffHeap which if set to true then the cache is stored outside of the Heap! This way the cache is not entitled to Garbage Collection slow downs and the performance can be increased as advertised in the EHCache website. Unfortunately all this power comes with a cost, namely to activate the off-heap storage a licence key is needed after a 30 days trial. Here’s a speed/size/memory diagram:


Finally the test class looks like this:

package com.dimitrisli.ehcache;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class EHCacheFirstExample {

	private final CacheManager cacheManager;
	private final Cache cache;

	public EHCacheFirstExample(){
		//cacheManager = new CacheManager(getClass().getResource("/src/main/resources/ehcache.xml"));
		cacheManager = CacheManager.create();
		cache = cacheManager.getCache("sampleCacheFromEhcacheXml");
	}

	public Cache getCache() {
		return this.cache;
	}

	public void addElementToCache(Element element){
		this.cache.put(element);
	}

	public static void main(String[] args) {
		EHCacheFirstExample fe = new EHCacheFirstExample();
		fe.addElementToCache(new Element("myCacheEntryKey","myCacheEntryVal"));
		for(Object key : fe.getCache().getKeys()){
			System.out.println(key + ":"+ (String) fe.getCache().get(key).getObjectValue());
		}
	}
}

A couple of things to notice: the CacheManagercan be created either as a singleton through its static factory method

CacheManager.create()

or a new instance specifying as a URL the location of the EHCache property file. Moreover the “convention over configuration” mantra of Maven makes

src/main/resources

the ideal place for the ehcache.xml properties file to live. Finally the Cache object as well as the Element object are not generic objects therefore making the iteration a bit cumbersome and the runtime-checking/casting feeling so 1.4

You can find the code in this github repository