cannot Autowire a class from external jar in spring boot - spring-boot

Have a class A in a spring boot application. Have added a module in the pom, and i am able to import that class 'B' from that module in this class
but i am not able to autowire the same,
#EnableAutoConfiguration
class A
{
A(B b)
}
There are no compile time errors, but the application fails to start
Parameter 0 of method <> required a bean of type <> that could not be found
Tried annotating the main class with #ComponentScan({"package of class B"}) , no compile errors, but the application fails to start with same error, but with different classes.
thoughts ?

If you specify #ComponentScan with a specific package, Spring will only scan that package and subpackages for Spring beans. So if your different classes are in a different package structure, you have to add those packages as well in the annotation.

Related

Spring AOP aspect doesn't get applied if included from an external jar with different package name

I have a spring boot rest service that included an external project in pom as it's dependency. That external project is basically a jar that has spring AOP code.
The base package in my main application that includes this external jar with spring AOP code is x.y.z
The class in external jar where the #before advice is, is under the package a.b.c
With this class under a.b.c package, it doesn't get recognized by the main application where I want to use the spring aop implementation and apply the aspect. However, when I change it's package from a.b.c to x.y.z (which I really can't do in real life) it works fine.
I know that in spring boot service which happens to be the including service, it scans everything under root package given in the application class, x.y.z in this case and that is why aspect works fine if it's class is under x.y.z.
however, the problem is that this spring app jar will be used across multiple applications. So changing package name like this is not an option.
Is there a way to accomplish this without changing the package name of the class where spring app code is ?
Probably component scan is only activated for your application class packages by default. You can extend it to multiple packages, including the aspect package:
XML style configuration:
<context:component-scan base-package="x.y.z, a.b.c" />
Annotation style configuration:
#ComponentScan(basePackages = {"x.y.z", "a.b.c"})
Disclaimer: I am not a Spring user, only an AspectJ expert. I just knew that you can configure component scan, googled the syntax for you and hope it is correct.
Please define the bean (of jar project )inside main application. Give the #ComponentScan(basePackages = {"x.y.z", "a.b.c"}) as well as #EnableAspectJAutoProxy. Also include below piece of code.
ex:
` #Bean
public LoggingHandler loggingHandler()
{
return new LoggingHandler();
}`
Also annotate external jar code with:
`#Aspect
#Component
public class LoggingHandler {`
What #kriegaex suggests is correct. In addition to that, please make sure you are using #Component along with #Aspect. Since #Aspect is not a Spring annotation, Spring won't recognize it and hence your aspect won't be registered. So, using #Component is mandatory to getting aspects to work in Spring environment.

Spring not recognising some #Configuration and #Component classes

I have - or rather had - a working Spring application, running within IntelliJ. It contains several classes annotated with #Configuration, and several #Component beans. At some point, the following happened:
Intelli started showing errors in the code editor stating "Could not autowire. No bean of 'xxx' type found". But there are such beans which are annotated with #Component.
Breakpoints in the constructor of specific #Component beans are not reached. But that is not true for all #Component beans.
When running in debug mode, breakpoints in certain #Configuration files are not reached, even though the debugger was stopping there before. The application will fail if it is autowired with one of these #Component beans.
The application starts without errors, but obviously without several beans configured in #Configuration classes being called.
The class which contains the main method which runs the Spring Boot application is annotated with #SpringBootApplication. #Component classes which live in the same package as this class are recognised and can be autowired, even into classes in other packages.
I am not aware of anything in the code or project which would have changed.
Under File -> Project Settings -> Modules, under Spring Application Context have now selected all #Configuration files. However this makes no difference.
Have also tried Build -> Rebuild Project.
The packages in which the classes reside have not changed. Has anyone seen anything like this before?
Thanks
If few classes are not getting recognised #Component. Then it could be the case that those classes don't come under the same package. You must have observed that the classes under the same package as of Main class of #SpringBootApplication, got recognised with #Component because #SpringBootApplication defines an automatic #ComponentScan on the package.
So other classes which were defined in some other package are not recognised because there is no #ComponentScan for those classes' package.
You can do the following to get those classes recognised(add the other packages which are not directly under the hierarchy of #SpringBootApplication):
#ComponentScan({"com.example.springboot.anything","com.example.springboot.somethingelse"})
#SpringBootApplication
public class AnySpringBootApplication {
I am sure it will not be a common case, but for me the problem was that my class had a relatively generic name. Although it was located in the package mentioned in the ComponentScan, on the same level with other classes all found and used, I kept having problems that the ApplicationContext failed to load. After I renamed the class it worked, I found that two other classes in org.springframework had the same name.

External Java Library issue with Autowiring and injecting bean

I have created a Spring Boot application managed by Maven.
I'm retrieving an company's library from our Maven repository.
In this library, we have a service interface, not being annotated with '#Service':
public interface MyService {
//...
}
This service has only one implementation :
public class DefaultMyService implements MyService {
//...
}
This library context is managed the old Spring way (in applicationContext.xml file).
I read that normally, Spring Boot is able to find the implementation if there's only one in the scope.
When I try to run "spring-boot:run" on my project, it will fail with the following error :
No qualifying bean of type 'com.pharmagest.saml.SAMLService'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
I tried:
To add a #ComponentScan on the configuration class, including packages in error : #ComponentScan(basePackages={"com.mycompany.web", "com.mycompany.thelibrary.client.*", "com.mycompany.thelibrary.services.*"})
To add the bean definition in applicationContext.xml (if I add the interface it tells me it can define it, thus I heard that Spring can find the default implementation if there is only one ?)
To add library at "runtime" in projects options
To add the library as external resource not via maven
In all cases I just can maven build but can't run the project.
Do you have any advice to help me ? thanks!
Won't work as the DefaultMyService has no #Component (or #Service) annotation will not be detected.
Bean definition has to be a concrete instance so use DefaultMyService instead of the interface. Spring will not detect anything for you your understanding is wrong
and 4. Will not change anything only adding dependencies without proper 1. or 2. will do nothing.
Just add a #Bean to your configuration
#Bean
public DefaultMyService myService() {
return new DefaultMyService();
}
Or import the other libraries applicatiponContext.xml which is what you probably should do.
#ImportResource("classpath:/applicationContext.xml")
Add this next to the #SpringBootApplication.

Create auto configure spring library to spring-boot application

I am creating a library which uses spring 4.3.0.One of the spring-boot application will consume this library. Currently i am using #ComponentScan in the main class of spring-boot application to scan the beans inside library instead i want to auto-configure it.So what i did is i created a configuration class inside the library and declared #ComponentScan in the configuration file.
After consuming the library in spring-boot application it is not scanning the beans inside library and throws,
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sample.book.client.service.BookService] found for dependency [com.sample.book.client.service.BookService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1057)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
... 33 common frames omitted
How to resolve this error ? Why Spring scanning #service classes before #Configuration?
Your help should be appreciable and i will provide code-samples if needed.
It seems to me that most probable cause is that your library resides in a different package than your spring boot application (and its sub-packages). When annotating a class with #SpringBootApplication you also get #ComponentScan annotation set to its default (that is scanning components in a package where a given class resides).
Personally, I prefer to create a #Configuration annotated class in my library projects. Such class is responsible for proper library setup (declaring component scan and so on). Later, in dependent project I use an #Import annotation to import that configuration class (and corresponding beans).
I like the import. But I wanted to avoid any imports or package scan in client code.
I built my-lib (spring-boot)
by defining, Configuration in resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.fanniemae.ebrms.dsrunner.DecisionServiceRunnerConfiguration
added componentScan in my configuration (my-lib)
#Configuration
#EnableConfigurationProperties(DecisionServiceRunnerProperties.class)
#ComponentScan(basePackages = { "com.xyz.dsrunner.*" })
public class DecisionServiceRunnerConfiguration {
and just included as dependency in my client spring boot application.
I guess that your config is not loaded by default from your Boot Application.
I also guess that you have not added
#EnableAutoConfiguration
to your Boot Application.
So you can try to add your config to the Annotation #EnableAutoConfiguration to be loaded by your application. Then the Configuration that you put in META-INF/spring.factories inside your library-JAR is automatically loaded.
Or you can #Import your configuration in your #SpringBootApplication class
#Import({MailServiceConfig.class, ServiceConfig.class})
can be use for enable the specific configurations;
http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch04s03.html

How to Autowire repository interface from a different package using Spring Boot?

I am new to Spring Boot and want to autowire a repository from a different package in a Rest Controller. It seems that when I place the interface and implementation in a different package the actual controller the autowire seems to fail.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.acme.repository.RawDataRepository] found for dependency:..
Controller:
package com.acme.controller;
import com.acme.repository.RawDataRepository;
// imports removed!
#RestController
#EnableAutoConfiguration
#ComponentScan("com.acme")
public class DataCollectionController {
#Autowired
private RawDataRepository repository;
// code removed!
}
I have tried to use the #ComponentScan annotation but this gives no solution.
Any idea what i am missing? Whenever i put the interface into the package in which the controller resides then all goes well.
If you have Spring Data #Repositories in a different package you have to explicitly #EnableJpaRepositories (or replace "Jpa" with your own flavour). Boot takes it's defaults from the package containing the #EnableAutoConfiguration so it might work to just move that class as well.
You have to use following two annotations
#EnableJpaRepositories(basePackages = "package-name")
#EntityScan(basePackages = "package-name")
EnableJpaRepositories will enable repository if main class is in some different package.
You need to use EntityScan as well to point to package where you have your entity beans or else it will fail with 'Bean is not of managed type' error.
Spring Boot Provides annotations for enabling Repositories.
So whenever someone uses any Repository (it can be JPARepository , CassandraReposotory) it should be enabled in Application Class itself.
Example:
#EnableCassandraRepositories("package name")
#EnableJpaRepositories("package name")
After providing the above annotations, the container takes care of injecting beans for repositories as well.

Resources