The sections below include information about packages and how you can manage the growth of your source code.
Writing code in an organized manner from the beginning of the project is important for the lifecycle of the project and its maintainability in the long run. Organized code will make it easy to extend and improve your project over time. Ballerina project structure makes it easy to write clean code by eliminating repetitions, writing reusable code, adding new features without changing the existing code, etc. To achieve this, Ballerina has the concept of packages and modules.
Ballerina code is organized in a single shareable unit called a
package is a collection of
modules, and a
module is a collection of Ballerina source files, test files, and resources. A package should contain at least one module called the default module. Each module has its own directory, which organizes source files, test files, and resources.
It is common in small projects to have only one (default) module in a package. As a result, the default module’s content is placed directly in the root of the package directory.
Create your first Ballerina package
bal new command below creates a package with the default module.
$ bal new hello_world
This creates a new Ballerina package in the default module with the
Ballerina.toml file, which identifies a directory as a package and a sample source file (i.e.,
main.bal) with a main function.
bal new command generates the following file structure.
cd hello_world tree . . ├── Ballerina.toml └── main.bal 0 directories, 2 files
Info: You may also create a service or a library package instead of the main function as explained in the sections below.
Create a Ballerina service package
$ bal new -t service hello_service
This creates a Ballerina source containing a service declaration with Ballerina tests to test the service. It creates the following file structure with the service template.
cd hello_service . ├── Ballerina.toml ├── service.bal └── tests └── service_test.bal 1 directory, 3 files
Create a library package
$ bal new -t lib hello_lib
This creates a Ballerina source file containing a function that prints
Hello, world! along with a test file to test the function. Additionally, it creates the
Package.md file, which is required to publish a package to Ballerina Central.
├── Ballerina.toml ├── hello_lib.bal ├── Module.md ├── Package.md ├── resources └── tests └── lib_test.bal
The default module
When a package is created with the
bal new command, the
Ballerina.toml and the
main.bal files are created.
main.bal file is a Ballerina source file, which belongs to the default module.
The root directory of the default module is the root directory of the package as well.
Therefore, the package root directory contains files that belong to the package as well as the default module.
You can add more source files at the package root, and all the top-level symbols (i.e., functions, variables, etc.) defined in one file will also be visible to other files as they share the same namespace.
This namespace is called the default module of the package. The package name, which is specified in the
Ballerina.toml file is also used to refer to the default module.
As projects grow in complexity, the need arises to organize code better. This could be because you want to separate the functionalities of the package and/or to add boundaries to the visibility of certain functionalities. Therefore, Ballerina allows subdividing the code into multiple modules as well.
You can add more modules to the package using the
bal add command:
$ cd hello_world $ bal add util
This will create the
modules directory in the package root. The
modules/util directory is the root of the
The package structure after adding a non-default module will have the directory structure below.
. ├── Ballerina.toml ├── main.bal └── modules └── util ├── Module.md ├── resources ├── tests │ └── lib_test.bal └── util.bal 4 directories, 5 files
Import a module from the same package
You can access any public symbol from another module of the package by importing the particular module using an import declaration.
The import declaration syntax is as follows.
import module_name [as import_prefix];
In the above syntax:
import_prefixhas to be a valid Ballerina identifier and the
import_prefixis used to refer to public symbols in the declared module.
import_prefixis optional. If it is not available, the last part of the module name can be used.
In a package, which has the default module containing the
main.bal file and a non-default module named
hello-world.util, you can add a public function in the
hello_world.util module and use this function in the
main.bal file in the default module.
import hello_world.util; String formattedMsg = util:properCaseMessage("hello world!");
import-prefix is not given, the module name
util is used to refer to the symbols in the
For information on the structure of a package directory, see Package references.