Skip to content

Commit

Permalink
More flexible guice configuration!
Browse files Browse the repository at this point in the history
  • Loading branch information
jjlauer committed Feb 29, 2016
1 parent 3bf499f commit 12c8806
Show file tree
Hide file tree
Showing 33 changed files with 1,141 additions and 366 deletions.
34 changes: 19 additions & 15 deletions ninja-core/src/main/java/ninja/Bootstrap.java
Expand Up @@ -38,6 +38,9 @@
import com.google.inject.Module; import com.google.inject.Module;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.google.inject.Stage; import com.google.inject.Stage;
import ninja.conf.FrameworkModule;
import ninja.conf.NinjaBaseModule;
import ninja.conf.NinjaClassicModule;


/** /**
* Bootstrap for a Ninja application. Assists with initializing logging, * Bootstrap for a Ninja application. Assists with initializing logging,
Expand Down Expand Up @@ -117,7 +120,6 @@ public synchronized void shutdown() {
Ninja ninja = injector.getInstance(Ninja.class); Ninja ninja = injector.getInstance(Ninja.class);
ninja.onFrameworkShutdown(); ninja.onFrameworkShutdown();
injector = null; injector = null;
ninja = null;
} else { } else {
logger.error("Shutdown of Ninja not clean => injector already null."); logger.error("Shutdown of Ninja not clean => injector already null.");
} }
Expand All @@ -133,36 +135,38 @@ public void addModule(Module module) {


protected void configure() throws Exception { protected void configure() throws Exception {


// Bind lifecycle support
addModule(LifecycleSupport.getModule());

// Scheduling support
addModule(SchedulerSupport.getModule());

// Base configuration of Ninja // Base configuration of Ninja
addModule(new Configuration(ninjaProperties)); addModule(new NinjaBaseModule(ninjaProperties));


// Main application module (conf.Module or com.example.conf.Module) // Main application module (conf.Module or com.example.conf.Module)
String applicationModuleClassName String applicationModuleClassName
= resolveApplicationClassName(APPLICATION_GUICE_MODULE_CONVENTION_LOCATION); = resolveApplicationClassName(APPLICATION_GUICE_MODULE_CONVENTION_LOCATION);


AbstractModule applicationModule = null;

if (doesClassExist(applicationModuleClassName)) { if (doesClassExist(applicationModuleClassName)) {

Class<?> applicationModuleClass = Class Class<?> applicationModuleClass = Class
.forName(applicationModuleClassName); .forName(applicationModuleClassName);


AbstractModule applicationConfiguration = null;

// Tries to instantiate module by giving the NinjaProperties as constructor arg // Tries to instantiate module by giving the NinjaProperties as constructor arg
try { try {
applicationConfiguration = (AbstractModule) applicationModuleClass applicationModule = (AbstractModule) applicationModuleClass
.getConstructor(NinjaProperties.class).newInstance(ninjaProperties); .getConstructor(NinjaProperties.class).newInstance(ninjaProperties);
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
applicationConfiguration = (AbstractModule) applicationModuleClass applicationModule = (AbstractModule) applicationModuleClass
.getConstructor().newInstance(); .getConstructor().newInstance();
} }

}
addModule(applicationConfiguration);
// Slipstream in the "classic" ninja configuration?
if (applicationModule == null || !(applicationModule instanceof FrameworkModule)) {
// Classic configuration of Ninja
logger.info("Enabling Ninja classic configuration");
addModule(new NinjaClassicModule(ninjaProperties));
}

if (applicationModule != null) {
addModule(applicationModule);
} }


// Ninja module // Ninja module
Expand Down
2 changes: 1 addition & 1 deletion ninja-core/src/main/java/ninja/RouteBuilderImpl.java
Expand Up @@ -29,7 +29,7 @@


import com.google.inject.Injector; import com.google.inject.Injector;


class RouteBuilderImpl implements RouteBuilder { public class RouteBuilderImpl implements RouteBuilder {


private static final Logger log = LoggerFactory private static final Logger log = LoggerFactory
.getLogger(RouteBuilder.class); .getLogger(RouteBuilder.class);
Expand Down
Expand Up @@ -46,24 +46,9 @@ public class BodyParserEngineManagerImpl implements BodyParserEngineManager {
private final Map<String, Provider<? extends BodyParserEngine>> contentTypeToBodyParserMap; private final Map<String, Provider<? extends BodyParserEngine>> contentTypeToBodyParserMap;


@Inject @Inject
public BodyParserEngineManagerImpl(Provider<BodyParserEnginePost> bodyParserEnginePost, public BodyParserEngineManagerImpl(Injector injector) {
Provider<BodyParserEngineJson> bodyParserEngineJson,
Provider<BodyParserEngineXml> bodyParserEngineXml,
Injector injector) {


Map<String, Provider<? extends BodyParserEngine>> map = Maps.newHashMap(); Map<String, Provider<? extends BodyParserEngine>> map = Maps.newHashMap();


// First put the built in ones in, this is so they can be overridden by
// custom bindings
map.put(bodyParserEnginePost.get().getContentType(),
bodyParserEnginePost);
map.put(bodyParserEngineJson.get().getContentType(),
bodyParserEngineJson);
map.put(bodyParserEngineXml.get().getContentType(),
bodyParserEngineXml);


// Now lookup all explicit bindings, and find the ones that implement // Now lookup all explicit bindings, and find the ones that implement
// BodyParserEngine // BodyParserEngine
for (Map.Entry<Key<?>, Binding<?>> binding : injector.getBindings() for (Map.Entry<Key<?>, Binding<?>> binding : injector.getBindings()
Expand Down Expand Up @@ -100,7 +85,7 @@ public BodyParserEngine getBodyParserEngineForContentType(String contentType) {


} }


protected void logBodyParserEngines() { final protected void logBodyParserEngines() {
List<String> outputTypes = Lists.newArrayList(getContentTypes()); List<String> outputTypes = Lists.newArrayList(getContentTypes());
Collections.sort(outputTypes); Collections.sort(outputTypes);


Expand Down
24 changes: 24 additions & 0 deletions ninja-core/src/main/java/ninja/cache/CacheException.java
@@ -0,0 +1,24 @@
/*
* Copyright 2016 ninjaframework.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ninja.cache;

public class CacheException extends RuntimeException {

public CacheException(String msg, Throwable t) {
super(msg, t);
}

}
93 changes: 31 additions & 62 deletions ninja-core/src/main/java/ninja/cache/CacheProvider.java
Expand Up @@ -16,6 +16,8 @@


package ninja.cache; package ninja.cache;


import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import ninja.utils.NinjaConstant; import ninja.utils.NinjaConstant;
import ninja.utils.NinjaProperties; import ninja.utils.NinjaProperties;


Expand All @@ -25,84 +27,51 @@
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provider; import com.google.inject.Provider;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import ninja.utils.ImplFromPropertiesFactory;
import org.slf4j.LoggerFactory;


/** /**
* A provider that determines which implementation to load as Cache based on * A provider that determines which implementation to load as a Cache based on
* the value of key {@link CacheConstant#CACHE_IMPLEMENTATION} in * the value of a configuration key in {@link NinjaProperties} (aka application.conf).
* {@link NinjaProperties} (aka application.conf). *
* The configured implementation is only resolved when its actually used vs.
* at application startup.
* *
* If this variable is set the instance for that class is * If this variable is set the instance for that class is
* instantiated and used as cache implementation. * instantiated and used as cache implementation.
* *
* If the variable is not set {@link CacheEhCacheImpl} is used by default. * If the variable is not set {@link CacheEhCacheImpl} is used by default.
*
*
* @author ra
*
*/ */
@Singleton @Singleton
public class CacheProvider implements Provider<Cache> { public class CacheProvider implements Provider<Cache> {

static private final Logger logger = LoggerFactory.getLogger(CacheProvider.class);
private final NinjaProperties ninjaProperties;
private final Injector injector; private final ImplFromPropertiesFactory<Cache> factory;

private final Supplier<Cache> supplier;
private final Cache cache;
private final Logger logger;

@Inject @Inject
public CacheProvider( public CacheProvider(Injector injector, NinjaProperties ninjaProperties) {
Injector injector, this.factory = new ImplFromPropertiesFactory<>(
NinjaProperties ninjaProperties, injector,
Logger logger) { ninjaProperties,

NinjaConstant.CACHE_IMPLEMENTATION,
this.ninjaProperties = ninjaProperties; Cache.class,
this.injector = injector; "ninja.cache.CacheEhCacheImpl",
this.logger = logger; true,
logger);



// lazy singleton
Class<? extends Cache> cacheClass = null; this.supplier = Suppliers.memoize(new Supplier<Cache>() {

@Override
String cacheImplClassName = ninjaProperties.get(NinjaConstant.CACHE_IMPLEMENTATION); public Cache get() {

return factory.create();
if (cacheImplClassName != null) {
try {

Class<?> clazz = Class.forName(cacheImplClassName);
cacheClass = clazz.asSubclass(Cache.class);

logger.info("Using the {} as implementation for caching.", cacheClass);

} catch (ClassNotFoundException e) {

throw new RuntimeException(
"Class defined in configuration " + NinjaConstant.CACHE_IMPLEMENTATION +
"not found (" + cacheClass + ")", e);

} catch (ClassCastException e) {

throw new RuntimeException(
"Class defined in configuration "
+ NinjaConstant.CACHE_IMPLEMENTATION +
"is not an instance of interface cache ("
+ cacheClass + ")", e);
} }
} });

if (cacheClass == null) {
// load default implementation
cacheClass = CacheEhCacheImpl.class;
logger.info("Using default eh cache implementation. ({}) ", cacheClass);

}

cache = injector.getInstance(cacheClass);

} }


@Override @Override
public Cache get() { public Cache get() {
// only called once => reference cached by guice... return this.supplier.get();
return cache;

} }

} }
3 changes: 1 addition & 2 deletions ninja-core/src/main/java/ninja/cache/NinjaCache.java
Expand Up @@ -20,14 +20,13 @@
import java.io.Serializable; import java.io.Serializable;
import java.util.Map; import java.util.Map;


import net.sf.ehcache.CacheException;
import ninja.utils.TimeUtil; import ninja.utils.TimeUtil;


import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;


/** /**
* A convenience class to access the underlaying cache implementation. * A convenience class to access the underlying cache implementation.
* *
* Makes getting and setting of objects a lot simpler. * Makes getting and setting of objects a lot simpler.
* *
Expand Down
28 changes: 28 additions & 0 deletions ninja-core/src/main/java/ninja/conf/FrameworkModule.java
@@ -0,0 +1,28 @@
/*
* Copyright 2016 ninjaframework.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ninja.conf;

import com.google.inject.AbstractModule;

/**
* Application modules that extend this class will skip Ninja's default
* "classic" configuration and start with an empty slate.
*/
public abstract class FrameworkModule extends AbstractModule {

// intentionally empty

}
Expand Up @@ -14,74 +14,51 @@
* limitations under the License. * limitations under the License.
*/ */


package ninja; package ninja.conf;


import ninja.cache.Cache; import ninja.*;
import ninja.cache.CacheProvider;
import ninja.jpa.JpaModule;
import ninja.migrations.MigrationInitializer;
import ninja.postoffice.Postoffice;
import ninja.postoffice.guice.PostofficeProvider;
import ninja.utils.LoggerProvider; import ninja.utils.LoggerProvider;
import ninja.utils.NinjaProperties; import ninja.utils.NinjaProperties;
import ninja.utils.NinjaPropertiesImpl; import ninja.utils.NinjaPropertiesImpl;
import ninja.utils.ObjectMapperProvider;
import ninja.utils.XmlMapperProvider;


import org.slf4j.Logger; import org.slf4j.Logger;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.google.inject.multibindings.OptionalBinder; import ninja.lifecycle.LifecycleSupport;
import ninja.scheduler.SchedulerSupport;


/** /**
* The basic configuration of the main ninja framework. * The basic configuration of the main ninja framework.
*
* @author ra
*
*/ */
public class Configuration extends AbstractModule { public class NinjaBaseModule extends AbstractModule {


private final NinjaPropertiesImpl ninjaProperties; private final NinjaPropertiesImpl ninjaProperties;


public Configuration(NinjaPropertiesImpl ninjaProperties) { public NinjaBaseModule(NinjaPropertiesImpl ninjaProperties) {
this.ninjaProperties = ninjaProperties; this.ninjaProperties = ninjaProperties;
} }


@Override @Override
public void configure() { public void configure() {

System.setProperty("file.encoding", "utf-8"); System.setProperty("file.encoding", "utf-8");


OptionalBinder.newOptionalBinder(binder(), ObjectMapper.class) // Lifecycle support
.setDefault().toProvider(ObjectMapperProvider.class) install(LifecycleSupport.getModule());
.in(Singleton.class);

// Scheduling support
OptionalBinder.newOptionalBinder(binder(), XmlMapper.class).setDefault() install(SchedulerSupport.getModule());
.toProvider(XmlMapperProvider.class).in(Singleton.class);

// Routing
bind(RouteBuilder.class).to(RouteBuilderImpl.class); bind(RouteBuilder.class).to(RouteBuilderImpl.class);

bind(Router.class).to(RouterImpl.class).in(Singleton.class); bind(Router.class).to(RouterImpl.class).in(Singleton.class);


// provide logging // Logging
bind(Logger.class).toProvider(LoggerProvider.class); bind(Logger.class).toProvider(LoggerProvider.class);


// Bind the configuration into Guice // Bind the configuration into Guice
ninjaProperties.bindProperties(binder()); ninjaProperties.bindProperties(binder());
bind(NinjaProperties.class).toInstance(ninjaProperties); bind(NinjaProperties.class).toInstance(ninjaProperties);

// Postoffice
bind(Postoffice.class).toProvider(PostofficeProvider.class);

// Cache
bind(Cache.class).toProvider(CacheProvider.class);

bind(MigrationInitializer.class).asEagerSingleton();
install(new JpaModule(ninjaProperties));

} }


} }

0 comments on commit 12c8806

Please sign in to comment.