I'm writing a Java package to interact with a dynamo table, and I'm using Guice for DI. The package exposes a client to its users as follows -
// External client
public class Client {
DataManager manager;
public static Client getClient() {
return Guice.createInjector(new MyModule()).getInstance(Client.class);
}
}
// Manager class to interact with dynamo
public class DataManager {
AmazonDynamoDb amazonDynamoDb;
DynamoDbMapper dynamoDbMapper;
@Time // IMPORTANT - This is AOP style metric recording which records the amount of time taken to do a particular operation
public void addRecord();
public void deleteRecord();
...
}
// Class that represents an entry in the table
public class Data {
}
One of the use cases is that a table check has to performed before the client instance is returned to the users of this package. Which basically means that I have to call an initializeTable() function somewhere in my code. My question is where should I put that logic?
- In the constructor? Probably not because violates DI principles of doing only wiring in constructors, and makes testing difficult.
- Inside a Guice module? I could create a @Provides function that initializes the client and before returning it, runs the init() function. But a limiting factor here is that I have AOP style annotations that won't work if the object instances are not created by Guice itself.
What I ended up doing was this (performing injection on a module itself which would be registered with Guice in the Client#getClient() method)-
public class InitializingModule extends AbstractModule {
/**
* Perform injection on this instance so that the table initialization happens before any usable class is
* returned to the clients of this package.
*/
@Override
protected void configure() {
requestInjection(this);
}
/**
* Configure dynamoDB to check for and initialize the table.
*
* @param startupUtil
* @throws Exception
*/
@Inject
void configureDynamo(DynamoStartupUtil startupUtil) throws Exception {
startupUtil.initialize();
}
}
So where is this initialization logic supposed to go so that the principles of DI are not violated and the classes are easily testable? Note that Guice does not support @PostConstruct yet.