From Ruby on Rails to Spring Boot
When I migrated from Rails to Spring Boot, I lacked content to guide me without having to go through all of the basics of a web framework. So, I wrote this tutorial.
Join the DZone community and get the full member experience.
Join For FreeLike Rails, Spring Boot also follows Convention over Configuration principles. The goal of this tutorial is to focus on the similarities and differences between both frameworks to provide a quick guide for developers who are migrating from one to another.
Prerequisite
Maven instalation
On Ubuntu
sudo apt update
sudo apt install maven
On Mac OS (With Homebrew)
brew update
brew install maven
Spring Boot CLI instalation
On Ubuntu (With SDKMAN)
curl "https://get.sdkman.io" | bash
source ~/.sdkman/bin/sdkman-init.sh
sdk install springboot
On Mac (With Homebrew)
brew tap pivotal/tap
brew install springboot
App Initialization
Once Spring Boot CLI is installed, we can use spring init
command to start a new Spring Boot project (just like we would do with rails new
):
# rails new <app_name>
spring init <app_name> --build=maven -d=web,data-jpa,h2,thymeleaf
--build
allows us to specify a build system:- maven: Build automation and dependency management tool. It also uses convention over configuration.
-d
allows us to specify the dependencies we want to set up. In this example, we're using the ones that are aimed at a basic web project:- web: Build web, including RESTful, applications using Spring MVC. Uses Apache Tomcat as the default embedded container.
- data-jpa: Persist data in SQL stores with Java Persistence API using Spring Data and Hibernate.
- h2: Provides a fast in-memory database that supports JDBC API, with a small (2 MB) footprint. Supports embedded and server modes as well as a browser-based console application.
- thymeleaf: Server-side Java template engine.
Note that a class was created named as DemoApplication.java
in src/main/java/com/example/<app_name>/
. By default, Spring uses Maven as the project management tool. After running the command above, dependencies can be found in pom.xml
file, at the root directory.
Navigate to your app's newly created directory and then install dependencies specified in pom.xml
by using Maven:
# bundle install
mvn clean install
If you want to add new dependencies to the project once you've already created it, you'll edit the pom.xml
file (just like you'd on the Gemfile). After adding a dependency, remember to run mvn install
again.
Start the server using spring-boot:run
, a task that's provided by the Maven plugin:
# rails s
mvn spring-boot:run
The application can now be accessed at http://localhost:8080/. At this point, an error page will be rendered, as no controllers have been defined so far.
Controllers and Views
In Spring Boot, there is no such thing as the rails generators. Also, there is no file like routes.rb
, where all routes are specified in a single place.
Write the controller inside <app_name>/src/main/java/<package_name>
:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FooController {
@GetMapping("/foo")
public String index() {
return "bar";
}
}
The @GetMapping
annotation ensures that GET requests performed to /foo
will be mapped to the method declared right after it (there is no file similar to Rails' routes.rb in Spring Boot. Routes are defined alongside its methods).
Because of Thymeleaf, by returning the String "bar", the application will look for an HTML file of the same name in src/main/resources/templates/
.
Create the following page:
bar.html
<p>FooBar</p>
Now, if we run the application with mvn spring-boot:run
command and access it at http://localhost:8080/foo, we'll see the bar.html
page being rendered.
Project Structure
At this point, we have the initial structure of a Maven project.
- Main application code is placed in
src/main/java/
. - Resources are placed in
src/main/resources
. - Test code is placed in
src/test/java
.
In the root directory, we have the pom file: pom.xml
.
This is the Maven build specification. As mentioned above, it contains the project's dependencies declarations.
RESTful Routes
Let's say we want to build a blog containing the seven RESTful actions (index, new, create, show, edit, and destroy) for posts path. In Rails, we could achieve that by defining resources: :posts
in routes.rb
file.
As mentioned at the beginning of this tutorial, Spring Boot does not have a central point where all routes are specified. They are defined in the controllers.
We've already seen an example using @GetMapping
annotation to demonstrate the definition of a route that uses GET
method. Similarly, Spring supports four other inbuilt annotations for handling different types of HTTP request methods:
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
From Rails Models to Spring Entities
To represent a Post at the application level, we'll need to define it as a Spring JPA entity (very similar to how a model in Rails would be done).
@Entity // Designate it as a JPA Entity
public class Post {
@Id // Mark id field as the entity's identity
@GeneratedValue(strategy = GenerationType.AUTO) // Value will be automatically provided
private Long id;
private String title;
private String content;
public Long getId() { ... }
public void setId(Long id) { ... }
public String getTitle() { ... }
public void setTitle(String title) { ... }
public String getContent() { ... }
public void setContent(String content) { ... }
}
Spring Data JPA provides some built-in methods to manipulate common data persistence operations through the usage of repositories in a way that's very similar to Rails' ActiveRecord. So, to work with Post data, a PostRepository
must be implemented as well:
public interface PostRepository extends JpaRepository<Post, Long> {
}
JpaRepository
interface takes to params, in this scenario: Post
and Long
.
Post
because it is the entity that will be used and Long
because that's the type of Post
's identity (ID).
This interface will be automatically implemented at runtime.
Performing a Creation Through a Web Interface
The next step is adding a form to submit posts to the blog.
At this point, we already have the templates/blog/new.html
file containing a single line. You can access this page at http://localhost:8080/posts/new.
Using Thymeleaf, we can do that with the following approach: