create main factory class

This commit is contained in:
Bartosz Wieczorek 2018-03-22 15:59:26 +01:00
parent 369dbd244d
commit bd6a6aefe3
12 changed files with 124 additions and 91 deletions

View File

@ -3,16 +3,12 @@
#include <eedb/pg/config.hpp>
#include <eedb/pg/connection.hpp>
#include <eedb/pg/CategoriesRepository.hpp>
#include <eedb/pg/Users.hpp>
#include <eedb/pg/ItemsRepository.hpp>
#include <eedb/pg/Factory.hpp>
#include <eedb/WebApplicationFactory.hpp>
#include <eedb/WebServer.hpp>
#include <Wt/WApplication.h>
#include <set>
#include <Wt/WEnvironment.h>
static auto _createSinks() {
std::vector< spdlog::sink_ptr > sinks;
@ -45,42 +41,21 @@ static auto createDbConnection(std::function< bool(const std::string &, std::str
}
}
std::unique_ptr< Wt::WApplication >createApplication (const Wt::WEnvironment &env) {
auto server = env.server();
auto connection = createDbConnection([server](const auto & name, auto & val) { //
return server->readConfigurationProperty(name, val);
});
auto factory = std::make_unique< eedb::pg::FactoryImpl >(std::move(connection));
return eedb::WebApplicationFactory{}.create(std::move(factory), env);
}
int main(int argc, char ** argv) {
initializeLogs();
std::set< std::unique_ptr< eedb::pg::Connection > > activeConnections;
eedb::WebServer server{argc, argv};
server.run([&activeConnections, &server](const auto & env) {
// in order to extend the lifetime of new connection to the lifetime of web application, we need to
// hold it in external container
auto dbIt = activeConnections.emplace(createDbConnection(server.getPropertiesReader())).first;
eedb::WebApplicationFactory factory;
return factory.create(
[&activeConnections, dbIt]() {
// remove connection hold by application from container
spdlog::get("default")->info("Removing database connection from connection list");
activeConnections.erase(dbIt);
},
// users factory
[db = dbIt->get()]() { //
spdlog::get("default")->info("Creating user repository");
return std::make_unique< eedb::pg::UsersImpl >(*db);
},
// categories repository
[db = dbIt->get()]() { //
return std::make_unique< eedb::pg::CategoriesRepositoryImpl >(*db);
},
// items repository
// [db = dbIt->get()]() { //
// return std::make_unique< eeItemsRepository >(*db);
// },
env);
});
server.run(createApplication);
return 0;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <eedb/Factory.hpp>
namespace eedb::pg {
class Connection;
class FactoryImpl : public Factory {
public:
FactoryImpl(std::unique_ptr< Connection > connection);
~FactoryImpl() override;
std::unique_ptr< Users > usersRepository() const override;
std::unique_ptr< CategoriesRepository > categoriesRepository() const override;
std::unique_ptr< ItemsRepository > itemsRepository() const override;
private:
std::unique_ptr< Connection > _connection;
};
} // namespace eedb::pg

View File

@ -0,0 +1,25 @@
#include <eedb/pg/Factory.hpp>
#include <eedb/pg/CategoriesRepository.hpp>
#include <eedb/pg/ItemsRepository.hpp>
#include <eedb/pg/Users.hpp>
#include <eedb/pg/connection.hpp>
namespace eedb::pg {
FactoryImpl::FactoryImpl(std::unique_ptr< Connection > connection) : _connection{std::move(connection)} {}
FactoryImpl::~FactoryImpl() {}
std::unique_ptr< Users > FactoryImpl::usersRepository() const {
return std::make_unique< UsersImpl >(*_connection);
}
std::unique_ptr< CategoriesRepository > FactoryImpl::categoriesRepository() const {
return std::make_unique< CategoriesRepositoryImpl >(*_connection);
}
std::unique_ptr< ItemsRepository > FactoryImpl::itemsRepository() const {
return std::make_unique< ItemsRepositoryImpl >(*_connection);
}
} // namespace eedb::pg

View File

@ -0,0 +1,22 @@
#pragma once
#include <memory>
namespace eedb {
class Users;
class CategoriesRepository;
class ItemsRepository;
class Factory {
public:
virtual ~Factory() = default;
virtual std::unique_ptr< Users > usersRepository() const = 0;
virtual std::unique_ptr< CategoriesRepository > categoriesRepository() const = 0;
virtual std::unique_ptr< ItemsRepository > itemsRepository() const = 0;
};
} // namespace eedb

View File

@ -13,6 +13,7 @@ namespace eedb {
class AuthPage;
class HomePage;
class IWebSession;
class Factory;
using AuthPageFactory = std::function< std::unique_ptr< AuthPage >() >;
using HomePageFactory = std::function< std::unique_ptr< HomePage >(Wt::Auth::AuthWidget &) >;
@ -20,8 +21,11 @@ using HomePageFactory = std::function< std::unique_ptr< HomePage >(Wt::Auth::Aut
class WebApplication : public Wt::WApplication {
public:
enum class LoginState { weak, strong };
WebApplication(std::unique_ptr< eedb::IWebSession > session, AuthPageFactory authPageFactory, HomePageFactory homePageFactory);
~WebApplication() {}
WebApplication(std::unique_ptr< eedb::IWebSession > session,
AuthPageFactory authPageFactory,
HomePageFactory homePageFactory,
std::unique_ptr< Factory > repository);
~WebApplication();
void authEventLogin(LoginState state);
void authEventLogout();
@ -31,5 +35,6 @@ class WebApplication : public Wt::WApplication {
std::unique_ptr< eedb::IWebSession > _session;
HomePageFactory _homePageFactory;
std::unique_ptr< Wt::Auth::AuthWidget > _authWidget;
std::unique_ptr< Factory > _factory;
};
} // namespace eedb

View File

@ -4,9 +4,7 @@
#include <memory>
namespace eedb {
class CategoriesRepository;
class Users;
class User;
class Factory;
} // namespace eedb
namespace Wt {
@ -18,12 +16,6 @@ namespace eedb {
class WebApplicationFactory {
public:
using UsersFactory = std::function< std::unique_ptr< eedb::Users >() >;
using CategoriesFactory = std::function< std::unique_ptr< eedb::CategoriesRepository >() >;
using DbHolder = std::function< void() >;
public:
std::unique_ptr< Wt::WApplication >
create(DbHolder db, UsersFactory users, CategoriesFactory categories, const Wt::WEnvironment & env) const;
std::unique_ptr< Wt::WApplication > create( std::unique_ptr< Factory > factory, const Wt::WEnvironment & env) const;
};
} // namespace eedb

View File

@ -2,7 +2,7 @@
#include <functional>
#include <utils/spimpl.hpp>
#include <Wt/WServer.h>
namespace Wt {
class WApplication;
@ -13,17 +13,14 @@ class WServer;
namespace eedb {
class WebServer {
class WebServer : public Wt::WServer {
public:
using AppCreator = std::function< std::unique_ptr< Wt::WApplication >(const Wt::WEnvironment &) >;
using AppFactory = std::function< std::unique_ptr< Wt::WApplication >(const Wt::WEnvironment &) >;
WebServer(int argc, char ** argv);
std::function<bool(const std::string &, std::string& )> getPropertiesReader() const;
void run(AppCreator creator);
private:
spimpl::unique_impl_ptr< Wt::WServer > _server;
void run(AppFactory factory);
};
} // namespace eedb

View File

@ -26,14 +26,12 @@ class IWebSession : public Session {
class WebSession final : public IWebSession {
public:
explicit WebSession(const Wt::WEnvironment & env, std::function<void()> dbCloser);
~WebSession() override;
explicit WebSession(const Wt::WEnvironment & env);
virtual const Wt::WEnvironment & enviroment() const override;
Wt::Auth::Login & login() override;
private:
std::function<void()> _dbCloser;
Wt::Auth::Login _login;
const Wt::WEnvironment & _env;
};

View File

@ -1,5 +1,6 @@
#include <eedb/WebApplication.hpp>
#include <eedb/Factory.hpp>
#include <eedb/WebSession.hpp>
#include <eedb/auth/PgUserAuth.hpp>
@ -13,17 +14,9 @@
#include <Wt/Auth/AuthWidget.h>
#include <Wt/WApplication.h>
#include <Wt/WBorderLayout.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WEnvironment.h>
#include <Wt/WLineEdit.h>
#include <Wt/WMessageBox.h>
#include <Wt/WNavigationBar.h>
#include <Wt/WPopupMenu.h>
#include <Wt/WServer.h>
#include <Wt/WStackedWidget.h>
#include <Wt/WText.h>
#include <Wt/WTextArea.h>
#include <Wt/WTheme.h>
#include <spdlog/spdlog.h>
@ -34,8 +27,12 @@ namespace eedb {
WebApplication::WebApplication(std::unique_ptr< eedb::IWebSession > session,
AuthPageFactory authPageFactory,
HomePageFactory homePageFactory)
: Wt::WApplication(session->enviroment()), _session(move(session)), _homePageFactory(move(homePageFactory)) {
HomePageFactory homePageFactory,
std::unique_ptr< Factory > repository)
: Wt::WApplication(session->enviroment()),
_session(move(session)),
_homePageFactory(move(homePageFactory)),
_factory{std::move(repository)} {
useStyleSheet("/resources/style.css");
setTheme(eedb::BootstrapTheme{}.create());
@ -49,6 +46,8 @@ WebApplication::WebApplication(std::unique_ptr< eedb::IWebSession > session,
root()->addWidget(std::move(authPage))->processEnvironment();
}
WebApplication::~WebApplication() {}
void WebApplication::authEventLogin(WebApplication::LoginState) {
if(!_authWidget) {
_authWidget = std::unique_ptr< Wt::Auth::AuthWidget >(

View File

@ -11,6 +11,7 @@
#include <widget/DefaultNavigationBar.hpp>
#include <eedb/Category.hpp>
#include <eedb/Factory.hpp>
#include <eedb/User.hpp>
#include <eedb/Users.hpp>
@ -20,16 +21,16 @@
#include <Wt/WText.h>
namespace eedb {
std::unique_ptr< Wt::WApplication >
WebApplicationFactory::create(DbHolder db, UsersFactory users, CategoriesFactory categories, const Wt::WEnvironment & env) const {
std::unique_ptr< Wt::WApplication > WebApplicationFactory::create(std::unique_ptr< Factory > repository,
const Wt::WEnvironment & env) const {
using std::make_unique;
using std::move;
using std::unique_ptr;
auto session = std::make_unique< eedb::WebSession >(env, std::move(db));
auto session = std::make_unique< eedb::WebSession >(env);
auto authPageFactory = [ usersRegistry = std::move(users), session = session.get() ]()->std::unique_ptr< eedb::AuthPage > {
auto userDatabase = make_unique< eedb::auth::UserDatabase >(usersRegistry());
auto authPageFactory = [ repository = repository.get(), session = session.get() ]()->std::unique_ptr< eedb::AuthPage > {
auto userDatabase = make_unique< eedb::auth::UserDatabase >(repository->usersRepository());
auto services = eedb::auth::Services();
auto & login = session->login();
@ -41,6 +42,8 @@ WebApplicationFactory::create(DbHolder db, UsersFactory users, CategoriesFactory
return make_unique< eedb::DefaultHomePage >(*session, navigationBarFactory(authWidget));
};
return make_unique< eedb::WebApplication >(std::move(session), std::move(authPageFactory), std::move(homePageFactory));
return make_unique< eedb::WebApplication >(
std::move(session), std::move(authPageFactory), std::move(homePageFactory), std::move(repository));
}
} // namespace eedb

View File

@ -8,23 +8,21 @@
namespace eedb {
WebServer::WebServer(int argc, char ** argv) : _server{spimpl::make_unique_impl< Wt::WServer >(argc, argv, WTHTTP_CONFIGURATION)} {}
WebServer::WebServer(int argc, char ** argv) : Wt::WServer(argc, argv, WTHTTP_CONFIGURATION) {}
std::function< bool(const std::string &, std::string &) > WebServer::getPropertiesReader() const {
return [server = _server.get()](const auto & name, auto & val) {
return server->readConfigurationProperty(name, val);
};
}
void WebServer::run(WebServer::AppCreator creator) {
void WebServer::run(WebServer::AppFactory factory) {
try {
auto _run = [&creator](const auto & env) {
auto application = creator(env);
auto _run = [&factory](const auto & env) {
auto application = factory(env);
return application;
};
_server->addEntryPoint(Wt::EntryPointType::Application, _run);
this->addEntryPoint(Wt::EntryPointType::Application, _run);
eedb::auth::Services::configureAuth();
_server->run();
Wt::WServer::run();
} catch(Wt::WServer::Exception & e) {
std::cerr << e.what() << std::endl;
} catch(std::exception & e) {

View File

@ -3,11 +3,7 @@
#include <eedb/auth/PgUserAuth.hpp>
namespace eedb {
WebSession::WebSession(const Wt::WEnvironment & env, std::function< void() > dbCloser) : _dbCloser{std::move(dbCloser)}, _env(env) {}
WebSession::~WebSession() {
_dbCloser();
}
WebSession::WebSession(const Wt::WEnvironment & env) : _env(env) {}
const Wt::WEnvironment & WebSession::enviroment() const {
return _env;