Month: November 2014

Spring Boot and Spring Data

Continuing on from the previous article, I finally managed to get to Spring Data. In a way, this is just Spring JPA and looks like this:

@Configuration
@EnableAutoConfiguration
public class Application {

  public static void main(String[] args) {

    ConfigurableApplicationContext context = SpringApplication.run(Application.class);
    PersonRepository repository = context.getBean(PersonRepository.class);

    for (Person person : repository.findAll()) {
      System.out.println(person);
    }
    context.close();
  }
}

Although this looks similar to the Hibernate JPA previously, there are some significant changes. The first is the use of a Repository interface, PersonRepository. This has to descend from the Spring Data Repository interface, usually via another interface:

public interface PersonRepository extends CrudRepository<Person, Long> {
}

I’ve used CrudRepository, the most basic, and given it the class name of the POJO and the type of the unique identifier, which is a Long. Notice that you have to use the class equivalent of the primitive type. You don’t need to define anything else if you don’t want to; CrudRepository defines the basic functions as standard:

public interface CrudRepository<T extends Object, ID extends Serializable> extends Repository<T, ID> {
  public <S extends T> S save(S s);
  public <S extends T> Iterable<S> save(Iterable<S> itrbl);
  public T findOne(ID id);
  public boolean exists(ID id);
  public Iterable<T> findAll();
  public Iterable<T> findAll(Iterable<ID> itrbl);
  public long count();
  public void delete(ID id);
  public void delete(T t);
  public void delete(Iterable<? extends T> itrbl);
  public void deleteAll();
}

As before, the field mappings have to be put directly in the POJO using annotations. Something to remember is that with Spring JPA you have to make sure the column names are lower case.

Next you have to configure the connection properties. This goes in a file called “application.properties”, the default:

spring.datasource.url=jdbc:jtds:sqlserver://localhost:1433/A_DB
spring.datasource.username=aaron
spring.datasource.password=********
spring.datasource.driverClassName=net.sourceforge.jtds.jdbc.Driver

You may have noticed in the application definition is the use of the EnableAutoConfiguration annotation. This is from Spring Boot, which is our next subject.

Spring Boot

So far, behind the scenes, so to speak, we’ve been adding dependencies into the Maven POM file with some abandon, but, to get Spring Boot working, we have to remove them. Why use Spring Boot? I can’t really give you a straight answer, other than to say there are a lot fewer problems when using Spring Data. Take my word for it.

As described in the starting guide instruction on the Spring Boot web site, you have to add the following:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.1.8.RELEASE</version>
</parent>

… which goes in the project root. Next you want something to tell Spring Boot to pull in the Data JPA layer:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

… which goes in the dependencies. Clear everything else out of the dependencies: this will cause all kinds of errors in the code, but resist the temptation to fix this by pulling in the dependencies. You will regret it if you don’t. Do a build (or clean and build), you’ll find that new dependencies have been pulled in via the parent and you don’t have to define anything. This also sorts out any import errors.

The dependencies that do have to be put in are specific to this particular project and that is the JTDS driver for MS SQL Server:

<dependency>
  <groupId>net.sourceforge.jtds</groupId>
  <artifactId>jtds</artifactId>
  <version>1.2</version>
</dependency>

You will be surprised to find that all this works straight away with no other configuration.

Spring Boot Web Services

So far, we’ve just been playing with the data, outputting the results to the console. To get it to do something useful, we need to introduce web services, in the form of a REST interface. This is what Spring Boot is really used for and this introduces the idea of Micro Services.

Micro Services are an architectural concept that takes componentisation to a system level. A system is divided up into sub-systems, each of which is considered a system in its own right, with its own security, metrics etc., and even its own built-in web server. These components are connected together using REST web services, so the definitions of these interfaces become very important. The implementation of one sub-system, or Micro Service, is independent of others, providing the interfaces are adhered to, so you can have one service built using .Net and another in Java, yet another in Node.js and JavaScript. There are lots of technologies being introduced and maturing that support, take advantage of or are being taken advantage of by this concept, in particular Docker, for deployment, Spring Boot and Drop Wizard for Java development.

Now we’ll add a REST service to the previous data project. First, we remove the data code from the Application class:

  public static void main(String[] args) {
    SpringApplication.run(Application.class);
  }

Exactly as before, just without the data code. This has been moved to the web service class, MyController:

@RestController
public class PersonController {

  @Autowired
  private PersonRepository repository;

  @RequestMapping("/")
  public String index() {
    StringBuilder sb = new StringBuilder();
    sb.append("<!DOCTYPE html>").append("<html lang='en'>");
    sb.append("<head>").append("<meta charset='UTF-8'>");
    sb.append("<title>Something, something</title>").append("</head>");
    sb.append("<body>");
    sb.append("<table>");
    for (Person person : repository.findAll()) {
      sb.append("<tr>");
      sb.append("<td>").append(person.getId()).append("</td>");
      sb.append("<td>").append(person.getFirstName()).append("</td>");
      sb.append("<td>").append(person.getLastName()).append("</td>");
      sb.append("</tr>");
    }
    sb.append("</table>");

    sb.append("</body>");
    sb.append("</html>");
    return sb.toString();
  }
}

The class is designated a RestController, which tells Spring that it’s the class that handles http requests as REST requests. The RequestMapping annotation tells it which path to respond to, in this case the root. I’m responding with a string at this point and creating a simple web page as the payload.

Notice that the repository is automatically created by annotating the declaration with @Autowired.

The POM has also been added to with Spring Boot dependencies, spring-boot-starter-web and spring-boot-starter-jetty:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

The former seems to be mostly used to enable the web services, but also to prevent Tomcat being used. Instead it used Jetty, which is simpler. The only other thing needed is to tell Maven that this is a Boot application, rather than a Java one:

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

That’s pretty much it. If you now run up the application, it will start Jetty on port 8080 and the response will be a web page with the Persons loaded from the database.

JSON

Instead of delivering an HTML page as the payload, we can deliver a JSON string. This is all built into Spring Boot and is just a case of altering the definition of the index function:

  @RequestMapping("/")
  public Person[] index() {
    List personList = new ArrayList();
    personList.addAll((Collection) repository.findAll());
    return personList.toArray(new Person[0]);
  }

findAll returns an Iterable, so this needs to be converted to an array via ArrayList. The array of JobType objects is coded to JSON and sent as the response automatically.

Scaling Business Application Development with Play and Scala

Yesterday evening, I went to see a presentation by Peter Hilton at Skills Matter on using Scala and Play for small-scale development.

In an affable and down-to-earth manner, Peter went through two case studies that his company had handled, both  web developments in Holland, where he is based. This is somewhat unusual for Scala in particular and any JVM-based language in general: normally much “lighter” technologies, such as ASP.Net or PHP, are used.

He highlighted the use of a stack of technologies, Play, Scala, Slick (for database connectivity and access), PostgreSQL and MySQL for the database and Bootstrap for the website layout. In particular, he went through the use of Slick, which he recommended, as it has an unusual, more SQL, feel compared to other ORM’s.

He also emphasised the speed of development and that the amount of code needed was much smaller than previous applications he’d developed: the first application was ~4000 lines and the second ~2000, which are both a lot smaller than the applications I’ve worked on. It was interesting to see how his team short-cutted: using social media for security (why not?) and Excel spreadsheet integration for record maintenance.

Overall, it was a good presentation about using Scala in a different way.

Database Integration with Java

The other week I saw a presentation on InfoQ regarding Spring Data, so I thought I’d have a look at how Java connects to databases.

JDBC

The most basic way of connecting to a database in Java is to use JDBC (Java Database Connectivity). This involves creating suitable objects, establishing a connection to the database, executing a SQL statement and parsing the results:

try {
      Connection connection = null;
      ResultSet resultset = null;
      try {
        Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
        connection = DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/A_DB",
                                                 "aaron",
                                                 "********");
        Statement statement = connection.createStatement();
        resultset = statement.executeQuery("SELECT "
                                           + "firstName, "
                                           + "lastName, "
                                           + "gender "
                                           + "FROM person");
        Person person;
        while (resultset.next()) {
          person = new Person();
          person.setFirstName(resultset.getString("firstName"));
          person.setLastName(resultset.getString("lastName"));
          person.setGender(resultset.getString("gender"));
          System.out.println(person);
        }

      } finally {
        if (resultset != null) {
          resultset.close();
        }
        if (connection != null) {
          connection.close();
        }
      }
    } catch (ClassNotFoundException ex) {
      Logger.getLogger(ConnectingUsingJDBC.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
      Logger.getLogger(ConnectingUsingJDBC.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
      Logger.getLogger(ConnectingUsingJDBC.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SQLException ex) {
      Logger.getLogger(ConnectingUsingJDBC.class.getName()).log(Level.SEVERE, null, ex);
    }

Legacy systems contain a lot of code just like this, or variations of. As you can see, there’s a lot of “boilerplate” code: connecting to the database; closing the connections and cleaning up afterwards; mapping the fields in the recordset to the attributes of the class, etc. However, it is standard with the JDK, which means you don’t need any third part library. You can also remove some of the boilerplate using the latest features such as multiple catches and try-with-resources:

try {
      Connection connection = null;
      ResultSet resultset = null
      Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
      try(connection = DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/A_DB",
                                                 "aaron",
                                                 "********");
        Statement statement = connection.createStatement();
        resultset = statement.executeQuery("SELECT "
                                           + "firstName, "
                                           + "lastName, "
                                           + "gender "
                                           + "FROM person")){
        Person person;
        while (resultset.next()) {
          person = new Person();
          person.setFirstName(resultset.getString("firstName"));
          person.setLastName(resultset.getString("lastName"));
          person.setGender(resultset.getString("gender"));
          System.out.println(person);
        }

      } finally {
        if (resultset != null) {
          resultset.close();
        }
        if (connection != null) {
          connection.close();
        }
      }
    } catch (InstantiationException | IllegalAccessException | SQLException | ClassNotFoundException ex) {
      Logger.getLogger(ConnectingUsingJDBC.class.getName()).log(Level.SEVERE, null, ex);
    }

Try-with-resources saves having to tidy up as it closes the resources for you. The multiple catch gain saves you some lines, but only if you do the same thing for every exception. This is now 34 lines as opposed to 53, but you still get the feeling that there’s an easier way to do this. And there is…

Hibernate

Look up the word “Object Relational Mapping” on Wikipedia and you get this:

“Object-relational mapping (ORM) is a programming technique for converting data between incompatible type systems in object-oriented programming languages. This creates, in effect, a “virtual object database” that can be used from within the programming language.”

In the list of ORM software for Java you’ll find a reference to Hibernate.

Essentially, what Hibernate does is map objects onto the result set fields, reducing the code even further, or, really, moving it somewhere else:

    Configuration config = new Configuration();
    config.configure();
    Session session = config.buildSessionFactory().openSession();

    Transaction tx = session.beginTransaction();
    try {
      List result = session.createQuery("from person").list();

      for (Person person : (List<Person>) result) {
        System.out.println(person);
      }
    } finally {
      tx.commit();
      session.close();
    }

The connection details are moved to an XML configuration file that, by default, is named hibernate.cfg.xml and contained in the root resources folder:

<?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="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:jtds:sqlserver://localhost:1433/A_DB</property>
    <property name="hibernate.connection.username">aaron</property>
    <property name="hibernate.connection.password">********</property>
    <mapping resource="jobtype.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

Notice that it refers to a “mapping resource”, in this case another XML file called “jobtype.hbm.xml”. This is where the details of the mapping are kept and it’s in the root folder again:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="org.laughing.lemon.Person" table="person">
    <id column="ID" name="ID" type="int">
      <generator class="assigned"/>
    </id>
    <property column="firstName" name="firstName" type="string"/>
    <property column="lastName" name="lastName" type="string"/>
    <property column="gender" name="gender" type="string"/>
  </class>
</hibernate-mapping>

Notice that it’s mapped the class name to the table and the column names to the attribute names of the Person class. This, in turn, has to extend the Java Serializable interface:

import java.io.Serializable;

public class Person implements Serializable {

  private int ID;
  private String firstName;
  private String lastName;
  private String gender;

You still have to do the work (you can, in theory, leave the mapping if the column names and attribute names are the same and it will work out the mappings automatically, but better safe…), but it is now done in configuration files rather the Java. You also have to introduce some transaction handling for the first time, which was done automatically for you in the JDBC.

The problem with this is that it’s not a standard. There’s still a fair bit of messing around if I wanted to switch to different ORM software. To impose some kind of standardisation, Java now has JPA, the Java Persistence API.

JPA

This is not a library or framework of any kind, but a standard or specification that ORM’s now adhere to, usually by implementing a plug-in or extension, which is what Hibernate does. Thus Hibernate JPA:

    EntityManagerFactory entityManagerFactory =
          Persistence.createEntityManagerFactory("org.laughing.lemon");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    
    List<person> result = 
         entityManager.createQuery("from org.laughing.lemon.Person", Person.class).getResultList();
    for (Person person : result) {
      System.out.println(person);
    }

    entityManager.close();

Very similar to the Hibernate implementation and, like Hibernate, it takes the connection information from an XML file, in this case “persistence.xml”:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="org.laughing.lemon" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <class>org.laughing.lemon.Person</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:jtds:sqlserver://localhost:1433/A_DB"/>
      <property name="javax.persistence.jdbc.password" value="********"/>
      <property name="javax.persistence.jdbc.driver" value="net.sourceforge.jtds.jdbc.Driver"/>
      <property name="javax.persistence.jdbc.user" value="aaron"/>
    </properties>
  </persistence-unit>
</persistence>

Notice that the persistence unit has a name that then gets used in the Java application. The mapping is done in the POJO class:

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

@Entity
@Table(name="person")
public class Person implements Serializable {

  @Id
  @Column(name="id")
  private int ID;
  @Column(name="firstname")
  private String firstName;
  @Column(name="lastname")
  private String lastName;
  @Column(name="gender")
  private String gender;

Conclusion

So far, I’ve shown three seperate ways that a Java application can connect to a database. JDBC is the most direct and basic, with Hibernate and JPA abstracting the database table to Java objects.