I have problem with UserDetailsServiceImpl()
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'securityConfig': Injection of autowired
dependencies failed; The constructor UserDetailsServiceImpl() is
undefined
#Bean
public UserDetailsService userDetailsService(){
return new UserDetailsServiceImpl();
}
#Service
#NoArgsConstructor(force = true)
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserService userService;
#Autowired
public UserDetailsServiceImpl(UserService userService) {
this.userService = userService;
}
Application failed to start((
I saw your project and review something about that.Here you want to implement both User with CustomUser and UserDetailsService with custom userDetailsService.
1) Your UserDetailsServiceImpl class implements UserDetailsService. Inject your UserService with Autowired annotation. Remove this constructor or just comment it.
#Autowired
private UserService userService;
/*public UserDetailsServiceImpl(UserService userService) {
this.userService = userService;
}*/
2) Annotate your interface UserService with #Service and it implementation class UserServiceImpl with #Repository as they are spring component.
3)Remove this Bean from AppConfig Class.
#Bean
public UserDetailsService userDetailsService(){
return new UserDetailsServiceImpl();
}
4) As you create your custom UserDetailsService named UserDetailsServiceImpl so you need to introduce your custom implementation to AuthenticationManagerBuilder. To do this inject your custom class in SecurityConfig with #Autowired annotation.
#Autowired
private UserDetailsServiceImpl userDetailsService;
5) Yes, you are in last phase. set this userDetailsService to authentication manager by setting
#Autowired
public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(getShaPasswordEncoder());
}
So you are almost done. Since you used Spring-boot, so it embedded with tomcat server (a servlet container). Go to your pom.xml and find packaging tag ( generally places at first )and change it to
<packaging>jar</packaging>
Now clean and build your project (In my case I used netbeans to clean and build, you can use maven command). After successfully build, you found a /target folder. Go to the folder and open terminal, run the jar with java -jar music-review-1.0-SNAPSHOT.jar.
Your updated project can be found here.
Create a interface named UserDetailsService;
public interface UserDetailsService{
public void someMethod();
}
Implement the interface as follows
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
UserDetailsService userDetailsService;
#Override
public void someMethod() throws Exception {
//your implementation
}
}
Related
I have a service class, called CommandUser with 4 dependencies (3 repositories and one passwordEncoder) and a respective test class, called CommandUserTest. I instantiate the 3 dependencies using #Autowired and the passwordEncoder using #RequiredArgsConstruct.
The problem happens when I run the createUser test, the 3 repositories mocks are null and only the passwordEncoder mock were initialized properly. I think the problem is related with use of different dependecy injections approaches (#Autowired and #RequiredArgsConstructor).
One solution is use #Autowired in passwordEncoder dependency (all dependencies using #Autowired) or all dependencies using #RequiredArgsConstructor, but I wanna understand why this happens.
Thanks in advance.
The service class (CommandUser):
#Service
#RequiredArgsConstructor
#Transactional
public class CommandUser implements ICommandUser, UserDetailsService {
#Autowired
private IQueryRoleRepository queryRoleRepository;
#Autowired
private ICommandUserRepository commandUserRepository;
#Autowired
private IQueryUserRepository queryUserRepository;
private final PasswordEncoder passwordEncoder;
#Override
public User createUser(User user) throws GeneralBusinessException {
Optional<User> optionalUser = queryUserRepository.findUserByUsername(user.getUsername());
if(optionalUser.isPresent()) throw UserAlreadyExistsException.builder().username(user.getUsername()).build();
user.setPassword(passwordEncoder.encode(user.getPassword()));
return commandUserRepository.saveUser(user);
}
// other methods;
}
The test class (CommandUserTest):
#ExtendWith(MockitoExtension.class)
class CommandUserTest {
#Mock
private IQueryRoleRepository queryRoleRepository;
#Mock
private ICommandUserRepository commandUserRepository;
#Mock
private IQueryUserRepository queryUserRepository;
#Mock
private PasswordEncoder passwordEncoder;
#InjectMocks
private CommandUser commandUser;
#Test
void createUser() throws GeneralBusinessException {
// given
User user = factoryDummyUser();
// when
commandUser.createUser(user);
// then
verify(commandUserRepository).saveUser(user);
}
// other tests
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I'm working on a Spring Boot application and I'm trying to inject my UserService class into my TenantIdentifierResolver class because I want to use the createUser() method. However i get a nullpointer exception. For some reason userService is set to null, what am I missing here?
#Component
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver {
public static final String DEFAULT_TENANT = "default_schema";
private UserService userService;
#Override
public String resolveCurrentTenantIdentifier() {
String tenant = TenantContext.getCurrentTenant();
if(tenant != null){
userService.createUser(tenant);
return tenant;
} else {
return DEFAULT_TENANT;
}
}
#Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
I've tried to use #Autowired or make a constructor injection but then I got this error:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| entityManagerFactory defined in class path resource [org/example/membership/config/HibernateConfig.class]
↑ ↓
| tenantIdentifierResolver (field private org.example.membership.service.UserService org.example.membership.multitenancy.TenantIdentifierResolver.userService)
↑ ↓
| userService defined in file [C:\project\Member\server\target\classes\org\example\membership\service\UserService.class]
↑ ↓
| userRepository defined in org.example.membership.repository.UserRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration
↑ ↓
| (inner bean)#18957a3d
└─────┘
This is my UserService class
#Service
public class UserService {
private UserRepository userRepository;
private TenantService tenantService;
public UserService(UserRepository repository, TenantService tenantService) {
this.userRepository = repository;
this.tenantService = tenantService;
}
#Transactional
public User createUser(String tenant) {
Tenant tenant = new Tenant();
tenant.setTenantName(tenant);
tenantService.initDatabase(tenant);
return tenant ;
}
}
This is my HibernateConfig class
#Configuration
public class HibernateConfig {
#Autowired
private JpaProperties jpaProperties;
#Bean
JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
#Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource,
MultiTenantConnectionProvider multiTenantConnectionProviderImpl,
CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl
) {
Map<String, Object> jpaPropertiesMap = new HashMap<>(jpaProperties.getProperties());
jpaPropertiesMap.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
jpaPropertiesMap.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProviderImpl);
jpaPropertiesMap.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolverImpl);
LocalContainerEntityManagerFactoryBean em = new
LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("org.example*");
em.setJpaVendorAdapter(this.jpaVendorAdapter());
em.setJpaPropertyMap(jpaPropertiesMap);
return em;
}
}
#Autowired
private UserService userService;
As for the circular dependency problem, I think you should try to avoid.
In the end you have to resolve the circular dependency, no matter what injection types you use or if you resort to lazy injection etc.
At the moment your entityManagerFactory requires the userService bean (through the tenantIdentifierResolver), which in itself requires entityManagerFactory. That's a bad architecture. You can either remove the call to userService from the tenantIdentifierResolver, or change it so that no JPA related functionality is used in there (i.e. if you really need to create the tenants/users on the fly, use plain JDBC calls in there). Then you have broken the dependency cycle and everything should work.
You are not injecting the dependency. You should use Constructor injection:
private final UserService userService;
public TenantIdentifierResolver(UserService userService) {
this.userService = userService;
}
Or if you prefer you can use attribute injection:
#Autowired
private UserService userService;
The problem you are facing here is called circular dependency. It occurs when two components need bean of each other. Spring doesn't know which one to create first. You can read more about it here www.netjstech.com/2018/03/circular-dependency-in-spring-framework.html
Easiset solution would be to implement setter-based auto wiring in one of components.
#Component
public class TenantIdentifierResolver {
private UserService userService;
public UserService userService() {
return userService;
}
#Autowired
public void setUserService(final UserService userService) {
this.userService = userService;
}
}
I added spring security to my application and it's working great, but now existing tests are broken, when I run them I get:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userDetailsService in xxx.xxx.someapp.spring.security.WebSecurityConfig required a bean of type 'xxx.xxx.sardinatank.someapp.security.services.UserDetailsServiceImpl' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
This is how I'm wiring the UserDetailsServiceImpl in my WebSecurityConfig
#Autowired
UserDetailsServiceImpl userDetailsService;
This is an example controller
#RestController
public class HelloWorldController {
#GetMapping
public ModelAndView helloWorld() {
final ModelAndView bootstrapFront = new ModelAndView("index.html");
return bootstrapFront;
}
}
And this is a test that fails
#WebMvcTest(controllers = HelloWorldController.class)
#ContextConfiguration
#WebAppConfiguration
class HelloWorldControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#BeforeEach
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void getBootstrappedDoc() throws Exception {
MvcResult mvcResult = mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andReturn();
assertEquals("index.html", mvcResult.getModelAndView().getViewName());
}
}
I guess you might have declared it as a #Component or something that is not part of this list:
#Controller, #ControllerAdvice, #JsonComponent, Converter, Filter, WebMvcConfigurer
which means UserdetailServiceImpl will not be part of the #SpringWebMVC sliced test context, hence spring doesn't bootstrap it.
You have 2 options:
Either you decorate your UserServiceImpl with one of the aforementioned annotations: e.g
#JsonComponent
class UserDetailsServiceImpl implements userDetailsService { ... };
Or you inject a mock of UserServiceImpl in your test with #MockBean:
#WebMvcTest(controllers = HelloWorldController.class)
#ContextConfiguration
#WebAppConfiguration
class HelloWorldControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
#MockBean
UserDetailsServiceImpl userDetailsService;
private MockMvc mockMvc;
//...
}
I have a problem in spring boot concerning repositories.
I have a service :
#Service("userService")
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
}
and the repos here :
#Repository("userRepository")
public interface UserRepository extends CrudRepository<User, Long> {
User findByEmail(String email);
}
When I run the app I get this message :
Description:
Field userRepository in com.projectWS.service.UserServiceImpl required a
bean of type 'com.projectWS.repo.UserRepository' that could not be found.
Action:
Consider defining a bean of type 'com.projectWS.repo.UserRepository' in your
configuration.
Please help me I'm so desperate...
this is my main class:
#SpringBootApplication
#Configuration
#EnableWebMvc
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Another problem is , #EnableJpaRepositories doesn't get recognized !!
most likely your Main class is defined within a package and your other packages are not getting scanned.
Try annotation your Main class with:
#ComponentScan("com.projectWS")
judging by your error message and assuming that the top of your package level starts at com.projectWS
I am not a Spring expert but I suspect that this can be because of the case of the name of these classes. Just for peace of mind test this please:
#Service("userService")
public class UserServiceImpl implements UserService {
#Qualifier("userRepository")
#Autowired
private UserRepository userRepository;
#Qualifier("roleRepository")
#Autowired
private RoleRepository roleRepository;
}
It seems like you have not added Spring data for JPA, add the following to your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
I have Spring Java Services class with a lot of beans:
#Service ("employeeManager")
public class EmployeeManagerImpl implements EmployeeManager
{
#Autowired
EmployeeDAO employeedao;
#Autowired
Workerdao workerdao;
#Autowired
SallaeryDao sallaeryDao
#Autowired
TaxDao taxDao
#Autowired
HouresDao houresDao
#Autowired
*****Dao
public EmployeeDTO createNewEmployee()
{
return dao.createNewEmployee();
}
}
Can I clean the Service class code without a lot of bean declare in my class that I will have only one bean? I have a lot of bean and I don't want to declare them in the class with