CDI : #alternative vs #Qualifiers - java

being new to CDI, i want to know the practical difference between an alternative and a
Qualifier.
in Weld reference, it's stated that:
4.3. Qualifier annotations
If we have more than one bean that implements a particular bean type,
the injection point can specify exactly which bean should be injected
using a qualifier annotation.
but while explaining the Alternatives, it is said:
4.7. Alternatives
Alternatives are beans whose implementation is specific to a
particular client module or deployment scenario.
If I understood right, #Qualifier defines which implementations of the target bean get injected to the Injection Points.
on the other hand #Alternative describes a wish during deployment dependending on the client about whether or not an Alternatice to the standard (the "#default" I mean ) bean get Injected to the injection's point.
It is right ?

Yes, that's right. You can imagine qualifiers as the basic weaving that you setup at development time, using annotations in your source code.
Alternatives allow you to overwrite this at execution time using the beans.xml file - a simple deployment artifact.
A typical scenario would be to use different beans.xml for different environments and thereby enable mock-alternatives for components that you don't want to execute on your local / integration environments.

Related

Weld and test-jar

We have a maven multi-module project with the following modules:
prj-srv
prj-client
The srv project contains EJBs. In prj-srv/src/test, we have #Alternative implementations of the EJBs, specified in the alternatives section of beans.xml. This works.
The project prj-client has prj-srv as a dependency. In addition, it has a dependency on prj-srv of type test-jar, scope test, so that it can use the alternative EJB implementations for tests. This works, too.
Now then: in prj-client/src/main/java, we have local implementations of the EJB interfaces (so that we can cache the data) annotated with our qualifier #Cacheable. What I would like to do, is setup the tests in prj-client/src/test/java so that they use my test implementations from prj-srv (the ones that aren't cacheable, but who cares since it's for testing).
I have tried:
Creating a class with producer methods (#Produces #Alternative #Cacheable) in prj-client/src/test/java, but I don't know how to configure beans.xml to set this up as the alternative
Creating classes in prj-srv/src/test/java that extend the test EJBs, annotated #Alternative #Cacheable, and put them in src/test/resources/META-INF/beans.xml in the alternatives section, but weld still injects the "real" #Cacheable beans from src/main/java.
Is there some problem mixing #Alternative with qualifiers? How can I get my tests to use alternate implementations of a qualified class?
Just found it: I had forgotten to mark the constructors of the #Cacheable implementations with #Inject. Apparently, even though it was marked as an alternative in beans.xml, since Weld didn't know how to initialize it, instead of throwing an error, it just silently decided to ignore the alternative...

CDI: Injecting resources to beans from external libraries

In Spring we have annotation-based and XML-based configuration. While the first is recommended for quick development, the second is more flexible and able to handle special cases. By us there are currently 2: injecting mocks for JUnit tests and configuring beans from external libraries.
I haven't found any equivalent for XML configuration for CDI, so my question is, how to handle dependency injection for such beans? They are from external libraries, they need to be configured and there's no possibility to add any annotations to them.
You have three solutions to your need:
Use a producer
CDI provides a way to transform non CDI class in beans. It is called a producer. If you want to create a bean from a class named NonCdiClass You only have to create something like that
public class MyProducers {
#Produces
public NonCdiClass produceNonCdiClass() {
return new NonCdiClass();
};
}
}
You can now #Inject this bean when needed.
You can put as many producer method as you want in your class.
If you need to simulate injection in your produced bean you can do it thanks to CDI that injects parameters in producer methods calls.
#Produces
public NonCdiClass produceNonCdiClass(MyFisrtBean param1, MySecondBean param2) {
NonCdiClass res = new NonCdiClass(param1);
res.setParam(param2);
return res;
};
}
In this example MyFirstBean and MySecondBean are existing bean classes that will be injected by CDI at producing time.
Producers can also have Qualifiers (on them or on their parameters) or inject the InjectionPoint which is a CDI internal bean allowing you to produce your bean differently in function of where is the injection and what annotation it has.
You have a nice InjectionPoint example in Weld reference documentation.
Develop an extension
I won't go into much details here since I don't know if it's your need, but you can register bean in an extension in the AfterBeanValidation phase. These registered beans can be of any class you want.
Should you need more info I could develop here.
Use Seam Solder (legacy) or wait for Deltaspike 0.6
Solder integrated a config module but this project is no more maintained since it's been in the process to be merged in Apache Deltaspike. This merge is in Deltaspike roadmap for version 0.6: http://issues.apache.org/jira/browse/DELTASPIKE-271. So you could start using Solder config and switch to Deltaspike when it'll have the feature (which should be quite close).
This solution is not my favorite but if you really want to have a config file à la Spring, it's the closest solution
Pure CDI provides the #Alternative annotation to inject for example mock objects during testing phase via beans.xml, but many mock libraries do a better work since they're designed for it.
I'm not aware of a way to use beans.xml to inject anything outside of the ear/war itself.

Resolve EJB Dependencies without a container

I am currently working on a solution for testing EJB 3 Services with JUnit.
(Yes, I have looked at ejb3unit but it doesn't work for me. Yes, I have looked at container-integrated testing with openEJB but that didn't work out neither..)
So my question is what would be the way for resolving #EJB annotated Dependencies? And I don't mean by using a DI Framework like Weld, Guice or Spring. The solution should be applicable for plain old JUnit Tests -> without using an EJB Container like JBoss, Glassfish or openEJB.
I was able to replace the injection of the entity manager via #PersistenceContext with a little hack using java reflections. So how would I do that for dependencies with #EJB annotation?
(I wouldn't mind building and resolving the dependency tree myself, just looking for ideas ;) )
Greetings from Germany,
p.s.
Not sure why you're against the solution you proposed.
I was about to offer stuff like Arquillian, but hey - you don't want to have a container involved.
I just want to be sure about the reason you don't want container, before I move on to some ideas (though I did not test them) -
With JBoss AS 7.x deployment time of enterprise application servers was vastly reduced,
Not to mention that with Arquillian you have a deployment API, and you can decide what you will deploy (i.e - deploy for example just a single bean for a given test).
However, I do respect you question, so here are some ideas -
A. You mentioned you managed to inject an EntityManager using reflection - how did you do that? Why not apply the same to your beans?
B. If you're encountering problems with A, why not develop your own injection code , based on cglib , for example (in order to create Proxy not just for interface, but also for classes).
This way, when an object of the class is created,
you will be able to intercept the default CTOR, and scan for fields annotated with #Ejb.
I would suggest using some sort of configuration file that maps for each bean interface how to instantiate an appropriate class, and run this flow recurisevely (as the injected bean might have a field with #EJB annotation as well).
Pay attention that if you decide to use this method of work, you'll be implementing some sort of "mini dependnecy injection framework" - besides the fact that personally I would be interested in seeing your code ( :) ) I think you should carefully think why you don't want to use an "already made solution.
Note regarding the Arquillian suggestions, that still requires an EJB Container like JBoss, GlassFish, or OpenEJB.
If the problem is just finding and including all the dependencies, try this jar that includes all the required dependencies for EJB Lite:
http://repo1.maven.org/maven2/org/apache/openejb/openejb-lite/4.0.0/openejb-lite-4.0.0.jar
Include that in your test classpath (no other jars needed) then just boot the embedded container:
EJBContainer container = EJBContainer.createEJBContainer();
MyBean bean = (MyBean) container.getContext().lookup("java:global/myModleName/MyBean");
Working example here
Have you look at Arquillian?
You can find all the documentation on the project page: http://www.jboss.org/arquillian.html

Spring annotations conflicts with my design guidelines

Overview
Using
Spring 3.0.1 (annotation configuration)
Current configuration is using CGLib as proxy creator but this is not my preference
Transactions are annotation configured without any special settings
All configuration is done with annotations (#Service, #Transactional, #ManagedResource, #Inject, etc.)
Hibernate 3.5 (entities are annotated with javax.persistence)
Guidelines highlights
Every bean annotated with #Repository or #Service must have an interface
Constructor DI (when re-configuration isn't required)
Constructor has default visibility (Foo(Bar bar) {...})
Bean fields are final (when re-configuration isn't required)
Leads to no default constructor
Implementations are default visible with final modifier (final class Foo)
The Problem
CGLib can't proxy final classes
CGLib requires default (empty) constructor
Some services are required to be exposed via JMX
MBean exporter can't work unless proxied by CGLib
Some #Transactional #Services are accessed via facade service which requires more than one service to include in the facade transaction (e.g. Observer service over 2 application components)
Some interfaces have more than one implementation (which currently distinguished by #Qualifier)
Future guideline (or nice to have feature) - each application module will have beanRefContext.xml file to configure its internal application context
When I used to work with XML configuration I was able to enforce all the guidelines I presented above, but when switching to annotations it seems like Spring is misbehaving.
Developers in my group prefer annotation configuration (I seems easier to wire and write new code), but I've noticed all kind of "hacks" they introduce to the code to prevent from dealing with Spring application context failures.
The Question(s)
Are there best practices I should follow when using annotation configuration?
When using more than one implementation per interface (trying to reduce the use of #Primary or #Qualifier)
When using #Transactional
When using #ManagedResource
When using a combination of the above
Is there a way of stop working with CGLib, keep the annotation configuration and still be able to export my MBeans with annotations?
What is the suitable implementation for keeping most (preferably, all) of my guidelines?
I came up with the following solution (to questions #2 and #3) to be able to enforce my design guidelines and keep using annotation based configuration:
Each dependent project (Maven module) has it's own ApplicationContext
Every dependent project application context is defined in beanRefContext.xml
These application contexts are loaded in hierarchy using Spring context hierarchy mechanism.
This step is actually not fully supported by Spring and requires additional work
Since my application is layered, I could disable CGLib on all my modules besides the JMX layer (I can live with it :-) ).
The above steps also enabled me to reduce the execution time of Spring aware tests (every module loaded only a sub-set of beans).
As a practical guideline (for question #1), if an interface has more than one implementation, I place #Primary on the widely used one and other clients, requiring another implementation, wire the bean using #Qualifier.
Answer to point 2)
You could use AspectJ instead of CGLib.

How to choose between methods of acquiring dependencies?

I've seen at least three ways of acquiring dependencies in a Java object without coupling the object to the creation of the dependency;
Dependency Injection
- some framework injects a required object into another object based on an external configuration, example: Spring managed beans
Dependency Lookup
- a class looks up a required dependency in some kind of directory service, example: JNDI lookups in a Java EE container
Static Factories
- an object in a global scope provides instances on demand - the standard Java SE APIs seem to be littered with these, example: java.util.Logger.getLogger(name), java.util.Calendar.getInstance()
What guidance can you provide as to which is most appropriate for a situation?
I prefer dependency injection, because the object need not know how it acquires the references it needs.
Dependency lookup still requires the object to know about the lookup service and its URL.
Static factories are similar to lookup services.
I prefer dependency injection.
When I talk about DI with Spring Framework I see following
It's supported by IDEs (error check, visualization).
You can setup other needed stuff like AOP, properties loading, ...
You have big config possibilities - XML, annotation, JavaConfig
Can be use also in desktop application.
These outbalance every negatives like dependency on another library. Why should I use another approach?
This really depends on the context. If you are writing a self-contained Maths API you might want to use static factories because the code will be less verbose, setup-free and maybe more efficient. If you need to access/provide a remote dependency, a JNDI/LDAP lookup, or ESB messaging would work well. For injecting your services/DAO's/datasources into your typical enterprise server code you'd be better off using one of the common D.I. frameworks like Google Guice or Spring.
There is no single 'best' solution in software design; it's always a tradeoff.

Categories

Resources