Nemanja Kovacevic
Nemanja Kovacevic

Reputation: 3560

Guice not working as expected (with Tomcat, Jersey...)

I'm trying to build an app using Jersey, Rest, Tomcat, c3p0 etc.

I have a ConfigurationManager class I want to be an eager singleton, and Connection pool class I also want to be an eager singleton. Connection pool is using a Configuration Manager annotated with inject but configuration manager inside Connection pool is null, it's not injected for some reason. It's instantiated by guice I can see this from log.

When I inject it in Rest resource class it is working as expected.

Also when I inject it in StartupServlet it's null.

I would very much appreciate it if anyone can shed some light on this. Below you can find web.xml and classes.

web.xml

<servlet>
    <servlet-name>StartupServlet</servlet-name>
    <servlet-class>net.nemanjakovacevic.ft1p.configuration.StartupServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- set up Google Guice Servlet integration -->
<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
    <listener-class>net.nemanjakovacevic.ft1p.configuration.GuiceServletConfiguration</listener-class>
</listener>

GuiceServletConfiguration.java

public class GuiceServletConfiguration extends GuiceServletContextListener {

@Override
protected Injector getInjector() {
    return Guice.createInjector(new GuiceConfigurationModule(),  new JerseyServletModule() {

        @Override
        protected void configureServlets() {

            /* bind the REST resources */
            bind(Test.class);

            serve("/*").with(GuiceContainer.class);
        }

    });
}

}

GuiceConfigurationModule.java

public class GuiceConfigurationModule extends AbstractModule {

@Override
protected void configure() {
    bind(ConfigurationManager.class).asEagerSingleton();
    bind(ConnectionPool.class).asEagerSingleton();
}

}

ConfigurationManager

public class ConfigurationManager {
// Nothing important here, loading from config file
}

ConnectionPool (It's not working here)

public class ConnectionPool {

private static final Logger log = LoggerFactory.getLogger(ConnectionPool.class);

private ComboPooledDataSource pooledDataSource;

@Inject
private ConfigurationManager cManager;

public ConnectionPool() {
    log.info("Initializing c3p0 coonection pool");
    pooledDataSource = new ComboPooledDataSource();
    try {
//Null pointer exception here, cManager is null
        pooledDataSource.setDriverClass(cManager.getJdbcDriverClassName());
        pooledDataSource.setJdbcUrl(cManager.getJdbcUrl());
        pooledDataSource.setUser(cManager.getDatabaseUsername());
        pooledDataSource.setPassword(cManager.getDatabasePassword());
    } catch (PropertyVetoException e) {
        log.error("Exception during c3p0 initalisation.", e);
        //TODO obrada izuzetaka
    }
}
}

Test.java (It's working here)

@Path("/test")
public class Test {

@Inject
ConfigurationManager cManager;

@GET
@Path("/{param}")
public Response getMsg(@PathParam("param") String msg){
                    // cManager is not null, it's injected as it should be
        String output = cManager.getDatabaseHostName();
        return Response.status(200).entity(output).build();
}
}

Upvotes: 1

Views: 2006

Answers (1)

Mairbek Khadikov
Mairbek Khadikov

Reputation: 8089

Field ConfigurationManager cManager will be injected when object construction is completed. That's why you are getting NPE in constructor and everything is fine in Test.java class.

Consider replacing field injection with constructor injection.

Just try this code

public class ConnectionPool {
    @Inject
    public ConnectionPool(ConfigurationManager cManager) {
        ...
    }

}

Upvotes: 3

Related Questions