I have a library in which I defined a class let's say MyClass with #Component along with #Value but when I try to use this in my Spring Boot application and try to Autowire it, I get exception about Spring not being able to find this type and ask me to define a Bean. All other classes gets injected just fine that I have defined in the application it self.
How can I make the MyClass to be injected?
Without a complete information on about your library, how you are using it, we can't provide solution. Assuming everything on your library is correct, you can simply add #ComponentScan on the application that use your library.
Create a class as below and that should fix your problem.
#Configuration
#ComponentScan({"your library package"})
public class YourConfig {
}
If this doesn't solve your problem, add more information on your question and I will update my answer accordingly.
Related
Whenever spring boot application runs it sees the #SpringBootApplication annotation and runs the #ComponentScan which scans the classes with the annotations such as #Component etc and makes the object in the container.I have a little bit of idea that it might be using reflections internally to create the objects but I am not able to connect all the dots .I want to know what exact information does #AutoConfiguration gives to the container that it is able to get all the information of all the component annotated clases of any component ?
P.s. I have edited the wrong question
First of all #AutoConfiguration is responsible for setting up the default configurations for a Spring boot application depending on the dependencies we have added in the pom.xml.
The thing you are looking for is #ComponentScan which is what performs the component class scanning within the default package and all of its sub packages. It does this by going through each class in the package and looking for the #Component,#Service or #Repository annotations. If any of them is present then the container adds this as a bean.
#SpringBootApplication internally has the #ComponentScan annotation added to it along with two others.
What is the entry point of a spring boot application?
While going through a Spring Boot application code, all that it says is there is a code
public static void main having - SpringApplication.run(Application.class, args)
Example - SpringBoot2RestServiceApplication.java .
But how to get to know what is the entry point, just by going through the code. Earlier, if we go through applicationContext.xml - example - applicationContext.xml, we could understand the flow.
Is there any way, or maybe a standard to follow to make this understanding self-explanatory?
My question was more of understanding the flow of the application than finding the main class. One option could be separating configurations(#Configuration) to a separate class having multiple #Bean annotations, this would help in finding all bean wirings at one place. Is there a standard that large projects use to make code flow understandable?
The easiest thing to do would probably be to search for #SpringBootApplication in your code.
But, a guaranteed way to get this information would be to build the Spring Boot JAR. From there, you can open the resulting JAR and find the main class defined in the manifest, under META-INF/MANIFEST.MF. You'll see it under the Start-Class attribute:
Start-Class: com.example.foo.Application
I think the OP is studying an existing Spring Boot application, and is asking how to locate any runner, such as Application Runners, Command Line Runners, MVC controllers, Rest controllers, etc.
I don't know if there is an easy way to locate those, unless they are grouped together in the original design.
It's a difficult problem to do programmatically, because threads can be launched outside of Spring, for example in a constructor or a #PostConstruct.
It would be nice though if there were IDE support to easily locate anything that gets launched by Spring Boot
search #SpringBootApplication annotation in your project, the class with #SpringBootApplication annotation will automatically do the component-scan for the sub packages.
if no #SpringBootApplication annotation found, search the class extending "SpringBootServletInitializer" which is also a starting point for the spring boot application
The Entry of any spring boot application has an annotation of #SpringBootApplication
I have a question about the usage of DataJpaTest annotation. I am trying to test a Jpa repository, exactly as shown in the documentation.
I am getting an error that the HttpServletRequest cannot be resolved. It is because a different bean of mine is using it.
Why is the test trying to use the irrelevant bean? I would expect a DataJpaTest to only load Jpa related beans, repositories, etc. It seems it is trying to load all beans, which of course have their own dependencies.
What is the correct way to write a DataJpaTest so that I only focus on my Jpa repositories?
This is on Java 8, Spring Boot 2 and junit 5.
Update 1: thanks for the comments guys. My test class is literally based on the documentation.
My Spring Boot application class is like this:
#SpringBootApplication
#EnableSwagger2
#EnableCorsFilter
#ComponentScan(basePackages = {"com.acme.superapp"})
#SuppressWarnings("HideUtilityClassConstructor")
public class Swagger2SpringBoot {
public static void main(String[] args) {
new SpringApplication(Swagger2SpringBoot.class).run(args);
}
}
This actually helped because after I removed the "ComponentScan" annotation I get a different error, related to Swagger.
So it seems these annotations are affecting my test.
Thanks for your comments guys. The comment from M. Deinum and shinjw showed me to the correct path. I needed to slim down the entrypoint so that it does not have anything extra.
According to the documentation :
If you structure your code in a sensible way, your
#SpringBootApplication class is used by default as the configuration
of your tests.
It then becomes important not to litter the application’s main class
with configuration settings that are specific to a particular area of
its functionality.
Therefore I moved the ComponentScan and EnableSwagger2 annotations elsewhere, in different Configuration classes and this did the trick.
Thanks for your help!
I am refactoring an application using Spring by moving some shared components (a webservice client) into a library. The components cannot work on their own so still need some beans from the application that uses the library. What is the best practice for this?
I have created a #Configuration class so the application only needs to #Import it to use the library, but the application also needs to supply a Jackson ObjectMapper and a Settings object containing how to contact the webservice. I autowire the ObjectMapper and Settings beans into various beans used in the library. The application uses the library by injecting the Client into its code and calling it.
This works, but I'm not sure it's the right style. In IntelliJ IDEA as I develop the library, it complains that the beans the library injects don't exist with a red underline, which is true, they don't exist. But normally when I see red all over files that cannot be resolved, that tells me maybe I'm not doing it the right way.
The library needs to be used with applications using Spring 3 and 5. What is the proper way for a library to ask for things like ObjectMapper when it's not appropriate to define its own (because the app will already have Jackson), and "proprietary" beans like the Settings object?
Your question is a bit broad but hopefully I can give you a hint to the right direction.
The components cannot work on their own so still need some beans from the application that uses the library. What is the best practice for this?
First: This components should use an interface instead of some concrete beans.
Second: If you have a reusable library then this typical needs some configuration, that can not been part of the library itself because it depends on application that use that library
Third: because of second (and first): your library should not been based on any form of auto wiring, instead your library should been based on explicit (or default) configuration.
And this solve the problem. Use interfaces and an explicit configuration of your library in your application. As well as add an good documentation of the needed configuration to your lib.
Using inspiration from #Kayaman and #Ralph, I decided it's not appropriate to expose Spring as a part of a library to be used directly from the application's context. I realize now it's also not appropriate because the library could define duplicate "private" beans it did not want to expose. I was overthinking it. If I wanted to use Spring, I found out I could do this:
public class Factory {
public static Client createClient(ObjectMapper mapper, Settings settings) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerSingleton("mapper", mapper);
beanFactory.registerSingleton("settings", settings);
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(beanFactory);
ctx.registerBean(ClientConfiguration.class);
ctx.refresh();
return ctx.getBean(Client.class);
}
}
Essentially, it's OK to use Spring as an implementation detail. Since the configuration I made exposed only one bean, it makes sense as a factory method. In the application I would create a method like this:
#Bean public Client makeClient(ObjectMapper mapper, Settings settings) {
return Factory.createClient(mapper, settings);
}
Of course the Bean method would have ObjectMapper and Settings injected in from the application's context, or could be inline constructors for ObjectMapper/Settings.
Instead, what I decided was since the client had few enough beans and none were lazy, I just removed Spring annotations entirely and just built the object graph by hand in almost as much code as the spring context took. Now the library has the benefit of not requiring Spring at all at runtime, in a supposed non-Spring application.
I am using Java-based Spring configuration in my project, specifying bean construction in #Bean-annotated methods in #Configuration. Recently, Recently, I've started to think that maybe it would've been better to use #Autowired to remove all non-important beans from #Configuration, leaving only small "root" set of them (key services and technical beans like those of Spring MVC).
Unfortunately, it seems that Spring can notice implementations for #Autowired dependencies only if they are inside component-scanned package which I cannot do without resorting to some XML.
Is there any way to use #Autowired with Java-based configuration without explicitly specifying each bean?
If I understand you correctly, you're expecting Spring to auto-discover the DaoImpl class based on the autowired dependency on the Dao interface.
This isn't going to happen - you either need to use component scanning, or you need to explicitly declare the bean, either as <bean> or #Bean.
The reason for this is that Java provides no mechanism to discover classes which implement a given interface, the classloader just doesn't work that way.
If you are implementing the Idao via dao and you are looking to #Autowire that dependency into your reference var... you need to first:
define the bean so you (in Java Based Config) simply return the impl class to the interface. The bean name is that of your method name.
When you autowire this, it will search for a matching name between your reference variable you are looking to autowire and your declaration.
THEN you will be fine. Hope this helps.