Skip to content

Configuring Atmosphere's Classes Creation and Injection

jfarcand edited this page Sep 4, 2014 · 2 revisions

Custom Object 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>

Built In Framework Support

By default, Atmosphere doesn't support Injection, but you can enable one of the following supported frameworks by just adding the artifact on you classpath.

Using Contexts and Dependency Injection (CDI)

For CDI, Atmosphere will use the following code for injecting/creating object:

public class CDIObjectFactory implements AtmosphereObjectFactory {
    @Override
    @SuppressWarnings("unchecked")
    public <T> T newClassInstance(AtmosphereFramework framework, Class<T> classToInstantiate) throws InstantiationException, IllegalAccessException {
        CreationalContext cc = null;

        final BeanManager bm;
        try {
            bm = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
            final Iterator<Bean<?>> i = bm.getBeans(classToInstantiate).iterator();
            if (!i.hasNext()) {
                return classToInstantiate.newInstance();
            }
            Bean<T> bean = (Bean<T>) i.next();
            CreationalContext<T> ctx = bm.createCreationalContext(bean);
            T dao = (T) bm.getReference(bean, classToInstantiate, ctx);
            return dao;
        } catch (Exception e) {
            // Log ME. Fallback to normal.
            return classToInstantiate.newInstance();
        } finally {
            if (cc != null) cc.release();
        }
    }
}

You can install it by adding in your pom.xml:

 <dependency>
    <groupId>org.atmosphere</groupId>
    <artifactId>atmosphere-cdi</artifactId>
    <version>2.1.0+</version>
</dependency>

Atmosphere will auto-detect it and use it automatically.

Using Spring

For Spring, Atmosphere will use the following code for injecting/creating object:

public class SpringWebObjectFactory implements AtmosphereObjectFactory {
	
	private static final Logger logger = LoggerFactory.getLogger(SpringObjectFactory.class);

	@Override
	public <T, U extends T> U newClassInstance(AtmosphereFramework framework,
			Class<T> classType, Class<U> classToInstantiate)
			throws InstantiationException, IllegalAccessException {
		WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(framework.getServletContext());
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
	    context.setParent(parent);
	    context.register(classToInstantiate);
	    context.refresh();
		U t = context.getBean(classToInstantiate);
		if (t == null) {
			logger.info("Unable to find {}. Creating the object directly."
					+ classToInstantiate.getName());
			return classToInstantiate.newInstance();
		}
		return t;
	}

	public String toString() {
		return "Spring Web ObjectFactory";
	}

}

You can install it by adding in your pom.xml:

 <dependency>
    <groupId>org.atmosphere</groupId>
    <artifactId>atmosphere-spring</artifactId>
    <version>2.1.0+</version>
</dependency>

Using Guice

For Guice, Atmosphere will use the following code for injecting/creating object:

public class GuiceObjectFactory implements AtmosphereObjectFactory {
    private static final Logger logger = LoggerFactory.getLogger(GuiceObjectFactory.class);
    private static Injector injector;
    static {
        injector = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
            }
        });
    }

    @Override
    public <T> T newClassInstance(AtmosphereFramework framework, Class<T> classToInstantiate) throws InstantiationException, IllegalAccessException {
        com.google.inject.Injector servletInjector = (com.google.inject.Injector)
                framework.getServletContext().getAttribute(com.google.inject.Injector.class.getName());

        if (servletInjector != null) {
            injector = servletInjector;
        }

        if (injector == null) {
            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());
            return classToInstantiate.newInstance();
        }
        return injector.getInstance(classToInstantiate);
    }
}

You can install it by adding in your pom.xml:

 <dependency>
    <groupId>org.atmosphere</groupId>
    <artifactId>atmosphere-guice</artifactId>
    <version>2.1.0+</version>
</dependency>

As simple as

The example below demonstrate how you can inject custom object with your @ManagedService class. The Chat class is taken from the famous Atmosphere's Chat

@ManagedService(path = "/chat")
public class Chat {
    private final Logger logger = LoggerFactory.getLogger(Chat.class);

    // Simple example
    @Inject
    public Service service;

    /**
     * Invoked when the connection as been fully established and suspended, e.g ready for receiving messages.
     *
     * @param r
     */
    @Ready
    public void onReady(final AtmosphereResource r) {
        logger.info("Browser {} connected.", r.uuid());
        logger.info("{}", service.doSomething());
    }

    /**
     * Invoked when the client disconnect or when an unexpected closing of the underlying connection happens.
     *
     * @param event
     */
    @Disconnect
    public void onDisconnect(AtmosphereResourceEvent event) {
        if (event.isCancelled()) {
            logger.info("Browser {} unexpectedly disconnected", event.getResource().uuid());
        } else if (event.isClosedByClient()) {
            logger.info("Browser {} closed the connection", event.getResource().uuid());
        }
    }

    /**
     * Simple annotated class that demonstrate how {@link org.atmosphere.config.managed.Encoder} and {@link org.atmosphere.config.managed.Decoder
     * can be used.
     *
     * @param message an instance of {@link Message}
     * @return
     * @throws IOException
     */
    @org.atmosphere.config.service.Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class})
    public Message onMessage(Message message) throws IOException {
        logger.info("{} just send {}", message.getAuthor(), message.getMessage());
        return message;
    }


    public final static class Service {

        public String doSomething() {
            return "Injected and Happy";
        }

    }
}

Step by Step Tutorials

Concepts & Architecture

15 Minutes Tutorial

Advanced Topics

API

Known WebServer Issues

References

External Documentations

githalytics.com alpha

Clone this wiki locally