Unit Testing of Spatial Queries

One reason why native SQL should be avoided is that it is not unit testable, so you never will get fast feedback if you break some query or the application model does no longer match the DB model. Another reason is, that your customers might already have a database vendor of their choice and you don’t want to force them to buy expensive licences from another one.

Even for spatial queries it is possible to use an abstraction layer and support multiple database vendors. Thanks to Hiberante Spatial or Eclipse Link extensions.

And if you use Hibernate Spatial in conjunction with GeoDB, a spatial extension of H2, which can run In-Memory, it is possible to execute spatial queries within unit tests. Which is a beautiful thing.

Here as an example an Entity with some spatial information (a location point) and a Repository based on JPA:

package at.nonblocking.geodb;

import com.vividsolutions.jts.geom.Point;

@Entity
public class Airport {

  @Id
  @GeneratedValue
  private long id;

  private String icaoCode;
  private String iataCode;
  private String name;

  @Type(type = "org.hibernate.spatial.GeometryType")
  private Point location;

  public Airport() {}

  public Airport(String icaoCode, String iataCode, String name, Point location) {
      this.icaoCode = icaoCode;
      this.iataCode = iataCode;
      this.name = name;
      this.location = location;
  }

  //Getter and setters omitted
}
package at.nonblocking.geodb;

import com.vividsolutions.jts.geom.Geometry;

@Repository
public class AirportRepositoryJPAImpl implements AirportRepository {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Airport getById(long id) {
        return this.entityManager.find(Airport.class, id);
    }

    @Override
    public List<Airport> findWithin(Geometry shape) {
        return this.entityManager.createQuery(
            "from Airport where within(location, :shape) = true", 
               Airport.class)
            .setParameter("shape", shape)
            .getResultList();
    }
}

Hibernate Spatial comes with several geometry types you have to annotate it with @Type(type = “org.hibernate.spatial.GeometryType”). Furthermore it adds some spatial functions to JPQL, such as within(), intersect() and so on.

To be able to write a unit tests against the Repository above, first add the following dependencies to your POM file:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.1.4.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-spatial</artifactId>
    <version>4.0</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>4.0.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.0.2.RELEASE</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.opengeo</groupId>
    <artifactId>geodb</artifactId>
    <version>0.8</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
</dependency>

You might have to add the following repository for GeoDB:

  <repository>
    <id>opengeo.org</id>
     <url>http://repo.opengeo.org/</url>
  </repository>

Next create the following Spring context to bootstrap GeoDB and Hibernate:

<bean id="airportRepository" class="at.nonblocking.geodb.AirportRepositoryJPAImpl"/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" 
              value="org.hibernate.spatial.dialect.h2geodb.GeoDBDialect" />
            <entry key="hibernate.hbm2ddl.auto" value="update" />
            <entry key="hibernate.show_sql" value="true" />
            <entry key="hibernate.format_sql" value="true" />
        </map>
    </property>
    <property name="packagesToScan">
        <list>
            <value>at.nonblocking.geodb</value>
        </list>
    </property>
</bean>

<bean id="dataSource" class="at.nonblocking.geodb.GeoDBInMemoryDataSource" />

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

The only difference to a normal Hibernate 4 setup is the dialect org.hibernate.spatial.dialect.h2geodb.GeoDBDialect.

For GeoDB it was necessary to create a custom data source, because all connections need to be initialized through GeoDB.init(). GeoDBInMemoryDataSource looks like this:

import geodb.GeoDB;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;

public class GeoDBInMemoryDataSource extends SingleConnectionDataSource {

    public GeoDBInMemoryDataSource() {
        setDriverClassName("org.h2.Driver");
        setUrl("jdbc:h2:mem:test");
        setSuppressClose(true);
    }

    @Override
    public Connection getConnection() throws SQLException {
        Connection conn = super.getConnection();
        GeoDB.InitGeoDB(conn);
        return conn;
    }
}

And now you can use Spring Test to write a JUnit test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-context-geodb2.xml")
@TransactionConfiguration(defaultRollback = true)
public class InMemoryGeoDbSpatial2Test {

    @Resource
    private AirportRepository airportRepository;

    @PersistenceContext
    private EntityManager entityManager;

    @Before
    public void insertTestData() {
        GeometryFactory geometryFactory = new GeometryFactory();

        Airport airportVienna = new Airport("VIE", "LOWW", "Wien Schwechat",
          geometryFactory.createPoint(new Coordinate(16.569613472222223, 48.11034788888889)));
        Airport airportPrague = new Airport("PRG", "LKPR", "Prague Ruzyne", 
          geometryFactory.createPoint(new Coordinate(14.26, 50.100833333333334)));

        this.entityManager.persist(airportVienna);
        this.entityManager.persist(airportPrague);
    }

    @Test
    @Transactional
    public void testFindAirportsAroundVienna() {
        GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
        shapeFactory.setNumPoints(32);
        shapeFactory.setCentre(new Coordinate(16.366667, 48.2));
        shapeFactory.setSize(0.5);

        Geometry aroundViennaShape = shapeFactory.createCircle();

        List<Airport> airports = this.airportRepository.findWithin(aroundViennaShape);

        assertNotNull(airports);
        assertTrue(airports.size() == 1);
        assertEquals("Wien Schwechat", airports.get(0).getName());
    }
}

And here the Hibernate SQL output:

    select
        airport0_.id as id0_,
        airport0_.iataCode as iataCode0_,
        airport0_.icaoCode as icaoCode0_,
        airport0_.location as location0_,
        airport0_.name as name0_ 
    from
        Airport airport0_ 
    where
        ST_Within(airport0_.location, ?)=1

You can see, Hibernate Spatial translates the JPQL within() function to ST_Within. On Oracle it would be translated to MDSYS.OGC_WITHIN.

Have fun with unit testing spatial queries.

Exception Translation in Java vs. Scala

Exception Translation is a very important pattern to prevent your code from being cluttered by framework specific exception types. For example, you don’t want to deal with JDBC exceptions in your business code, especially because you might want to switch to JPA or a NoSQL database some day.
The idea is to translate all vendor specific exceptions to an internal exception hierarchy before they cross layer or module boundaries. So, a developer of an higher level module has only to deal with a known set of possible exceptions and will not get headaches because of cryptic database exceptions.
Since Exception Translation is a cross cutting concern it should not be done in the production code. Lower level modules should not even know about the exception hierarchy used up the call stack by higher level modules.

Let’s say we have an persistence layer with repositories that throw all kinds of javax.persistence Exceptions and a service layer that only want to deal with internal exceptions:

@Repository
public class CustomerRepositoryImpl implements CustomerRepository {
  @PersistenceContext
  private EntityManager entityManager;

  public Customer persist(Customer customer) {
     //Could throw an javax.persistence.OptimisticLockException
     return this.entityManager.merge(partner);
  }  
}
   //In the service code
   try {
      this.customerRepository.persist(customer);
   } catch (my.ConcurrentUpdateException e) {
     //Deal with it
   }

In Java the only way to do such a translation is AOP. In Spring you could do something like this:

public class ExceptionTranslator {

  public void handleException(Throwable ex) {
    if (ex instanceof javax.persistence.OptimisticLockException) {
      return new my.ConcurrentUpdateException(
        "Concurrent update", ex);
    }
    //more
  }
}
<bean id="exceptionTranslator" class="my.ExceptionTranslator"/>

<aop:config>
  <aop:aspect ref="exceptionTranslator">
    <aop:pointcut id="repositoryMethod" 
       expression="within( @org.springframework.stereotype.Repository *)" />
    <aop:after-throwing pointcut-ref="repositoryMethod" 
       method="handleException" throwing="ex"/>
  </aop:aspect>
</aop:config>

This approach is of course quite magic (as AOP always is) and might be confusing to developers. Because they throw an exception on one end and have to catch another one at the other.

In Scala is is possible to integrate the exception translation directly in the code, but do the actual translation at one place at the same time. Due to the magic of closures and lazy evaluation. Remember, in Scala you can defer the evaluation of an method argument with the “=>” operator.

So, we could do this:

def persist(customer: Customer): Customer = {
  translateExceptions {
    this.customerRepository.persist(customer)
  }
}

If the translateExceptions Method looks like this:

def translateExceptions[T <: Any](body: => T): T = {
  try {
    body //Evaluate the given method body
  } catch {
    case e: javax.persistence.OptimisticLockException 
      => throw new my.ConcurrentUpdateException("Concurrent udpate", e)
  }
}

You could put the translation method into a Scala object and use it from everywhere:


object ExceptionTranslator {
  def apply[T <: Any](body: => T): T = {
  try {
    body
  } catch {
    case e: javax.persistence.OptimisticLockException 
      => throw new my.ConcurrentUpdateException("Concurrent udpate", e)
  }
}

//And use it like this:
def persist(customer: Customer): Customer = {
  ExceptionTranslator {
    this.customerRepository.persist(customer)
  }
}

Much smarter, much more understandable as in Java.

jQuery Europe 2014

I’ve been on the jQuery Europe conference in Vienna and learned a lot of interesting stuff.

The location, a baroque palace, was also quite awesome. Below Peter-Paul Koch (PPK), famous for QuirksMode, talking about Viewports on Mobile Devices in a 300 year old hall:

photo

His talk was one of the most interesting ones and a must for everyone who is every going to build serious mobile applications or want to understand the foundations of responsive design. Here his talk recorded on another conferences: PPK on Viewports.

Also very interesting: The talk of Patrick Lauke, who did a lot of research on touch events. Here his slide deck.

And thanks to the guys from Gentics who made this event possbile!