Fullstack Scala Project
In this lesson, you will build a fullstack Scala application that combines backend APIs, data handling, and a simple frontend interaction. This project brings together many concepts you have learned so far and shows how Scala is used in real production systems.
By the end of this lesson, you will understand how to structure a Scala project, expose REST APIs, handle data, and think like a fullstack Scala developer.
What Is a Fullstack Scala Application?
A fullstack Scala application typically includes:
- A backend written in Scala (APIs, business logic)
- Data access (database or in-memory storage)
- JSON serialization and deserialization
- A frontend or client that consumes the API
Scala is commonly used on the backend, while the frontend may be web-based or another service.
Project Overview
We will build a simple User Management System with the following features:
- Create a user
- Fetch all users
- Fetch a user by ID
This project focuses on clarity, structure, and performance rather than UI design.
Project Structure
A clean project structure is essential for maintainability.
fullstack-scala/
├── build.sbt
└── src/
└── main/
└── scala/
├── model/
├── service/
├── routes/
└── Main.scala
Each folder has a clear responsibility.
Defining the Data Model
Start by defining a user model using a case class.
case class User(id: Int, name: String, email: String)
Case classes are immutable and ideal for representing application data.
Service Layer (Business Logic)
The service layer manages data and business rules.
class UserService {
private var users = List(
User(1, "Alice", "alice@example.com"),
User(2, "Bob", "bob@example.com")
)
def getAllUsers: List[User] = users
def getUserById(id: Int): Option[User] =
users.find(_.id == id)
def addUser(user: User): Unit =
users = users :+ user
}
This simple service simulates a database using in-memory storage.
Creating REST Routes
Routes expose the service functionality to the outside world.
import akka.http.scaladsl.server.Directives._
class UserRoutes(service: UserService) {
val routes =
pathPrefix("users") {
get {
pathEndOrSingleSlash {
complete(service.getAllUsers.toString)
} ~
path(IntNumber) { id =>
complete(service.getUserById(id).toString)
}
}
}
}
This example uses HTTP routing to expose user endpoints.
Application Entry Point
The main application wires everything together.
object Main extends App {
val service = new UserService
val routes = new UserRoutes(service)
println("Server running on http://localhost:8080")
}
In real projects, this is where the HTTP server would be started.
JSON Handling
Fullstack applications often communicate using JSON. Scala libraries can convert case classes to JSON easily.
// Example JSON representation
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
This allows frontend clients to interact with the backend seamlessly.
Connecting a Frontend
The frontend can be:
- A web application
- A mobile app
- Another backend service
It simply sends HTTP requests to the Scala backend and processes the responses.
Error Handling
Robust applications handle errors gracefully.
service.getUserById(10) match {
case Some(user) => user
case None => "User not found"
}
Using Option prevents null-related errors.
Performance Considerations
For production systems:
- Use asynchronous APIs
- Prefer immutable data structures
- Use efficient collections
- Add caching where necessary
📝 Practice Exercises
Exercise 1
Add a method to delete a user by ID.
Exercise 2
Extend the service to update an existing user.
Exercise 3
Design a simple frontend request that fetches all users.
✅ Practice Answers
Answer 1
def deleteUser(id: Int): Unit =
users = users.filterNot(_.id == id)
Answer 2
def updateUser(updated: User): Unit =
users = users.map(u => if (u.id == updated.id) updated else u)
Answer 3
GET http://localhost:8080/users
What’s Next?
In the next lesson, you will complete the Scala Capstone Project, where you combine everything learned in this course into a real-world application.