I remember these days when building something similar in Java required much more body movements, and maybe this was the reason to why some start-ups have chosen other weak typing languages with all their fancy Web frameworks for rapid bootstrapping. This isn't the case anymore, see how easy is creating a REST service that supports all CRUD operations in Java:
1. Define your task model:
/** * Task model */ @Entity public class Task { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String text; private Date created = new Date(); private Date completed; public String getText() { return text; } public void setText(String text) { this.text = text; } public Date getCreated() { return created; } public void setCreated(Date created) { this.created = created; } public Date getCompleted() { return completed; } public void setCompleted(Date completed) { this.completed = completed; } }
2. Tell what operations on tasks you're going to support:
/** * This class defines DB operations on Task entity */ public interface TaskRepository extends PagingAndSortingRepository<Task> { // Magic method name automatically generates needed query public List<Task> findByCompletedIsNull(); }
3. Configure your application:
/** * This class is responsible for: * - Setting up DB connection and ORM * - Initializing REST service for all found entities * - Starting Spring application (main entry point) */ @ComponentScan @Configuration @EnableAutoConfiguration @EnableJpaRepositories @EnableTransactionManagement public class Application extends RepositoryRestMvcConfiguration { @Bean public DataSource dataSource() throws PropertyVetoException { MySQLDataSource dataSource = new MySQLDataSource(); dataSource.setDatabaseName("taskdb"); dataSource.setUserName("user"); dataSource.setPassword("pass"); return dataSource; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); // Database tables will be created/updated automatically due to this: jpaVendorAdapter.setGenerateDdl(true); jpaVendorAdapter.setDatabase(Database.MYSQL); LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); entityManagerFactoryBean.setDataSource(dataSource); entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter); entityManagerFactoryBean.setPackagesToScan(getClass().getPackage().getName()); return entityManagerFactoryBean; } @Bean public PlatformTransactionManager transactionManager() { return new JpaTransactionManager(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
That's all! After invoking this application, you'll get a task complete REST service for free. Let's test it:
Create a new task:
~$ curl -X POST -H "Content-Type: application/json" -d '{"text":"Implement simplest REST Java application"}' http://localhost:8080/tasks
See the task contents:
~$ curl http://localhost:8080/tasks/1
{ "text" : "Implement simplest REST Java application", "created" : 1395665199000, "completed" : null, "_links" : { "self" : { "href" : "http://localhost:8080/tasks/1" } } }
Create another task:
~$ curl -X POST -H "Content-Type: application/json" -d '{"text":"Go home"}' http://localhost:8080/tasks
Find all tasks:
~$ curl http://localhost:8080/tasks
{ "_links" : { "self" : { "href" : "http://localhost:8080/tasks{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/tasks/search" } }, "_embedded" : { "tasks" : [ { "text" : "Implement simplest REST Java application", "created" : 1395665199000, "completed" : null, "_links" : { "self" : { "href" : "http://localhost:8080/tasks/1" } } }, { "text" : "Go home", "created" : 1395665359000, "completed" : null, "_links" : { "self" : { "href" : "http://localhost:8080/tasks/2" } } } ] }, "page" : { "size" : 20, "totalElements" : 2, "totalPages" : 1, "number" : 0 } }(pay an attention to how easy is it implementing pagination using this REST service!)
Mark the first task as complete:
~$ curl -X PATCH -H "Content-Type: application/json" -d "{\"completed\":$(($(date +%s)*1000))}" http://localhost:8080/tasks/1
Find incomplete tasks:
~$ curl http://localhost:8080/tasks/search/findByCompletedIsNull
{ "_embedded" : { "tasks" : [ { "text" : "Go home", "created" : 1395665359000, "completed" : null, "_links" : { "self" : { "href" : "http://localhost:8080/tasks/2" } } } ] } }Pretty easy and yet powerful, huh?
For more information and instructions for how to compile and run this application, see source code on GitHub.