Project Setup and Layouts
Learn more details about recommended project layouts, customizing layouts and best practices.
Content
Start New Projects with cds init
Use cds init
to start new projects.
cds init <project-name>
cds init <project-name> --add-java
Following the ideas of Convention over Configuration and Grow as you go new CAP projects have a minimal setup. Yet as soon as you add models, you can deploy them to databases, and as soon as you add a first service definition, you get a full-fledged OData server up and running, for example using cds watch
.
Following the ideas of Convention over Configuration and Grow as you go new CAP projects have a minimal setup. Yet as soon as you add models, you can deploy them to databases, and as soon as you add a first service definition, you get a full-fledged OData server up and running, for example using mvn cds:watch
.
Learn more in the Getting Started in a Nutshell guide.
Default Project Layouts
Projects created with cds init
have this default layout:
Projects created with cds init --add-java
have this default layout:
Files/Folders | Description |
---|---|
app/ | UI content goes in here; one or more in subfolders |
db/ | Domain Models and database-related content go in here |
srv/ | Service definitions and implementations go in here |
package.json or pom.xml | your project descriptor |
While you’re free to choose your own project layout, we recommend adopting the following default layout to leverage built-in support and zero configuration.
You could argue that a domain model isn’t necessarily database-related, and if there’s a database involved, domain models can usually be deployed to it as is. Putting the domain models there help you to benefit from CAP’s convention-over-configuration default, to deploy all content from ./db to a database.
Customizing Layouts
Many cds
commands work with the above project layout by default. For example, when you run cds watch
, CDS models will be automatically fetched and loaded from these locations:
Many cds
and mvn cds
commands work with the above project layout by default. For example, when you run mvn cds:watch
or mvn spring-boot:run
, CDS models will be automatically fetched and loaded from these locations:
- db/index.cds or db/*.cds
- srv/index.cds or srv/*.cds
- app/index.cds or app/*.cds
- schema.cds
- services.cds
These locations are taken from a configuration option cds.roots
, which in turn you can inspect using the cds env
command:
cds env get roots
#> [ 'db/', 'srv/', 'app/', 'schema', 'services' ]
cds env get folders
#> { db:'db/', srv:'srv/', app:'app/' }
You can change these settings to adjust your project layout, for example, in your package.json file as documented in the Node.js Configuration guide:
{
"cds": {
"folders": { "db":"db/", "srv":"srv/", "app":"app/" },
"roots": [ <...cds.folders>, "schema", "services" ],
...
}
}
The values shown above reflect the defaults.
Best Practices
A project can comprise data models as well as content for multiple databases, multiple services, and multiple UI apps. These may end up in several deployables that go to different runtime containers. For example:
- All UI apps are deployed as static web content to frontend servers.
- All services including implementation go to single Node.js servers.
- The data models and content go to different database servers.
Good: Keep Related Pieces in One Project
Distributed deployment is common and by no means a reason to split everything into separate projects as you certainly want all pieces to be deployed in concert. So we recommend to always put related modules together in one project.
Rules of Thumb:
- Go for separate projects if the result has an independent lifecycle.
- Otherwise, put all related modules in one project.
- In particular never split along private interfaces.
Bad: Splitting into Projects per Deployable
In contrast, if you split into separate projects - worst case one per UI app and per each service - this would mean that each module would have an individual lifecycle and would have to be deployed separately. Suppose that you made changes to your service and corresponding ones to the UI app that uses it. You’d have to synchronize the deployments and if one fails the other one might be unusable.