I am writing simple CRUD application which would fetch person records from database and I'm using SparkJava framework I have working code which fetches records from database but I would want to extract JOOQ DSLContext code and inject it as a bean and initialize it in another class in order to have more cleaner code, but I'm not sure how to achieve it here's main method which currently hold everything:
public static void main(String[] args) throws IOException {
final BasicDataSource ds = new BasicDataSource();
final Properties properties = new Properties();
properties.load(BankApiApplication.class.getResourceAsStream("/application.properties"));
ds.setDriverClassName(properties.getProperty("db.driver"));
ds.setUrl(properties.getProperty("db.url"));
ds.setUsername(properties.getProperty("db.username"));
ds.setPassword(properties.getProperty("db.password"));
final ConnectionProvider cp = new DataSourceConnectionProvider(ds);
final Configuration configuration = new DefaultConfiguration()
.set(cp)
.set(SQLDialect.H2)
.set(new ThreadLocalTransactionProvider(cp, true));
final DSLContext ctx = DSL.using(configuration);
final JSONFormat format = new JSONFormat().format(true).header(false).recordFormat(JSONFormat.RecordFormat.OBJECT);
port(8080);
get("/persons", (request, response) -> {
return ctx.select().from(Person.PERSON).fetch().formatJSON();
});
}
How I could extract code which initializes Datasource and configures DSLContext and instead I could just inject DSLContext or some kind of DSLContextHolder and do querying ?
So, in general, you want to inject the highest-level object you can. This is related to the Law of Demeter, which in short says that a component can know about its direct dependencies, but it shouldn't know about those dependencies' dependencies.
In your case, you're really only using DSLContext
(ctx
). [A note here: your code has a lot of two-letter names - it's pretty hard to follow. It would be easier if you wrote out e.g. ctx -> dslContext
, cp -> connectionProvider
]. This means you really only want your method to know about the DSLContext
, not its dependencies. Therefore, it would be good to pull the following out into a module, then inject just a DSLContext
:
Configuration
ConnectionProvider
Properties
BasicDataSource
If all these things are only used in this one main()
, you can write a single Provider
to return a DSLContext
. If some of these are used in multiple places (for more than instantiating this main()
's DSLContext
), then they can go in their own Provider
s. For example, here's what a Provider
for a DSLContext
would look like, if Configuration
was placed in its own Provider
:
public class MyModule extends AbstractModule {
// other providers
// ...
@Provides
@Singleton
public DSLContext dslContext(Configuration configuration) {
return SL.using(configuration);
}
}
Then, in your main()
, you would write:
Injector injector = Guice.createInjector(yourModule());
DSLContext myContext = injector.getInstance(DSLContext.class);
// ... use it