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:

XML
 




x
33


 
1
 <dependencies>
2
   
3
        ...
4
        <dependency>
5
            <groupId>org.scala-lang</groupId>
6
            <artifactId>scala-library</artifactId>
7
            <version>2.13.3</version>
8
        </dependency>
9
    </dependencies>
10
 
          
11
     <build>
12
        <finalName>spring-scala-mongodb</finalName>
13
        <plugins>
14
            <plugin>
15
                <groupId>net.alchim31.maven</groupId>
16
                <artifactId>scala-maven-plugin</artifactId>
17
                <version>4.4.0</version>
18
                <executions>
19
                    <execution>
20
                        <goals>
21
                            <goal>compile</goal>
22
                            <goal>testCompile</goal>
23
                        </goals>
24
                    </execution>
25
                </executions>
26
            </plugin>
27
            <plugin>
28
                <groupId>org.springframework.boot</groupId>
29
                <artifactId>spring-boot-maven-plugin</artifactId>
30
            </plugin>
31
        </plugins>
32
    </build>
33
 
          



If you want to run MongoDB locally, a good option might be Docker, which you can run with the command below:

Shell
 




xxxxxxxxxx
1


1
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.

Scala
 




xxxxxxxxxx
1
14


 
1
import org.springframework.data.annotation.Id
2
import org.springframework.data.mongodb.core.mapping.Document
3
 
          
4
import scala.annotation.meta.field
5
import scala.beans.BeanProperty
6
 
          
7
 
          
8
@Document class User
9
(@(Id@field) @BeanProperty var id: String,
10
 @BeanProperty var name: String,
11
 @BeanProperty var country: String) {
12
 
          
13
  def this() = this(null, null, null)
14
}



The repository interface makes the integration between the Scala application and the MongoDB instance easy:

Scala
 




xxxxxxxxxx
1


 
1
import org.springframework.data.repository.CrudRepository
2
import org.springframework.stereotype.Repository
3
 
          
4
@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:

Scala
 




xxxxxxxxxx
1
47


1
 
          
2
import javax.validation.Valid
3
import org.springframework.beans.factory.annotation.Autowired
4
import org.springframework.stereotype.Controller
5
import org.springframework.ui.Model
6
import org.springframework.validation.BindingResult
7
import org.springframework.web.bind.annotation.{GetMapping, PathVariable, PostMapping}
8
 
          
9
@Controller class UserController @Autowired()(private val userRepository: UserRepository){
10
 
          
11
  @GetMapping(Array("/")) def start(model: Model): String = {
12
    model.addAttribute("users", userRepository.findAll)
13
    "index"
14
  }
15
 
          
16
  @GetMapping(Array("/signup")) def showSignUpForm(user: User) = "add-user"
17
 
          
18
  @PostMapping(Array("/adduser")) def addUser(@Valid user: User, result: BindingResult, model: Model): String = {
19
    if (result.hasErrors) return "add-user"
20
    userRepository.save(user)
21
    model.addAttribute("users", userRepository.findAll)
22
    "index"
23
  }
24
 
          
25
  @GetMapping(Array("/edit/{id}")) def showUpdateForm(@PathVariable("id") id: String, model: Model): String = {
26
    val user = userRepository.findById(id).orElseThrow(() => new IllegalArgumentException("Invalid user Id:" + id))
27
    model.addAttribute("user", user)
28
    "update-user"
29
  }
30
 
          
31
  @PostMapping(Array("/update/{id}")) def updateUser(@PathVariable("id") id: String, @Valid user: User, result: BindingResult, model: Model): String = {
32
    if (result.hasErrors) {
33
      user.setId(id)
34
      return "update-user"
35
    }
36
    userRepository.save(user)
37
    model.addAttribute("users", userRepository.findAll)
38
    "index"
39
  }
40
 
          
41
  @GetMapping(Array("/delete/{id}")) def deleteUser(@PathVariable("id") id: String, model: Model): String = {
42
    val user = userRepository.findById(id).orElseThrow(() => new IllegalArgumentException("Invalid user Id:" + id))
43
    userRepository.delete(user)
44
    model.addAttribute("users", userRepository.findAll)
45
    "index"
46
  }
47
}



To run the Java application left the startup class, where we define it as a boot app.

Scala
 




xxxxxxxxxx
1
15


1
import org.springframework.boot.autoconfigure.SpringBootApplication
2
 
          
3
@SpringBootApplication
4
class BootConfig
5
 
          
6
 
          
7
import org.springframework.boot.SpringApplication
8
import org.springframework.boot.autoconfigure.SpringBootApplication
9
 
          
10
 
          
11
import org.springframework.boot.SpringApplication
12
 
          
13
object Application extends App {
14
  SpringApplication.run(classOf[BootConfig]);
15
}



In the front-end site thymeleaf parses the HTML templates and evaluates all expressions to render the value that was set in the controller:

HTML
 




xxxxxxxxxx
1
44


 
1
<!DOCTYPE html>
2
<html xmlns:th="http://www.thymeleaf.org">
3
<head>
4
    <meta charset="utf-8">
5
    <meta http-equiv="x-ua-compatible" content="ie=edge">
6
    <title>Users</title>
7
    <meta name="viewport" content="width=device-width, initial-scale=1">
8
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
9
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
10
    <link rel="stylesheet" href="../css/shards.min.css">
11
</head>
12
<body>
13
<div th:switch="${users}" class="container my-5">
14
    <div class="row">
15
        <div class="col-md-6">
16
            <h2 th:case="null">No users yet!</h2>
17
            <div th:case="*">
18
                <h2 class="my-5">Users</h2>
19
                <table class="table table-striped table-responsive-md">
20
                    <thead>
21
                    <tr>
22
                        <th>Name</th>
23
                        <th>Country</th>
24
                        <th>Edit</th>
25
                        <th>Delete</th>
26
                    </tr>
27
                    </thead>
28
                    <tbody>
29
                    <tr th:each="user : ${users}">
30
                        <td th:text="${user.name}"></td>
31
                        <td th:text="${user.country}"></td>
32
                        <td><a th:href="@{/edit/{id}(id=${user.id})}" class="btn btn-primary"><i class="fas fa-user-edit ml-2"></i></a></td>
33
                        <td><a th:href="@{/delete/{id}(id=${user.id})}" class="btn btn-primary"><i class="fas fa-user-times ml-2"></i></a></td>
34
                    </tr>
35
                    </tbody>
36
                </table>
37
            </div>
38
            <p class="my-5"><a href="/signup" class="btn btn-primary"><i class="fas fa-user-plus ml-2"></i></a></p>
39
        </div>
40
    </div>
41
</div>
42
</body>
43
</html>
44
 
          



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:

YAML
 




xxxxxxxxxx
1


 
1
"https://{default}/":
2
 type: upstream
3
 upstream: "app:http"
4
 
          
5
"https://www.{default}/":
6
 type: redirect
7
 to: "https://{default}/"



2) Service

YAML
 




xxxxxxxxxx
1


 
1
db:
2
   type: mongodb:3.6
3
   disk: 1024
4
 
          



3) Application

YAML
 




x


1
name: app
2
type: "java:11"
3
disk: 1024
4
hooks:
5
   build: mvn clean package
6
relationships:
7
   database: "db:mongodb"
8
web:
9
   commands:
10
       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:

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.

 

 

 

 

Top