docs/site/Inside-Loopback-Application.md
Digital transformation is changing how data and services are shared across Web/Mobile/IoT platforms. APIs allow easy and secure access to digital resources and capabilities of an organization by internal and external parties.
Developers are looking out for more productive ways of creating and consuming APIs.
Consider a typical Online Shopping site. First the UI requirements are
gathered. Customers would be provided a home page, a product list, a shopping
cart and an order history page.
Next, the API requirements are assessed. If the capability to choose products, add to cart and submit an order are exposed as secure APIs, they can be used by a web or mobile application which could be developed in-house or by a third party developer.
Once the API requirements are assessed,
Front end designers:
Can create an
Online Shopping prototypeto try the UI experience by using LoopBack's features to configure simple methods as remote API endpoints.
API developers:
Can assess API specifications and security options by creating and decorating remote methods with security options.
Back end developers:
Can create Entity-Relationship models from backend datasources using LoopBack's extensive model discovery features and connectors.
The example application loopback4-example-shopping is a nice place for developers to begin their LoopBack 4 journey.
In the following sections we will see how LoopBack can be used for the online shopping example.
For our Online Shopping site how the customer might interact with a web or
mobile application is the same.
Login use cases
| Use case | operations | summary |
|---|---|---|
| create a new user | POST /users | creates a user entity |
| query for a user | GET /users/{userId} | query for user entity by id |
| login as a user | POST /users/login | does basic authentication and returns a JWT |
Similar to this we can breakdown further use cases into API requirements.
Shopping use cases
Order use cases
In the example,
A product recommendations application is defined to mock shopping recommendation APIs. This also gives an appropriate use case to demonstrate invoking external APIs.
MongoDB is used for saving User and Order data. This demonstrates CRUD
operations on a model.
Redis is used for caching items in the shopping cart. This allows
demonstrating use of a KeyValue Connector as well as having multiple
datasources.
The API business logic is separated between various layers in LoopBack:
Controllers represent the API Endpoints. These endpoints
will have to authenticate incoming request, parse and validate as well as
orchestrate calls to Services and Repositories.
Services provide common interfaces
for external APIs and services. This allows invoking external services without
mentioning connection details every time. Services interchangeably also
provide common interfaces for locally available classes.
Models and Relations represent domain objects and provide entity relationship models.
Repositories represent the Entity layer for a specific
model and handle all CRUD operations on the model. They also use repository of
other models to handle entity relations.
LoopBack developers can configure simple controller classes and methods as remote endpoints. Out-of-the-box parsing and validation is done using the provided specification.
Developers typically create server-side "handler functions" for each route as
remote methods. In LoopBack, remote methods are defined in
controller classes and configured as API
endpoints with API decorators.
LoopBack has built-in decorators to indicate API specification and the expected arguments for the remote method.
For example,
login() method in the
UserManagementController
class is defined as /users/login API endpoint.findById in the
UserManagementController
is decorated with @param.path.string('userId') which means that the userId
parameter in the URL path is passed into the method at runtime.Dependency injection features in LoopBack is used to wire dependencies into constructors, class properties and methods.
The UserController in the shopping example needs to connect to a user service
to verify the user credentials and a JWT service to create a token. Having these
dependencies loosely coupled with the UserController will help developers of
the Login use case with separation of duties and inject mock services for
rapid testing.
For example, a TokenService interface is injected into the UserController to
verify and generate tokens. A
JWT Service
provides a local implementation of this interface specifically for JWTs.
Dependency injection is used to wire services and repositories with controllers dynamically at run time. We will also see that this feature is extensively used across LoopBack for all types of classes. For example, datasources are injected into repository classes.
Security implementations in LoopBack can be created as separate Authentication strategies and the
@authenticatedecorator can be used to define the authentication strategy of a particular endpoint.
For example,
jwt.whoAmI remote method in
UserController
is decorated with authenticate('jwt') to indicate the API endpoint is
authenticated with json web tokens.This helps in separation of security aspects of API endpoints from business logic and easy understanding of security specifications.
LoopBack provides extensive support in representing domain models and relations. Built-in
decoratorsare used to annotate property data types as well as entity relationships in aModelclass.
Models define the structure of domain objects. Model Relations help in defining entity composition and cardinalities like one-to-many or one-to-one.
Models can also be generated from existing tables in relational databases.
User and Order are domain objects in the shopping cart use case:
User model has a
has-many relation (ie., one-to-many) with Order
model. Hence the orders property in User model is annotated with the
@hasMany(() => Order) decorator.Order is composed with a list of products added in the shopping cart and
submitted towards the order. Hence the products property in Order model is
annotated as @property.array() to indicate that it is a list property.Order can be made only by one User. So, the userId property in
Order model is annotated with @belongsTo() decorator, to indicate Order
has a one-to-one relation with User.Repositories in LoopBack represent the
Entitylayer for querying and persisting a domain model. They also connect with other repositories to resolveEntity relations.
Applications displaying a user profile might need a list of associated recent
orders made by the user. The same also applies for an order page, some
associated user data could be needed. Querying for associated data for demands
from front end as well as for logical and persistence reasons is a common
requirement. Having a separate Entity layer helps in model driven CRUD
operations.
From the example,
User model data, the example uses a
UserRepository.Order model,
OrderRepository
is defined.UserRepository uses the entity composition defined in the User model
to create a has-many relation with the OrderRepositoryWe need appropriate drivers to connect with the backend datasources.
LoopBack has readily available connectors for most databases and other backend resources like REST, SOAP, Email, etc to provide easy to use CRUD operations and connection configurations.
In the example,
Redis datasource definition
uses the LoopBack kv-redis connector and
MongoDB datasource definition
uses the LoopBack mongodb connector.
The Shopping APIs have to be setup with configurations so that they are
accessible on a specific port, have a base url, etc. Also we may want to setup
various bootup activities if there are tasks to be completed
before the APIs are available online.
The
ShoppingApplication class
is a palette to hold all common configurations and startup activities of the
Shopping microservice.
The ShoppingApplication class extends the RestApplication class from the
@loopback\rest package and so has inherited the capabilities of the in-built
LoopBack Server to boot, start and stop. The application can
now be booted and started by calling the app.boot and app.start methods
respectively. In the example, this call is made from the
index.ts
file.
LoopBack as a model-driven framework provides various provisions for quick and easy API development :
ServicesRepository pattern