-
-
Notifications
You must be signed in to change notification settings - Fork 750
Configuring Atmosphere's Classes Creation and Injection
Starting with Atmosphere 2.1+, it is possible to configure an AtmosphereObjectFactory for dependencies injection and class creation. You can define your own and pass it to the framework by defining an init-param:
<init-param>
<param-name>org.atmosphere.cpr.objectFactory</param-name>
<param-value> << an implementation of AtmosphereObjectFactory >> </param-value>
</init-param>
Starting with Atmosphere 2.3.0+ Atmosphere have basic support for injection. If you are using 2.3.2+, you can also defines under META-INF/services/org.atmosphere.inject.Injectable
classes that implements the Injectable interface so the AtmosphereObjectFactory can inject those objects into your classes.
You can also enable one of the following supported frameworks by just adding the artifact on you classpath.
For CDI, Atmosphere will use the following code for injecting/creating object:
public class CDIObjectFactory implements AtmosphereObjectFactory<Object> {
private static final Logger logger = LoggerFactory.getLogger(CDIObjectFactory.class);
private BeanManager bm;
public CDIObjectFactory(){
try {
bm = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
} catch (NamingException ex) {
try {
bm = (BeanManager) new InitialContext().lookup("java:comp/env/BeanManager");
} catch (NamingException e) {
logger.error("{}", e);
}
}
final Iterator<Bean<?>> i = bm.getBeans(AtmosphereProducers.class).iterator();
if (!i.hasNext()) {
throw new IllegalStateException();
}
}
@Override
@SuppressWarnings("unchecked")
public <T, U extends T> U newClassInstance(Class<T> classType, Class<U> classToInstantiate) throws InstantiationException, IllegalAccessException {
CreationalContext cc = null;
try {
final Iterator<Bean<?>> i = bm.getBeans(classToInstantiate).iterator();
if (!i.hasNext()) {
logger.trace("Unable to find {}. Creating the object directly.", classToInstantiate.getName());
return classToInstantiate.newInstance();
}
Bean<U> bean = (Bean<U>) i.next();
CreationalContext<U> ctx = bm.createCreationalContext(bean);
U dao = (U) bm.getReference(bean, classToInstantiate, ctx);
return dao;
} catch (Exception e) {
logger.error("Unable to construct {}. Creating the object directly.", classToInstantiate.getName());
return classToInstantiate.newInstance();
} finally {
if (cc != null) cc.release();
}
}
@Override
public AtmosphereObjectFactory allowInjectionOf(Object o) {
return this;
}
public String toString() {
return "CDI ObjectFactory";
}
@Override
public void configure(AtmosphereConfig config) {
try {
AtmosphereProducers p = newClassInstance(AtmosphereProducers.class,AtmosphereProducers.class);
p.configure(config);
} catch (Exception e) {
logger.error("", e);
}
}
}
You can install it by adding in your pom.xml:
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-cdi</artifactId>
<version>2.3.0+</version>
</dependency>
Atmosphere will auto-detect it and use it automatically.
For Spring, Atmosphere will use the following code for injecting/creating object:
public class SpringWebObjectFactory implements AtmosphereObjectFactory<Class<?>> {
/**
* A comma delimited list of {@link org.atmosphere.inject.InjectableObjectFactory.DEFAULT_ATMOSPHERE_INJECTABLE} that
* won't be created by Spring.
*/
public static final String ATMOSPHERE_SPRING_EXCLUDE_CLASSES = "org.atmosphere.spring.excludedClasses";
private static final Logger logger = LoggerFactory.getLogger(SpringWebObjectFactory.class);
protected boolean preventSpringInjection = false;
private final List<Class<?>> excludedFromInjection = new ArrayList<Class<?>>();
private AnnotationConfigApplicationContext context;
@Override
public <T, U extends T> U newClassInstance(Class<T> classType,
Class<U> classToInstantiate)
throws InstantiationException, IllegalAccessException {
if (preventSpringInjection && excludedFromInjection.contains(classType)) {
logger.trace("Excluded from injection {}", classToInstantiate.getName());
return classToInstantiate.newInstance();
}
String name = classToInstantiate.getSimpleName();
if (!context.containsBeanDefinition(Introspector.decapitalize(name))) {
context.register(classToInstantiate);
}
U t = context.getAutowireCapableBeanFactory().createBean(classToInstantiate);
if (t == null) {
logger.info("Unable to find {}. Creating the object directly."
+ classToInstantiate.getName());
return classToInstantiate.newInstance();
}
return t;
}
@Override
public AtmosphereObjectFactory allowInjectionOf(Class<?> aClass) {
context.register(aClass);
return this;
}
public String toString() {
return "Spring Web ObjectFactory";
}
@Override
public void configure(AtmosphereConfig config) {
try {
String s = config.getInitParameter(ATMOSPHERE_SPRING_EXCLUDE_CLASSES);
if (s != null) {
String[] list = s.split(",");
for (String clazz : list) {
excludedFromInjection.add(IOUtils.loadClass(getClass(), clazz));
}
if (list.length > 0) {
preventSpringInjection = true;
}
}
context = new AnnotationConfigApplicationContext();
context.setParent(WebApplicationContextUtils.getWebApplicationContext(config.framework().getServletContext()));
context.refresh();
// Hack to make it injectable
context.register(AtmosphereConfig.class);
context.getBean(AtmosphereConfig.class, config.framework()).populate(config);
} catch (Exception ex) {
logger.warn("Unable to configure injection", ex);
}
}
}
You can install it by adding in your pom.xml:
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-spring</artifactId>
<version>2.3.0+</version>
</dependency>
For Guice, Atmosphere will use the following code for injecting/creating object:
public class GuiceObjectFactory implements AtmosphereObjectFactory<AbstractModule> {
private static final Logger logger = LoggerFactory.getLogger(GuiceObjectFactory.class);
protected Injector injector;
protected AtmosphereConfig config;
private final List<AbstractModule> modules = new ArrayList<AbstractModule>();
@Override
public void configure(AtmosphereConfig config) {
if (config == null) {
throw new NullPointerException("AtmosphereConfig can't be null");
}
this.config = config;
modules.add(new AtmosphereModule());
try {
AtmosphereProducers p = newClassInstance(AtmosphereProducers.class, AtmosphereProducers.class);
p.configure(config);
} catch (Exception e) {
logger.error("", e);
}
}
@Override
public <T, U extends T> U newClassInstance(Class<T> classType, Class<U> classToInstantiate) throws InstantiationException, IllegalAccessException {
initInjector(config.framework());
U t;
if (injector != null) {
t = injector.getInstance(classToInstantiate);
} else {
logger.warn("No Guice Injector found in current ServletContext. Are you using {}?", AtmosphereGuiceServlet.class.getName());
logger.trace("Unable to find {}. Creating the object directly.", classToInstantiate.getName());
t = classToInstantiate.newInstance();
}
return t;
}
@Override
public String toString() {
return "Guice ObjectFactory";
}
protected void initInjector(AtmosphereFramework framework) {
if (injector == null) {
// start by trying to get an Injector instance from the servlet context
Injector existingInjector = (Injector) framework.getServletContext().getAttribute(Injector.class.getName());
AbstractModule[] a = modules.toArray(new AbstractModule[modules.size()]);
if (existingInjector != null) {
logger.trace("Adding AtmosphereModule to existing Guice injector");
injector = existingInjector.createChildInjector(a);
} else {
logger.trace("Creating the Guice injector manually with AtmosphereModule");
injector = Guice.createInjector(a);
}
}
}
@Override
public AtmosphereObjectFactory allowInjectionOf(AbstractModule module) {
modules.add(module);
return this;
}
private class AtmosphereModule extends AbstractModule {
@Override
protected void configure() {
bind(BroadcasterFactory.class).toProvider(new Provider<BroadcasterFactory>() {
@Override
public BroadcasterFactory get() {
return config.getBroadcasterFactory();
}
});
bind(AtmosphereFramework.class).toProvider(new Provider<AtmosphereFramework>() {
@Override
public AtmosphereFramework get() {
return config.framework();
}
});
bind(AtmosphereResourceFactory.class).toProvider(new Provider<AtmosphereResourceFactory>() {
@Override
public AtmosphereResourceFactory get() {
return config.resourcesFactory();
}
});
bind(MetaBroadcaster.class).toProvider(new Provider<MetaBroadcaster>() {
@Override
public MetaBroadcaster get() {
return config.metaBroadcaster();
}
});
bind(AtmosphereResourceSessionFactory.class).toProvider(new Provider<AtmosphereResourceSessionFactory>() {
@Override
public AtmosphereResourceSessionFactory get() {
return config.sessionFactory();
}
});
bind(AtmosphereConfig.class).toProvider(new Provider<AtmosphereConfig>() {
@Override
public AtmosphereConfig get() {
return config;
}
});
}
}
}
You can install it by adding in your pom.xml:
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-guice</artifactId>
<version>2.3.0+</version>
</dependency>
- Understanding Atmosphere
- Understanding @ManagedService
- Using javax.inject.Inject and javax.inject.PostConstruct annotation
- Understanding Atmosphere's Annotation
- Understanding AtmosphereResource
- Understanding AtmosphereHandler
- Understanding WebSocketHandler
- Understanding Broadcaster
- Understanding BroadcasterCache
- Understanding Meteor
- Understanding BroadcastFilter
- Understanding Atmosphere's Events Listeners
- Understanding AtmosphereInterceptor
- Configuring Atmosphere for Performance
- Understanding JavaScript functions
- Understanding AtmosphereResourceSession
- Improving Performance by using the PoolableBroadcasterFactory
- Using Atmosphere Jersey API
- Using Meteor API
- Using AtmosphereHandler API
- Using Socket.IO
- Using GWT
- Writing HTML5 Server-Sent Events
- Using STOMP protocol
- Streaming WebSocket messages
- Configuring Atmosphere's Classes Creation and Injection
- Using AtmosphereInterceptor to customize Atmosphere Framework
- Writing WebSocket sub protocol
- Configuring Atmosphere for the Cloud
- Injecting Atmosphere's Components in Jersey
- Sharing connection between Browser's windows and tabs
- Understanding AtmosphereResourceSession
- Manage installed services
- Server Side: javadoc API
- Server Side: atmosphere.xml and web.xml configuration
- Client Side: atmosphere.js API