Tuesday, November 24, 2015

Get rid of null checks

As a developer we do our best to catch the null values and fail fast. I was writing too much code lines like below.

if (user == null) {
    throw new IllegalArgumentException("user most not be null.");
} 


After a while codebase can become dirty with this lines copy/pasted everywhere. While I was reading some Spring source code I found that Spring uses `Assert` Util class for that purpose. And we started to use this class as a replacement. Now code become better with this one line.
Assert.notNull(user, "user must not be empty");

Assert class has many useful methods like
Assert.isTrue
Assert.isNull
Assert.notNull
Assert.hasLength
Assert.hasText
Assert.doesNotContain
Assert.notEmpty
...

If throwing IllegalArgumentException is not good for you then you can create your own Util class for that purpose.

Exposing Spring Data Repositories over REST with Spring Boot and Spring Data REST

Spring Boot let us quickly create projects. Spring Boot favors convention over configuration. Most of the time we start with writing domain Entities. To quickly look around Entities or to populate some data we can use Spring Data REST. With Spring Data REST we can easily expose JPA based repositories as RESTful endpoints.

Most of the time you'll need to write your own endpoints for adding validations etc. But for testing the entities or when we need to try something it is good tool.

First we need to create Spring Boot project and add spring-data-rest as maven dependency to pom.xml file

  org.springframework.boot
  spring-boot-starter-parent
  1.3.0.RELEASE
 
 
  
   org.springframework.boot
   spring-boot-starter-data-rest
  
  
   mysql
   mysql-connector-java
   runtime
  
 

Let's create basic Entity
import javax.persistence.*;

@Entity
public class Customer {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

}

Spring Data's JpaRepository interface adds CRUD operations without adding any code. Spring Data REST will use this repository to generate REST endpoints.

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
}

Then all we need to do is add @EnableJpaRepositories annotation
@EnableJpaRepositories
@SpringBootApplication
public class SpringDataRestDemo {

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

}

When you start the application at the root of your url you'll see HATEOS supported endpoints response like below. You can make GET/POST/DELETE/PATCH/PUT requests to this endpoints.
{
  "_links": {
    "customers": {
      "href": "http://localhost:8080/customers{?page,size,sort}",
      "templated": true
    },
    "profile": {
      "href": "http://localhost:8080/profile"
    }
  }
}

Let's check the customers
{
  "_embedded": {
    "customers": [
      {
        "name": "ugur",
        "_links": {
          "self": {
            "href": "http://localhost:8080/customers/1"
          },
          "customer": {
            "href": "http://localhost:8080/customers/1"
          }
        }
      },
      {
        "name": "Luke",
        "_links": {
          "self": {
            "href": "http://localhost:8080/customers/2"
          },
          "customer": {
            "href": "http://localhost:8080/customers/2"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/customers"
    },
    "profile": {
      "href": "http://localhost:8080/profile/customers"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 2,
    "totalPages": 1,
    "number": 0
  }
}

{
  "name": "Luke",
  "_links": {
    "self": {
      "href": "http://localhost:8080/customers/2"
    },
    "customer": {
      "href": "http://localhost:8080/customers/2"
    }
  }
}

Sunday, November 22, 2015

Using Java 8 Time API with JPA

We were using the Joda-Time API for replacement of Java Date API. After improvements on the Java 8 Time API we decided to move on to the Java 8 Time API. But JPA 2.1 does not have built in support for Java 8 time API because Java 8 released after. But we can still use Java 8 API using the attribute converters.

Here the example code for converting LocalDate to java.sql.Date for persisting to db.



With autoApply = true property this converter will be apply to all LocalDates so entities can be clean. If you don't want this feature then you can add @Convert(converter = LocalDateConverter.class) annotation to the fields.