strange behaviour with componentscan in spring boot - spring

I have 3 packages:
mainpackage
repositories
controller
in my SpringBootApplication I have annotated:
#SpringBootApplication
#ComponentScan({"mainpackage","repositories","controller"})
In my repositories Package I have a component:
#Component
public interface UserRepository extends CrudRepository<User,Long> {
}
In my controller package I have a controller which autowires a component of 'repositories' :
#RestController
public class MyController {
#Autowired
private UserRepository userRepository;
which leads into :
Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException
What am I doing wrong ?
keeping all classes in one package works, but I like to have it a bit structured.

You're using spring-data-jpa repository, but it seems that you don't have any #EnableJpaRepositories in your SpringBootApplication class.
Please add it, e.g:
#SpringBootApplication
#ComponentScan({"mainpackage","repositories","controller"})
#EnableJpaRepositories("repositories")
and you might also need to add an #EntityScan with package where your entities resides:
#EntityScan("entities")

Related

Inject CRUD Repository in Spring

I can't Inject CRUD Repository in Spring.
Repository
#Repository
public interface EntityRepository extends CrudRepository<entity,Long>{
}
#Autowired EntityRepository eR
Error:
.. Required a Bean of Type EntityRepository that could not be found
Consider defining a bean of type 'EntityRepository' in your configuration.
My main
#SpringBootApplication
#ComponentScan({"de.xyz.*"})
#EntityScan("de.xyz.entities")
#EnableJpaRepositories("de.xyz.*")
//#EnableEurekaClient
public class Application extends SpringBootServletInitializer {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Another way of doing this is using the basePackages field; which is a field inside ComponentScan annotation.
#ComponentScan(basePackages = {"de.xyz.repository"})
public class Application extends SpringBootServletInitializer {
//
}
Step1 :
Try to include both the classes in the same package. This way you can narrow down the issue of component scanning. Remove all other annotations and keep only #SpringBootApplication
Note :
By default spring loads all the classes under the package of Application Class.
Step2 : See your dependencies, verify you have included the dependencies for JPA repositories.
Step3 : Post the GIT Hub link of the code, so that it can be looked further.
Otherwise add all the packages inside the component scan annotation , Like below.
#ComponentScan({ "a.b.c", "a.b.c.dao" })
As you have mentioned there is a configuration class which is creating the beans, try to include that class package in the same package or include it in component scan.
Hope this help.

How can I register an auto-implemented repository located in a dependency as bean?

I have a module A with a project dependency of module B:
A's build.gradle
dependencies {
....
compile project(":B")
}
In module B, I have this interface:
#Repository
public interface MyRepo extends CrudRepository<User, String> {
//some methods
}
In module A, I have this configuration class:
#Configuration
public class MyConfig {
#Bean
public MyRepo provideMyRepo() {
//???
}
}
How can I export MyRepo bean in module A?
I have tried using #ComponentScan and #EnableJpaRepositories:
#Configuration
#EnableJpaRepositories(basePackageClasses = MyRepo.class)
public class MyConfig {
#Autowired
public MyRepo myRepo;
}
But bean cannot be found:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean found for dependency
You can either #EnableJpaRepositories the package that MyRepo is contained in.
Or add a configuration is in Module B which will scan the required pacakges for the Repository for you and use the Import to pull the Configuration into A.
If it's a Spring Boot project you have the added functionality of Auto-configurations, https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
Finally, If the repository is already registered you can just use it as normal.
You don't need a new configuration for that repository since it is already registered with Spring. You can just inject it directly in your client classes in A module:
#Component
public class MyComponent {
#Inject
private MyRepo myRepo;
// your code using myRepo
}
If Spring says it can't find the bean, you need to check the autowiring configuration you have, so check that your scan path contain the repository class in B (change that using #ComponentScan or )
See this example

spring boot test slices for Web applications

I have an SpringBootApplication annotated class that also extends WebSecurityConfigurerAdapter to provider websecurity. This application also has a JPA layer which I want to test in isolation.
The appliation class roughly looks like
#SpringBootApplication
public class Application extends WebSecurityConfigurerAdapter {
...
}
Now I have a repository test that looks roughly like
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class, DbUnitTestExecutionListener.class})
#RunWith(SpringJUnit4ClassRunner.class)
#DataJpaTest
#DatabaseSetup(Stubs.MASTER_DATASET)
public class AppUserRepositoryTest {
...
}
However when I run this I get an error that says an ObjectPostProcessor needs to be wired. While I can understand the reason, Trying to understand if there is any workaround/solution to avoid having to define #MockBeans for all of the dependencies in WebSecurityConfigurerAdapter. The error I get is
Description:
Parameter 0 of method setObjectPostProcessor in org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter required a bean of type 'org.springframework.security.config.annotation.ObjectPostProcessor' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.security.config.annotation.ObjectPostProcessor' in your configuration.

Spring boot - #Component Annotation creates two beans of same type

When I add the #Component annotation to a class, it creates two beans of the same type (class type) and I get an error that there is no unique bean identifier.
But when I remove the #Component annotation, I only get one bean.
I don't see where the other bean is created.
Here is the class where I add #Component to:
package main.serviceconfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
#Component
/* prefix of key in application.properties*/
#ConfigurationProperties("")
public class ServiceConfiguration {
/* declare key suffixes here */
/* Then add getters and setters for the keys' values */
}
Where I #Autowire the bean:
#Controller
#Service
#Configuration
#RequestMapping("/users")
#EnableConfigurationProperties(ServiceConfiguration.class)
public class UserRestController {
#Autowired
private UserRepository repo;
#Autowired
private ServiceConfiguration config;
...
}
However, in the package explorer of my Eclipse IDE, I see that under Spring Elements -> Beans -> #Component annotation, that there are two beans of type main.serviceconfiguration.ServiceConfiguration
one is called serviceConfiguration
and the other is called main.serviconfiguration.ServiceConfiguration
The error from log:
No qualifying bean of type [main.serviceconfiguration.ServiceConfiguration] is defined: expected single matching bean but found 2: serviceConfiguration,main.serviceconfiguration.ServiceConfiguration
That is curious.
What you can do is force a name for the component like #Component("foo")
and then along with #Autowired add #Qualifier("foo")
This does not address the root cause though.
#EnableConfigurationProperties(ServiceConfiguration.class) already creates a bean of that type. Generally, you have duplicated annotations on all your classes shown here, which aren't necessary. For instance, why have you #Controller and #Service on your class? One is enough. And if it is a controller, it shouldn't be a configuration class, so you should remove the annotation #Configuration.

Spring annation for service

I am trying to use Spring annotation to define controller, service and dao, but failed.
the error message is
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.abs.absbase.ABSService] is defined: Unsatisfied dependency of type [interface com.abs.absbase.ABSService]: expected at least 1 matching bean
but I do define the service.
Another question is, how to define a sessionfactory to overwrite the HibernateDaoSupport in the ABSDaoImpl ?
Thanks
Source code is
#Controller
#RequestMapping("/abs.do")
public class ABSController {
#Autowired
#Qualifier("ABSService")
ABSService service;
...
}
#Service(value="ABSService")
public class ABSServiceImpl implements ABSService {
#Autowired
#Qualifier("ABSDao")
ABSDao dao;
}
#Repository(value="ABSDao")
public class ABSDaoImpl extends HibernateDaoSupport implements ABSDao {
...
}
According to me you just need to remove the #Qualifier annotation you have defined above the declaration of ABSService object in the controller. And also remove the (value="ABSService") from the #Service annotation on the service.
Hope this helps you.
Cheers.

Resources