Hello World Scala in the Cloud With Spring
In this tutorial, we are going to look at Scala using Spring MVC and MongoDB.
The first step is a Maven project and adds the following content to your Maven POM file. The easiest way to bootstrap a Spring Boot Maven project is by using Spring Initializer.
The next step is to set the Scala dependency in the pom.xml:
<dependencies>
...
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.13.3</version>
</dependency>
</dependencies>
<build>
<finalName>spring-scala-mongodb</finalName>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>4.4.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
If you want to run MongoDB locally, a good option might be Docker, which you can run with the command below:
xxxxxxxxxx
docker run -d --name mongodb-instance -p 27017:27017 mongo
In this project, we’ll create a sample that will handle a user in its respective client. The first step is to create the entity class, in this sample, a User class.
xxxxxxxxxx
import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.mapping.Document
import scala.annotation.meta.field
import scala.beans.BeanProperty
class User
(Id ) var id: String, (
var name: String,
var country: String) {
def this() = this(null, null, null)
}
The repository interface makes the integration between the Scala application and the MongoDB instance easy:
xxxxxxxxxx
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
trait UserRepository extends CrudRepository[User, String]
The last step is to create a resource where the client can do the request and then the CRUD:
xxxxxxxxxx
import javax.validation.Valid
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.validation.BindingResult
import org.springframework.web.bind.annotation.{GetMapping, PathVariable, PostMapping}
class UserController ()(private val userRepository: UserRepository){
Array("/")) def start(model: Model): String = { (
model.addAttribute("users", userRepository.findAll)
"index"
}
Array("/signup")) def showSignUpForm(user: User) = "add-user" (
Array("/adduser")) def addUser( user: User, result: BindingResult, model: Model): String = { (
if (result.hasErrors) return "add-user"
userRepository.save(user)
model.addAttribute("users", userRepository.findAll)
"index"
}
Array("/edit/{id}")) def showUpdateForm( ("id") id: String, model: Model): String = { (
val user = userRepository.findById(id).orElseThrow(() => new IllegalArgumentException("Invalid user Id:" + id))
model.addAttribute("user", user)
"update-user"
}
Array("/update/{id}")) def updateUser( ("id") id: String, user: User, result: BindingResult, model: Model): String = { (
if (result.hasErrors) {
user.setId(id)
return "update-user"
}
userRepository.save(user)
model.addAttribute("users", userRepository.findAll)
"index"
}
Array("/delete/{id}")) def deleteUser( ("id") id: String, model: Model): String = { (
val user = userRepository.findById(id).orElseThrow(() => new IllegalArgumentException("Invalid user Id:" + id))
userRepository.delete(user)
model.addAttribute("users", userRepository.findAll)
"index"
}
}
To run the Java application left the startup class, where we define it as a boot app.
xxxxxxxxxx
import org.springframework.boot.autoconfigure.SpringBootApplication
class BootConfig
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.SpringApplication
object Application extends App {
SpringApplication.run(classOf[BootConfig]);
}
In the front-end site thymeleaf parses the HTML templates and evaluates all expressions to render the value that was set in the controller:
xxxxxxxxxx
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Users</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
<link rel="stylesheet" href="../css/shards.min.css">
</head>
<body>
<div th:switch="${users}" class="container my-5">
<div class="row">
<div class="col-md-6">
<h2 th:case="null">No users yet!</h2>
<div th:case="*">
<h2 class="my-5">Users</h2>
<table class="table table-striped table-responsive-md">
<thead>
<tr>
<th>Name</th>
<th>Country</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.name}"></td>
<td th:text="${user.country}"></td>
<td><a th:href="@{/edit/{id}(id=${user.id})}" class="btn btn-primary"><i class="fas fa-user-edit ml-2"></i></a></td>
<td><a th:href="@{/delete/{id}(id=${user.id})}" class="btn btn-primary"><i class="fas fa-user-times ml-2"></i></a></td>
</tr>
</tbody>
</table>
</div>
<p class="my-5"><a href="/signup" class="btn btn-primary"><i class="fas fa-user-plus ml-2"></i></a></p>
</div>
</div>
</div>
</body>
</html>
The Java application is ready to go! Let's move it to the cloud easily with Platform.sh from three three YAML files:
1) Route:
xxxxxxxxxx
"https://{default}/":
type upstream
upstream"app:http"
"https://www.{default}/"
type redirect
to"https://{default}/"
2) Service
xxxxxxxxxx
db
type mongodb3.6
disk1024
3) Application
x
name app
type"java:11"
disk1024
hooks
build mvn clean package
relationships
database"db:mongodb"
web
commands
start java -jar $JAVA_OPTS $CREDENTIAL -Dserver.port=$PORT target/spring-scala-mongodb.jar
The application is now ready, so it’s time to move it to the cloud with Platform.sh using the following steps:
- Create a new free trial account.
- Sign up with a new user and password, or login using a current GitHub, Bitbucket, or Google account. If you use a third-party login, you’ll be able to set a password for your Platform.sh account later.
- Select the region of the world where your site should live.
- Select the blank template.
You have the option to either integrate to GitHub, GitLab, or Platform.sh will provide to you. Finally, push to the remote repository.
Done! We have a simple and nice Spring Scala application ready to go to the cloud.