-
Notifications
You must be signed in to change notification settings - Fork 142
Description
There are many frameworks that depend on annotations. I will be using Spring Boot as an example.
Spring Boot is a widespread Java framework that does not enforce any kind of structure, while being able to use all the Spring Boot modules to make application development easier.
These modules include interoperability with:
- CassandraDB
- CouchDB
- Kafka
- Many caching systems
- Queueing systems
- And many more
The problem here is, Spring Boot is mainly annotation driven. And while we are able to do dependency injection using a custom environment (like a ReaderT), other features of the framework are not accessible because of its hard dependency on annotations.
Of course, one can use the Java Persistence API (JPA) to handle the creation and modification of database entries.
Example application
This is an example of a very simple Spring Boot application that handles persistence and routing:
I'll be using Scala as the example language just for the sake of brevity, as it is less verbose and it is directly translatable to Java.
Application.scala
@SpringBootApplication
class Application { }
def main(args: Array[String]) = {
SpringApplication.run(classOf[Application], args)
}This is the entry point of our application. We are passing Application.class to the run method so Spring can operate on it using reflection.
I can imagine doing this easily in Eta:
@SpringBootApplication
data Application = Application @eta.myexample.Application
main :: IO ()
main = do
args <- getArgs
runSpringApplication (getClass (Proxy :: Proxy Application)) argsPost.scala
@Entity
class Post {
@Id
@GeneratedValue
var id: Long = null
var title: String = null
var content: String = null
}This class defines an entity that will be stored in the Post table.
I think it would be quite tricky to do so, unless we force the exported ADTs to be records:
@Entity
data Post = Post
{ id :: @Id @GeneratedValue (Mutable Long)
, title :: Mutable String
, content :: Mutable String
}(Idea: non-records fields could be exported as _1, _2, _n)
PostRepository.scala
trait PostRepository extends JpaRepository[Post, Long] { }This is just an interface that allows us to use some methods to access our database:
data PostRepository = PostRepository @foo.PostRepository
type instance Inherits PostRepository = '[JpaRepository Post Long](Note: I'm not sure if this is the correct way to do so)
PostController.scala
@Controller
@RequestMapping("/")
class PostController {
@Autowired
var postRepository: PostRepository = null
@GetMapping("/")
def posts(model: Model): String = {
val posts = postRepository.findAll()
model.addAttribute("posts", posts)
"postList"
}
@PostMapping("/")
def addToPostsList(post: Post): String = {
postRepository.save(post)
"redirect:/"
}
}This is the biggest part, the controller that handles all the requests and uses the other classes
@Controller
@RequestMapping "/"
data PostController = PostController
{ postRepository :: @Autowired (Mutable PostRepository)
}
@GetMapping "/"
posts :: Model -> Java PostController String
posts model = do
posts <- postRepository <.> findAll
model <.> addAttribute "posts" posts
return "postList"
@PostMapping "/"
addToPostsList :: Post -> Java PostController String
addToPostsList post = do
postRepository <.> save post
return "redirect:/"It looks quite feasible to me.
Note: I'm not an expert in the Eta export features. Although I'm a Haskeller, I haven't used Eta too much :)
**Note 2: This are just snippets of code, if the whole project is needed, you can find it in this repository, this commit **