Why does Quarkus warn me about injection in private fields? - quarkus

When I use something like the following in my Quarkus application:
#Path("v1")
#Produces(APPLICATION_JSON)
public class HelloWorldResource {
#Inject
private SomeBean someBean;
}
then I get a warning the following during the build process.
[INFO] [io.quarkus.arc.processor.BeanProcessor] Found unrecommended usage of private members (use package-private instead) in application beans:
- #Inject field acme.jaxrs.v1.HelloWorldResource#someBean
Everything seems to work just fine so why is Quarkus suggesting that change private to package-private?

If a property is package-private, Quarkus can inject it directly without requiring any reflection to come into play.
That is why Quarkus recommends package-private members for injection as it tries to avoid reflection as much as possible (the reason for this being that less reflection means better performance which is something Quarkus strives to achieve).
See section 2 of this guide for more details.

Related

How to make a bean discoverable by Quarkus CDI without using annotations

I have a simple Quarkus resource:
#Path("/rosters")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class RosterResource {
private final RosterService rosterService;
public RosterResource(RosterService rosterService){
this.rosterService = rosterService;
}
#GET
#Path("/{rosterId}")
public Response getRoster(#PathParam("rosterId")Long rosterId){
return Response.ok(rosterService.getRosterById(rosterId)).build();
}
}
I am trying to inject the RosterServiceinstance in my resource, but I am getting a javax.enterprise.inject.UnsatisfiedResolutionException. However, if I use the #ApplicationScoped annotation on RosterService, then everything works just fine. Is there a way of injecting the RosterService class in my resource without using annotations? In other words, is there a way of making RosterService discoverable by the Quarkus container without directly annotating the class?
Edit: looking into the CDI docs, it seems that you can manually register beans using a method with a #BuildStep annotation. However, it is not clear to me which class should contain the annotated method)
Another option would be to use a Jandex index
To the best of my knowledge, Quarkus only implements so called annotated bean discovery. That means that all CDI beans in Quarkus have to have a bean defining annotation. #ApplicationScoped is one of them.
EDIT: regarding a Jandex index, that allows you to scan for beans in additional JARs. In other words, it will only expand the set of classes that are scanned for a bean defining annotation.
When it comes to a #BuildStep method -- that is only possible in a Quarkus extension. Extensions are powerful (and indeed they can define additional beans) but also complex. You can start at https://quarkus.io/guides/building-my-first-extension, but it may feel overwhelming. It may also feel like this is not the right thing to do if you want to just make your class a bean -- and that would be true. But if your class comes from an external library that you can't change, extension makes sense.
Is there a specific reason why you don't want to annotate your service class with #ApplicationScoped (or any other of the bean discover/scope annotations)?
The only other way that I'm aware of (instead of annotations) is - as you yourself mentioned - the use of Jandex index.

IntelliJ can't find Spring bean from Kotlin object

I have a Spring Boot 2 + Kotlin application opened with IntelliJ 2019.1.
In this application I annotate some Kotlin objects with #Component. Example:
#Component
object MyObject: MyInterface {
// code
}
I have many different implementation of MyInterface (all with Kotlin objects) and I want to inject all of them in a list in another bean. Example:
#Component
class MyComponent #Autowired constructor(private val objects: List<MyInterface>) {
// code
}
The code runs correctly (the beans are inject in the list objects) but IntelliJ shows an error saying:
Could not autowire. No beans of '? extends MyInterface' or 'List<? extends MyInterface>' types found.
If I change 'object' to 'class' at 'MyObject', the error disappears.
My questions are:
Is it a problem with IntelliJ?
Is it not recommended to annotate Kotlin objects with #Component?
For information, as a possible workaround while the ticket created by Николай in this answer is not treated, I'm ignoring the error/warning only where I need with #Suppress("SpringJavaInjectionPointsAutowiringInspection"). Example:
#Suppress("SpringJavaInjectionPointsAutowiringInspection")
#Autowired
private lateinit var kotlinObjectBeans: List<MyInterface>
I hope it can help others that don't want to disable this check elsewhere.
I would recommend not to use kotlin objects with #Component or any other bean annotation.
There are two aspects and heaving a mix of them leads to lots of problems:
It might be several ApplicationContext instances in your application.
Kotlin object is related to a specific ClassLoader
It is a little bit strange to use Kotlin objects as #Component-s, because if your class knows that it will be used inside Spring-container you'll get more flexibility if you delegate to Spring the decision should this class be a singleton or not and all the other lifecycle management.
But practically I don't see any reason why it could be "not recommended" if you know what you are doing, and aware of probably bugs if your object become stateful.
So I think IDEA should support your case, and I've filled up a ticket IDEA-211826

How does spring know to use jackson for serialization even if i just added that dependency in maven, no more anything?

i just added jackson dependency in maven, no more anything and spring start to use it for marshalling without any additional code configuration, How does spring know to use jackson for serialization
short answer - if it's on the class path.
longer answer -
if you are using #EnableWebMvc it calls DelegatingWebMvcConfiguration which extends WebMvcConfigurationSupport which uses
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", WebMvcConfigurationSupport.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", WebMvcConfigurationSupport.class.getClassLoader());
to see if Jackson is in the class path. this boolean is used in various places including addDefaultHttpMessageConverters

What's the syntax for multiple dependency injection using Spring and Scala?

I'm creating a new application using Akka, Scala and Spring. However all the examples I found online show a single dependency being injected. Since the syntax is different from Java, could anyone tell me what'd it look like with multiple DI?
Spring 4 MVC with Scala
akka-scala-spring
Converting a Java Spring application to Scala
Example of single DI:
class HelloWorldController #Autowired() (nameService: Name) {
I would start by simply adding parameters to the autowired argument list:
class HelloWorldController #Autowired() (service1: Foo, service2: Bar)
Unfortunately, I haven't used Spring in Scala yet, but if #Autowired is anything like Google Guice's #Inject - and it looks pretty similar - then this should be all you need in your class file.

How to use spring to resolve dependencies of an object created manually?

I would like to know if it's possible to use Spring to resolve the dependencies of an object created manually in my program. Take a look at the following class:
public class TestClass {
private MyDependency md;
public TestClass() {
}
...
public void methodThaUsesMyDependency() {
...
md.someMethod();
...
}
}
This TestClass is not a spring bean, but needs MyDependency, that is a spring bean. Is there some way I can inject this dependency through Spring, even if I instantiate TestClass with a new operator inside my code?
Thanks
Edit: The method I'm describing in my original answer below is the general way to accomplish DI external of the container. For your specific need - testing - I agree with DJ's answer. It's much more appropriate to use Spring's test support, for example:
#Test
#ContextConfiguration(locations = { "classpath*:**/applicationContext.xml" })
public class MyTest extends AbstractTestNGSpringContextTests {
#Resource
private MyDependency md;
#Test
public void myTest() {
...
While the above example is a TestNG test, there is also Junit support explained in 8.3.7.2. Context management and caching.
General approach: Annotate your class with #Configurable and utilize AspectJ load-time or compile-time weaving. See 6.8.1 in the Spring documentation on AOP for more details.
You can then annotate your instance variables with #Resource or #Autowired. Though they accomplish the same goal of dependency injection, I recommend using #Resource since it's a Java standard rather than Spring-specific.
Lastly, remember to consider using the transient keyword (or #Transient for JPA) if you plan on serializing or persisting the objects in the future. Chances are you don't want to serialize references to your DI'd repository, service, or component beans.
See the autowire() method on the AutowireCapableBeanFactory class. If you use an ClasspathXmlApplicationContext, you can get the factory with getAutowireCapableBeanFactory()
To get the ApplicationContext, you would need to use a static singleton or other central repository, such as JNDI or a Servlet container. See DefaultLocatorFactory on how to get an instance of the ApplicationContext.
If what you need is for testing purposes, Spring has good support for the scenario that you described above.
Check out Spring Reference manual section on Testing

Resources