If you can't read please download the document
Upload
code-house
View
2.787
Download
0
Embed Size (px)
Citation preview
ApacheCon Europe 2012 Presentation Template - 1
When Camel meets CDI
ukasz Dywicki
Welcome everyone on talk When Camel meets CDI. On slide you see that word when" is stroke. It was removed because Camel already met CDI. :) Now we can share our experiences with you.
Goals
Determine state of DI support in Camel
Possible extension points to use
Transition from Spring to CDI
Show running CDI + Camel application
For this talk I have few goals. As this talk is latest in Camel in Action track you might get some points which was pointed by other presenters. First of all, I would like to determine state of Dependency Injection in Camel. It is ready for other than regular DI containers or not?We will point also possible extension points which are already present in Camel. This point might be really useful for people involved in other projects. You will see how to prepare hooks inside your projects to let developers use preferred DI container.Finally I will show you how transition from Spring to CDI looks like.But before we will go there, please let me introduce myself.
Who am I?
ukasz DywickiIndependent software contractor
ServiceMix user since 2008
Commiter of Apache Karaf
Camel contributor
My name is Lukasz Dywicki. I was born in Poland in 1985. I am independent software contractor since 2008 and I worked since then with number of companies.My main area of interest is middleware stuff from Apache. I realized in 2008 that there is lots of possibilities to help community and earn some cash.After almost two years I became Apache Karaf commiter. So you can be sure that I am not regular Java EE fan. My natural ground is OSGi.I am also contributor in Apache Camel. I am not yet commiter, however I walk around this project since I started using ServiceMix.
Camel + Red Hat
Before you will start thinking what this guy does here? He is not even Camel commiter!I would like to say that CDI extension in Camel is partially done by me and I support it as part of my work for Red Hat.
Brief introduction CDI, JSR-299
CDI is something fresh I believe. On this ApacheCon edition this is third talk about this spec. CDI was done as specification under Java Community Process.
Brief introduction CDI
Built on top of JSR-330
Package javax.inject@Inject
@Named
@Qualifier
@Scope
@Singleton
Provider
CDI as specification is assigned to Java EE, however it don't have to run on EE server. Most popular existing containers supports standalone mode. In other words you can run CDI inside swing application without fear.All injecting stuff is really built on top of JSR330. In fact this spec was standardization of annotations used by Guice and Spring.The JSR330 is limited to only few annotations and only one interface. However it's great basement for doing something more.
Brief introduction CDI cont.
On this slide you can see simplest CDI usage on servlet level. From developer point of view most important thing is fact, that there is no need to add anything more.No need to define bean in XML.No need to create any delegator beans or register proxy filter/servlet/listener or whatever.It just works. CDI in this moment became the missing glue. But let's go further.
Brief introduction CDI cont.
CDI contains more elements specific to full featured DI containerStereotypes
Application/Session/Request Scope
Bean Registry*
Possibility to implement own scopes
It's type safe by definition
Handles dependent beans creation
Lifecycle management with JSR-250
CDI compared to JSR330 is like big brother. It contains much more features, starting from stereotypes trough scopes, decorators, interceptors up to bean registry.As in other popular dependency containers developers can decide to implement new scope if necessary. It doesn't happen often, but for these who would like there is ready to use API to register it.Next thing, these days a term 'type safe' became very popular. I think it might be another buzz word. ;) So what's the type safety in case of CDI means? That you don't have to rely on bean names. You can use interface and qualifiers to choose interesting implementation.Typically if you have dependencies, container should manage creation of them and CDI does that. Also lifecycle management is done by container for you. Just put @PostConstruct or @PreDestroy annotations on method.
Brief introduction CDI cont.
Discovery of beans rely on presence of beans.xml file in META-INF or WEB-INF
Container discovers beans automatically
CDI is extensibleExtension interface
META-INF/services entry
Going further with DI stuff we can start seeing differences to existing containers CDI discovers beans by default. You don't have to name them or even annotate. To be honest, in 90% that's the case.The beans.xml file located in META-INF for JARs and in WEB-INF for WARs is a marker file. By default CDI container will not scan classpath entries without this file.The extension mechanism is standard, it requires additional entry in META-INF/services and implementation of given interface.
Support for Dependency Injection in Camel
After this short introduction we can determine state of support for Dependency Injection in Camel.
Support for DI in Camel
XML basedSpring
Blueprint
Annotation basedGuice
Spring JavaConfig
We can divide dependency containers into two categories. XML based or not. Of curse you can use Spring without defining beans in XML, however you still need some switches to be turned on inside application context.Blueprint is totally based on XML, it's OSGi specific standard which grown on top of Spring Dynamic Modules.On second hand we have annotation based stuff. Here we have Guice and Spring JavaConfig.
Support for DI in Camel
XML basedSpring
Blueprint
Annotation basedGuice
Spring JavaConfig
CDI
And CDI. Bigger brother of Guice.
Some pictures for fun
Ok, we spent some time on serious things. Now time to relax a bit!
Back to Camel
Ok, we spent some time on serious things. Now time to relax a bit!
Support for DI in Camel cont.
Registry
Injector
Two core parts of Camel which allows to port it across different Dependency Injection containers are Registry and Injector.
Registry
Let's take a look on Registry interface. It solves problem with portability of Dependency Injection containers. We can look up beans by name.First method returns an object, second lookup operation allows to set expected bean type.Third is designed to do lookups using only type. It returns Map where key is bean name and value is bean instance.
Core Registries
CompositeRegistry
SimpleRegistry
JndiRegistry
PropertyPlaceholderDelegateRegistry
Camel core ships with following registries.First is for wrapping multiple instances into one.Second is simple map and allows to put object instances to registry without any problems.The JndiRegistry allows to lookup beans using naming context.Latest is most tricky. You might not be aware of, but it's used all the time by Camel. It's doesn't meter if you use properties or not default camel context will always wrap registry set by you into PropertyPlaceholderDelegateRegistry.
3rd Party Registries
ApplicationContextRegistry
BlueprintContainerRegistry
OsgiServiceRegistry
CdiBeanRegistry
This slide lists registries provided by modules other than core.First comes with camel-spring, second with camel-blueprint.Third is provided by camel-core-osgi.Latest is developed uner camel-cdi module.What is important here there is no registry provided by Guice. Because construction of Guice there is no possibility to implement something similar to registry. It provides only Injector.
Injector
Injector is second tool which lets integrate Dependency Injection containers with Camel.It allows to obtain bean instance using type name only. I know it looks similar to Registry but both are used in different situation. Injector in many cases is used when lookup in Registry fails but given instance of bean is necessary to run.For example if lookup of component in Registry fails Camel tries to resolve type of Component and then use Injector to create instance of given type.
Core Injectors
ReflectionInjector
DefaultInjector
Reflection injector simply creates instance of given class using Reflection API.DefaultInjector populates fields annotated with Camel annotations like Produce or EndpointInject using a magic class called DefaultCamelBeanPostProcessor.
To be honest DefaultInjector duplicates work which could be possibly done by Dependency Injection container itself. However Spring API do not have good annotation processing API to stick with. That's
3rd party injectors
SpringInjector
GuiceInjector
CdiInjector
These injectors are in place by default. Mostly used is Spring, then we have Guice and new one CDI.
Transition from Spring to CDI
Now, after we saw integration points with DI containers, we can start talking about transition from Spring. How it looks like in Camel case.
Transition from Spring to CDI
No ApplicationContext instanceHow do I get bean from it?
No pre/post processorsCamelContextAware
Multiple camel contextsLinking beans with camel contexts
No domain specific namespaces
There are key differences between Spring and CDI.First of all we don't have something like ApplicationContext.There is no pre or post processors and you can not easily do a CamelContextAware stuff.Next things is problems with multiple instances of contexts in CDI you usually have one instance of given bean.When you have multiple beans you need to link it's dependencies in right way. That's why it becomes more complicated.And finally there is no domain specific namespaces. There is no need for them because there is no XML.
How do I get bean
Use Apache DeltaSpike BeanProvider class:getContextualReference(String) = Object
getContextualReference(Class) = T
getBeanDefinition(Class) = Set
getContextualReferences(Class) = List
Obtain bean instance from CDI requires few lines more than Spring. In spring you just could call applicationContext getBean method and that was all. In CDI you need to obtain reference first and then use this reference to ask for instance of bean.To avoid code duplication in camel-cdi we simply use deltaspike.
CamelContextAware
As I said there is no pre/post bean processors in case of CDI. But the good thing is that we could catch events.If we would like to change bean definition we can catch ProcessAnnotatedType event and modify bean definition. This code add @Inject to method setCamelContext using deltaspike AnnotatedTypeBuilder.
Events
BeforeBeanDiscovery
AfterBeanDisovery
ProcessBean
ProcessInjectionTarget
ProcessObserverMethod
AfterDeploymentValidation
BeforeShutdown
Linking beans
For linking route builder together with camel context we use @ContextName annotation.It's just a marker which allows extension link routes written by user with context instances to create.
Demo application
Common problems
Problems ...
Domination of Spring style DI
Multiple contexts vs simplicity of extension
Magic done inside Camel
Configuring Camel Context bean
TODO
Support for discoveringIntercept Strategies
Event Notifiers
Executors
Resolvers
Transactional services without spring-tx
Any questions?
Thank you for coming!