Skip to content

Instantly share code, notes, and snippets.

@irumiha
Last active September 17, 2023 15:23
Show Gist options
  • Save irumiha/c78b84f543e875cba0847f69e933a54d to your computer and use it in GitHub Desktop.
Save irumiha/c78b84f543e875cba0847f69e933a54d to your computer and use it in GitHub Desktop.
Single-file Spring Boot application. A silly example but it can be done. Run it as `jbang TodoApp.java`. You need the https://www.jbang.dev/ tool installed
//JAVA 17
//DEPS org.springframework.boot:spring-boot-dependencies:3.1.3@pom
//DEPS org.springframework.boot:spring-boot-starter-web
//DEPS org.springframework.boot:spring-boot-starter-data-jdbc
//DEPS com.h2database:h2
package app;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.event.EventListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.repository.query.Modifying;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class TodoApp {
public static void main(String[] args) {
SpringApplication.run(TodoApp.class, args);
}
private final Logger logger = LoggerFactory.getLogger(TodoApp.class);
private final TodoRepository todoRepository;
TodoApp(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
@GetMapping("/todos")
Iterable<Todo> todos() {
return todoRepository.findAll();
}
@PostMapping("/todos")
Todo newTodo(@RequestBody TodoCreateCommand todo) {
logger.debug("Creating new todo: {}", todo);
return todoRepository.save(new Todo(null, todo.description(), todo.done()));
}
@PostMapping("/todos/{id}/done")
Todo markTodoDone(@PathVariable("id") Integer id) {
todoRepository.markAsDone(id);
return todoRepository.findById(id).orElseThrow();
}
@PostMapping("/todos/{id}/not-done")
Todo markTodoNotDone(@PathVariable("id") Integer id) {
todoRepository.markAsNotDone(id);
return todoRepository.findById(id).orElseThrow();
}
}
@Component
record StartupAppListener(JdbcTemplate jdbc) {
@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
jdbc.execute("""
CREATE TABLE IF NOT EXISTS todos
(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
description TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT 0
);
""");
}
}
record TodoCreateCommand(String description, Boolean done) {
}
@Table("TODOS")
record Todo(@Id Integer id, String description, Boolean done) {
}
@Repository
interface TodoRepository extends CrudRepository<Todo, Integer> {
@Modifying
@Query("update todos set done = true where id=:id")
void markAsDone(@Param("id") Integer id);
@Modifying
@Query("update todos set done = false where id=:id")
void markAsNotDone(@Param("id") Integer id);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment