I call the trait method in directory B in directory A, which will not take effect

When I pass the user_service.rs call user_dao.rs , it does not success call user_dao trait method in Dao, what happened? Do I should to change to the implementation method of struct? I'm a little confused between trait and struct. I usually look at trait as an interface.

UserDao::user_register(&a, &user_dto); Call not effective

This is my directory structure:

api
 |_user_api.rs
service
 |_user_service.rs
dao
 |_user_dao.rs
 |
main.rs

user_service.rs:

use crate::dao::user_dao::UserDao;

use crate::domain::dto::user::UserRegisterDto;
use crate::domain::entity::user::UserRegister;

pub fn save_user(user_dto: &UserRegisterDto) {
    println!("userdto: {:?}", user_dto);

    let a = UserRegister{
        id: Some(String::from("55")),
        user_name: Some(String::from("55")),
        user_password: Some(String::from("55")),
        name: Some(String::from("55")),
        phone: Some(String::from("55")),
    };

    UserDao::user_register(&a, &user_dto);
}

user_dao.rs:

#[async_trait]
pub trait UserDao {
    async fn user_register(&self, user_dto: &UserRegisterDto);
}

#[async_trait]
impl UserDao for UserRegister{

    async fn user_register(&self, user_dto: &UserRegisterDto) {

        println!("come in");

        let mybatis = database::conn().await;

        println!("in execution");

        let user = UserRegister {
            id: user_dto.id.clone(),
            user_name: user_dto.name.clone(),
            user_password: user_dto.user_password.clone(),
            name: user_dto.name.clone(),
            phone: user_dto.phone.clone(),
        };

        println!("{:?}", user);
    
        mybatis.save(&user,&[]).await.unwrap();
    }
}

Do you have a file dao.rs or dao/mod.rs? If so, what does it contain?

I have, and I have mod.rs In every directory.

dao/mod.rs

pub mod user_dao;

The issue might be that user_register() returns a Future, but you aren't awaiting it. Does it work if you make save_user() an async fn and call UserDao::user_register(...).await;?

When I comment out #[async_trait] and await, he can call, but why? If so, do I need to use async await in my service module

It's not enough to learn to rust. I have to look at cargo, because I don't know how to build like maven and gradle. After reading cargo, I find that can't do it again. I also need to look at async and await

infinite loop......

Yes, for an async function call to take effect, you must await the returned Future. To do this, your service module either needs to be async itself, or explicitly block on the async runtime.

The #[async_trait] places a #[must_use] on the method, since it has no effect unless it is awaited. So you should be getting an unused_must_use warning from the compiler, unless you silenced the lint.

1 Like

what attribute is should used on the save_user() method? Obviously, it can't use #[async_trait]

You must declare it as an async fn, then call it as save_user(user_dto).await.

Yes, that's how I use it, but I find that I can't get into the method in the service directory when I call the API, lol~

new service user_save():

use crate::dao::user_dao::UserDao;

use crate::domain::dto::user::UserRegisterDto;
use crate::domain::entity::user::UserRegister;

pub async fn save_user(user_dto: &UserRegisterDto) {
    println!("userdto: {:?}", user_dto);

    let a = UserRegister{
        id: Some(String::from("55")),
        user_name: Some(String::from("55")),
        user_password: Some(String::from("55")),
        name: Some(String::from("55")),
        phone: Some(String::from("55")),
    };

    UserDao::user_register(&a, &user_dto).await;
}

api:

#[macro_use]
extern crate mybatis;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate async_trait;

mod config;
mod domain;
mod dao;
mod service;
mod api;
mod common;

use actix_web::{get, web, App, HttpServer, Responder};
use api::user_api;

#[tokio::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/hello", web::get().to(|| async { "Hello World!" }))
            .service(user_api::login)
    })
    .bind(("127.0.0.1", 8082))?
    .run()
    .await
}

What isn't working in this code? How are you trying to call save_user()?

When I make a request http://localhost:8082/user/register

It does not enter the service method

How is user_api::login defined?

Thank very much. It has been solved. I found that if want to use asynchronous working mode, must use await in the method called :slight_smile: