Quarkus / CDI and "java config" DI definitions - cdi

I just started a quarkus proof of concept. The containers-start time is amazing!
Right now, I'm working on the Dependency Injection part. And figuring out the options.
https://quarkus.io/blog/quarkus-dependency-injection/
My preferences are:
I prefer constructor injection. (This has been going ok).
I prefer "java config" so I can follow the "Composition Root" pattern of putting all my application dependency injections in a common place. (See https://blog.ploeh.dk/2011/07/28/CompositionRoot/ )
With Spring DI, this is done with the
org.springframework.context.annotation.Configuration
and declaring the Beans there.
Aka, I prefer not to place "#ApplicationScoped" annotations all over my classes.
Does CDI/Quarkus support a "java config" model? The reason I ask about quarkus is that I read quarkus has a limited CDI implementation.
//start quote//Our primary goal was to implement a supersonic
build-time oriented DI solution compatible with CDI. This would allow
users to continue using CDI in their applications but also leverage
Quarkus build-time optimizations. However, ArC is not a full CDI
implementation verified by the TCK - see also the list of supported
features and the list of limitations.//end quote
So my question isn't a solely CDI question.
I've tried different internet search terms, but they keep showing me Spring links. :(

You should create a CDI bean that will produce your beans, this is the standard CDI approach to what Spring calls Java Configuration.
So something like this
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
#ApplicationScoped
public class MyConfiguration {
#Produces
public MyBean myBean(){
return new MyBean();
}
}

Related

Quarkus - CDI bean tree/graph

I was wondering if there was a way using Quarkus to see how beans are being pulled in. Like a tree or graph showing the hierarchy of bean resolution. I have a few beans that I think should be considered "unused", but they are still pulled in (I know because they fail with missing config properties).
That's an interesting idea. Would you care to file a new issue here: https://github.com/quarkusio/quarkus/issues?
By the way, "unremovable" beans do not need to be injected anywhere. There are other rules that apply. For example, a #Named bean or a bean that declares an observer method is never removed. Furthermore, Quarkus extensions can add their own rules.
Added enhancement issue to github: https://github.com/quarkusio/quarkus/issues/26065
PR: https://github.com/quarkusio/quarkus/pull/26153
Will be built to 2.11

What is the search scope of CDI in case of injectable bean lookup?

I have a multi module maven project (a Java EE app with ear, persistence, web, ejb, api, bl and other modules), where I'd like to use Weld CDI.
When I try to inject a bean, where will Weld search for injectable beans? Will Weld search in all the modules, where a beans.xml is placed to WEB-INF or META-INF regardless from their dependencies (or dependencies matter somehow?), or will Weld be able to inject a bean from an other deployment? I tried to find a document, which describes the mechanism and boundaries of bean lookup, but I haven't found anything yet.
What you're describing is part of the overall EE spec, not the CDI spec. but yes, in general the contents of your EAR will be discovered as distinct applications (per the EE spec). This means that you may not be able to access individual beans across JARs. It is highly recommended to use WAR deployment with CDI.

Is #DeclareRoles limited to Java Servlet classes?

I'm trying to get a clear understanding of where #DeclareRoles annotation can be used. The API simply says:
Used by application to declare roles. It can be specified on a class.
I've used #DeclareRoles successfully with GlassFish and Payara and for them I can put #DeclareRoles anywhere; it seems those EE servers will scan and find all usages. I tried transferring some code to WebLogic 12.2.1 and started getting some role errors at deployment. I tracked the problem down to WebLogic wanting the #DeclareRoles annotation only on a Servlet class.
So should #DeclareRoles be able to put on any class and the GlassFish/Payara behavior is correct? Or should #DeclareRoles be limited only to a Servlet class and the WebLogic behavior is correct. Given WebLogic's history, I tend to think it's not doing the right thing.
After looking into this more, I found JSR-340, Servlet 3.1 specification, section 15.5.1 AND JSR-369, Servlet 4.0 specification, section 15.2.2 both state:
The #DeclareRoles annotation may only be defined in classes
implementing the javax.servlet.Servlet interface or a subclass
thereof.
So, it looks like WebLogic got this right and GlassFish/Payara behavior is outside of the spec.
According to the Java EE 7.0 & 8.0 Specifications, javax.annotation.security.DeclareRoles need only be supported by web containers and EJB containers.
In other words, the class that is annotated must be an EJB or a servlet.

CDI interceptor injected into a jersey RS service(resource) not working?

So, I have a tomcat 8 + jersey 2.5.1 + weld CDI app that works very well in most cases. Where it fails is that I am unable to intercept jersey resource method calls with a CDI interceptor. This makes sense because a jersey resource class is not a CDI bean. Then, is there any way to make a CDI interceptor work in jersey? Another way to ask this question: Can a CDI bean be used as a Jersey resource?
Thanks!
EDIT:
Before I wrote my RESTful resources using Jersey, I had CDI interceptors that were used to begin and commit database transactions. I really need to follow the same or similar pattern to implement this cross-cutting transaction injection in my RESTful jersey resources. That is the main reason for asking this question.
Thanks again!
Can a CDI bean be used as a Jersey resource?
Yes, but since Jersey's DI is based on hk2 and not CDI, you need a bridge.
In glassfish such a bridge is realized by the module jersey-gf-cdi:
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.6</version>
</dependency>
The module registers itself automatically and works on Tomcat beautifully (assuming you have correctly bootstrapped both Jersey and Weld).
Unfortunately, the versions before 2.6 relies on JNDI only, searching the provider under 'java:comp/BeanManager' which Tomcat does not allow.
A fix for this behaviour is available for 2.6 (a pull request I made some time ago), and falls back on CDI.current().getBeanManager().
I tested it on Tomcat 7 and works correctly, should work on Tomcat 8 too.
Adam Bien in one presentation recommends that you separate your Service (CDI or EJB) class from your RESTful resources class. His reason was that the RESTful class usually uses the HttpHeaders injected by Jersey yet not available in the CDI or EJB containers. The hazard is that your RESTful classes could be injected a Null reference of HttpHeaders if any CDI client like the JSF framework uses it.
Thanks to your self-answered question. You have just showed a second use case that validates Adam Bien's recommendation.
Simply keep them apart!

Calling #EJB from JSF Managed Bean

We are using JDeveloper 11g.
Both a Model and ViewController project that makes use of ADF fusion and what not.
My web-xml has an EJB reference for a stateful session EJB .
I have a managed bean that's declared in faces-config.
I am trying to access a EJB from inside the managed bean.
I declare
#EJB (name ="LocationServicesEJB")
private LocationServicesEJB locationServices;
When accessing this in a method, the locationServices is null.
I do not see any JNDI type problems in the console,
so I imagine that it's not even bothering to lookup.
Do I need to enable injection or something?
Or do I need to define 'locationServices' as managed property in my faces-config?
Please advise.
Thanx
You are confusing two different types of injection.
There is EJB injection that happens among EJBs by the respective annotation. This type is handled by the EJB container (your application server or OpenEJB e.t.c)
Then there is "normal" injection (ala Spring) that happens between normal Java beans
and is defined in faces-config. This type is handled by JSF.
So decide what you want to do.
My proposal would be to download the official Java EE tutorial and skim through all topics.

Resources