Weld and test-jar - java

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...

Related

Are Spring-Boot-Test #MockBeans supposed to qualify for #ConditionalOnBean conditions?

I have a java #Configuration class with a FOO #Bean annotated with #ConditionalOnBean(BAR.class). As I expect this bean to be or not provided by the importer project, it's not present anywhere in my project.
In my integration test, I mock Bar.class by means of #MockBeans. But for some reason Spring-Boot -debug tells me it did not found it so my conditional bean has not been loaded.
I'm almost sure this situation has worked properly in the past, but did I configure anything extra? I can't manage to make it work
P.S> I discovered that manually re-registering the #Bean in the same #Configuration as the conditional does not see it neither! Is there any known bug related to his?
Autoreply: The culprit in this case is
You need to be very careful about the order that bean definitions are
added as these conditions are evaluated based on what has been
processed so far. For this reason, we recommend only using
#ConditionalOnBean and #ConditionalOnMissingBean annotations on
auto-configuration classes (since these are guaranteed to load after
any user-defined beans definitions have been added).
P.S2> I realized Bar.class is an interface but I don't see why shouldn't it work as long as an implementation is present
P.S3> I found out that the MockitoTestExecutionListener is executed after the OnBeanCondition class. This seems my problem totally.
This and this explain why it is not possible:
https://github.com/spring-projects/spring-boot/issues/9624 and
https://gitter.im/spring-projects/spring-boot?at=59536ea74bcd78af56538629

Using interceptor bindings from a jar

I have been searching for a while, but I can't found any information on how to achieve in Java EE to define custom annotations (interceptor bindings) to be able to be used in multiple maven modules without declaring it in every package where I would like to use it. It's basic interceptor where implementation only prints something into console.
An example is like javax.ws.rs.Path where this annotation can be used on multiple locations and everything what it needs to do is to import correct dependency. I cannot achieve same affect with my annotation.
I have created new maven module with the interceptor and binding annotation. I also have beans.xml file in META-INF folder to enable CDI. Then I add dependency of this module to other project, where I want to use this annotation. Problem is, that when I want to use this annotations, the implementation of annotation does not execute method which is annotated with #AroundInvoke annotation.
I don't know what I'm doing wrong, because weld should start initializing bean implementation because CDI is enabled, but he don't, unless I put extra configuration for <interceptor> in beans.xml file where I want to use annotation.
Assuming by package you mean module;
You need to declare your annotation in its own maven module (possibly with other shared logic). Then pull in that maven module as a dependency in your other modules. That way you can use the annotation wherever you want.

CDI : #alternative vs #Qualifiers

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.

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.

Categories

Resources