I have a Database-JDBC-Connection
class and a Setup
class that loads the details of the username, password, database host etc and many other properties by reading a configuration file. The database class has a dependency on Setup class and hence I am using Guice DI for my tests
@Guice(module = DBModule.class)
public class MyTest {
@Inject DatabaseConn dbconn
}
And the Database Connnection class which depends on my Setup class.
@Guice(module = Setup.class)
public class DatabaseConn {
@Inject Setup setupInstance.
}
PS : The @Guice
annotation is used from the testng framework. More details Guice-Dependency-Injection-via-TestNG
After the instance of Setup class is created, I need to load the configuration properties (Not using Names.bindProprties()
), perform some prerequisites in terms of asserting that certain properties exist and also try to resolve their values from Environment variables, System properties etc. or any other source, based on our framework.
import com.google.inject.*
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import aaa.bbb.ccc.Setup
public class SetupModule implements Module {
private static Logger logger = LogManager.getLogger(SetupModule);
@Override
void configure(Binder binder){}
@Provides @Singleton
Setup getSetupProperties(){
System.out.println("DEBUG : Loading setup properties")
logger.info("Loading setup properties")
Setup s = new Setup();
logger.info("Loads the properties from configuration file.");
s.loadProperties();
logger.info("Verifies certain mandatory properties");
s.performPrerequisites();
logger.info("Resolve values from env. and system if required.");
s.resolveValues();
System.out.println("DEBUG : Done")
return s
}
}
However, this Setup class uses Log4j logger and I want to log the additional processing that I am doing (loading, asserting, resolving) using the log4j logger.
I have implemented the log4j listener etc. as suggested here Guice-Custom-Injection but the instance of logger is created in phase 2 of Guice injection. i.e. if you look at the sample code, the getSetupProperties() is initialized in the Guice Phase 1 and thus the log4j logger instance is not instantiated by then.
To prove that - I added the sysout in the injectMembers method of member injector class
@Override
void injectMembers(T instance) {
try {
System.out.println("DEBUG : Setting instance of logger")
field.set(instance, logger)
} catch (IllegalAccessException e) {
throw new RuntimeException(e)
}
}
So when I run, I see the following on the Sys out
DEBUG : Loading setup properties
DEBUG : Done
DEBUG : Setting instance of logger
Hence, nothing from the getSetupProperties method gets logged to my log4j log file.
My Database-Connection class uses
@Inject Setup setupProperties
and the above works. But because of the lack of logging, I am not able to debug anything in case of issues.
Hence, I want some mechanism that would instantiate my log4j logger during Guice phase 1 itself.
The question is more generic as well - i.e. for the cases where there are chained dependencies and before the 2nd dependent consumes the 1st instance, there is certain additional processing to be done. How to make sure that we have our logger available for those processing methods ?
There are 3 phases defined by Guice. More details Guice-Wiki
Appreciate any inputs if anybody has a direct solution or perhaps a workaround for the same.
PS : I have tried to give a snapshot of the problem, given that I cannot disclose exact implementation due to org policies.
Thanks.