Structure of a Scala Project
Let's look at our
chatbot program in a complete runnable project. Let's navigate to the
/day1-lesson1/1-project directory in our code supplement.
Note
The code is available on Github at the following link: https://github.com/TrainingByPackt/Professional-Scala

The preceding diagram is the typical directory structure of a Scala project. If you are familiar with the Java tools ecosystem, then you will notice the similarities between the
maven project layout.
In
src, we can
see project sources (
main and
test).
target is a place where output artifacts are created, whereas
project is used as a place to
internally build the project. We will cover all of these concepts later on.
organization := "com.packt.courseware"name := "chatbot1"version := "0.1-SNAPSHOT" scalaVersion := "2.12.4"
The head of any project is its
build.sbt file. It consists of the following code:
The text inside it is a plain Scala snippet.
organization,
name, and
version are instances of
sbt.key. For this point of view,
:= is a binary operator defined on
keys. In Scala, any method with two arguments can be used with the syntax of a binary operator.
:= is a valid method name.
build.sbt is interpreted by the
sbt tool.
Note
sbt – The original intention for the name, when
sbt was created by Mark Harrah, was '
Simple Build Tool'. Later on, the author decided to avoid such a decipherment, and kept it as it was. You can read about the details of
sbt here:
https://www.scala-sbt.org/1.x/docs/index.html.
Basic sbt Commands
We will now
talk about the basic
sbt commands.
sbt compile should compile
the project and live somewhere in its target compiled Java classes.
sbt run executes
the
main function of the project. Therefore, we can try to interact with our
chatbot:
rssh3:1-project rssh$ sbt run [info] Loading global plugins from /Users/rssh/.sbt/0.13/plugins [info] Set current project to chatbot1 (in build file:/Users/rssh/work/packt/professional-scala/Lesson 1/1-project/) [info] Running com.packt.courseware.Chatbot1 Hi! What is your name? Jon Jon, tell me something interesting, say 'bye' to end the talk
>qqq interesting.. >ddd interesting... >bye ok, bye [success] Total time: 19 s, completed Dec 1, 2017 7:18:42 AM
The output of the code is as follows:
sbt package prepares
an output artifact. After running it, it will create file called
target/chatbot1_2.12-0.1-SNAPSHOT.jar.
chatbot1 is the name of our project;
0.1-SNAPSHOT – version. 2.12 is the version of the Scala compiler.
Scala
guarantees binary compatibility only within the scope of a minor version. If, for some reason, the project still uses
scala-2.11, then it must use the library, which was created for
scala-2.11. On the other hand, updating to the next compiler version can be a long process for projects with many dependencies. To allow the same library to exist in the repository with different
scalaVersions, we need to have an appropriate
suffix in the jar file.
sbt publish-local – publishes the artifact on to your local repository.
Now let's see
our sample project and
sbt tool.
Activity: Performing Basic Operations with sbt: Build, Run, Package
- Install sbt on your computer, if not installed beforehand.
- Start the
sbtconsole by typingsbt consolein the root directory of the1-project(wherebuild.sbtis situated). - Compile the code by typing the
compilecommand into thesbtconsole. - Run the program by typing the
sbt runcommand into thesbtconsole. - When running this, say
byeto the bot and return to the console. - Package the program by typing
packageinto thesbtconsole.
IDE
Another part of the developer toolbox is an IDE tool (Integrated Development Environment). For our book, we will use Intellij IDEA community edition with the Scala plugin. This is not the only option: other alternatives are scala-ide, based on IBM Eclipse and Ensime (http://ensime.github.io/), which brings IDE features to any programmable text editors, from vi to emacs.
All tools support importing the project layout from
build.sbt.
Activity: Loading and Running a Sample Project in the IDE
- Import our project:
- Go to
File->Import-> navigate tobuild.sbt
- Go to
- Open the program in IDE:
- Start IDEA
- Press
Open - Select
day1-lesson1/1-project/build.sbt
- In the dialog window, which asks whether to open it as a file or as a project, select
project. - On the left part of the project's structure, unfold
srcentry. - Click on
main. - Ensure that you can see
main, as specified in the code. - Ensure that project can be compiled and run via the
sbtconsole.
For running our project from the IDE, we should edit the project's configuration (Menu:
Build/
Edit configuration or
Run/
Edit configuration, depending on which version of IDEA you are using).
Running the Project from IDE:
- Select
Run/Edit Configuration. - Select
Application. - Set the application's name. In our case, use
Chatbot1. - Set the name of the
Mainclass. In our case, it must becom.packt.courseware.Chatbot1. - Actually run the application: select Run, then Chatbot1 from the dropdown menu.
REPL
Another tool that we will frequently use is REPL (Read Eval Print Loop). It is often used for quickly evaluating Scala expressions.
From
sbt, we can enter REPL mode with the help of the
sbt console command. Let's try some
simple expressions.
Now, we'll look at how to evaluate expressions. Follow these steps to do so:
- Open the
sbttool. - Open
REPLby typing the following command:sbt console
- Type the following expressions and press Enter:
2 + 2"2" + 22 + "2"(1 to 8).sumjava.time.LocalTime.now()
Please note that we can have an interactive Scala
playboard inside IDE by creating a special file type: a Scala Worksheet. It's useful, but is mainly for demonstration purposes.
Obtaining the Time Request from Our Chatbot Program
For now, let's return to our task: modifying the
chatbot program so that it replies with
the current time, as requested by the use of
time. Let's learn how to do this:
Steps for C ompletion
- Check for
timeto match the statement:case "time" =>
- Retrieve the current time using the Java API. Use the
nowmethod ofjava.time.LocalTime:java.time.LocalTime.now()
- Display the output of the time using string interpolators, as follows:
println("time is ${java.time.LocalTime.now()}")
The
main method will look like this:
def main(args: Array[String]): Unit = {
val name = StdIn.readLine("Hi! What is your name?")
println(s" $name, tell me something interesting, say 'bay' to end the talk")
var timeToBye = false
while (!timeToBye)timeToBye = StdIn.readLine(">")
match {case "bye" => println("ok, bye")truecase "time" =>
println(s"time is ${java.time.LocalTime.now()}")truecase _ =>
println("interesting...")false}
}After we prepare and package our artifacts, we need to run them as well.
In this book, we will
use the running system from unpackaged sources via
sbt (as in the early days of Ruby applications), assuming that sources and
sbt tools are accessible from the production environment. Using this, we can use build tool commands for sources such as
sbt run. In real life, packaging for production is a bit more complex.
Popular methods for doing this are as follows:
- Preparing a fat jar (which includes all dependencies). An
sbtplugin for this exists, which can be found at the following link: https://github.com/sbt/sbt-assembly. - Preparing a native system package (which includes jars, dependencies, custom layouts, and so on). There is also an
sbtplugin to create native system packages, which can be found at the following link: https://github.com/sbt/sbt-native-packager.