liveBook · Manning

Dependency injection

As explained in Rust Servers, Services, and Apps

Dependency injection is a technique in which a component receives the resources or services it needs from an external provider.

Dependency injection supplies a component's required resources or services from outside it. In an Actix Web service, application state carries shared data and database connections into request handlers. section 4.3.3 section 3.2.2

A typical server setup proceeds as follows:

Injecting a PostgreSQL pool

Define AppState with a db: PgPool field, construct it from the database URL, and configure the Actix application with the resulting shared state. Handlers can then accept web::Data<AppState> alongside path parameters and use the pool for database operations. section 8.1 section 4.3.3

Listing 4.3 The tutor web service’s main() function
use actix_web::{web, App, HttpServer};
use dotenv::dotenv;
use sqlx::postgres::PgPool;
use std::env;
use std::io;
use std::sync::Mutex;
 
#[path = "../iter2/handlers.rs"]
mod handlers;
#[path = "../iter2/models.rs"]
mod models;
#[path = "../iter2/routes.rs"]
mod routes;
#[path = "../iter2/state.rs"]
mod state;
 
use routes::*;
use state::AppState;
 
#[actix_rt::main]
async fn main() -> io::Result<()> {
   dotenv().ok();                                                  #1
 
   let database_url = env::var("DATABASE_URL").expect(
     "DATABASE_URL is not set in .env file");
   let db_pool = PgPool::connect(&database_url).await.unwrap();    #2
   // Construct App State
   let shared_data = web::Data::new(AppState {
       health_check_response: "I'm good. You've already
       asked me ".to_string(),
       visit_count: Mutex::new(0),
       db: db_pool,
   });
   //Construct app and configure routes
   let app = move || {
       App::new()
           .app_data(shared_data.clone())                          #3
           .configure(general_routes)
           .configure(course_routes)
   };
 
   //Start HTTP server
 
   HttpServer::new(app).bind("127.0.0.1:3000")?.run().await
}

Trace the complete main function from environment loading and pool creation through AppState construction, application configuration, and server startup. section 4.3.3

How Rust Servers, Services, and Apps covers it

How deep it goes
Builds injection incrementally through state structs, web::Data registration, handler parameters, and a compiling server; defers completed database logic.
Examples
Uses a visit-count health check and a tutor service that injects a PostgreSQL pool into course and registration handlers.
What you can do after
Build it from scratch by registering shared Actix state and retrieving it from handler parameters.
How it connects
Connects application state, web handlers, connection pools, routes, and database access.

Also explained in

Compare how 21 books explain dependency injection →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust Servers, Services, and Apps. The section links point to the parts of the book it draws on.