I am having the class like below
#Controller
#RequestMapping(value = "/test")
#AllArgsConstructor
public class TestController {
#Qualifier("userDAO")
private final Test testDAO;
}
Below is my bean registration
<bean id="userDAO" class="com.test.dao.TestImpl"
p:sqlSessionFactory-ref="testSqlSessionFactory" />
when I run my app got error like below
No default constructor found; nested exception is java.lang.NoSuchMethodException bean configuration
Also I tried to add the lombok.config file in root and copied the Qualifier annotation, that's also not helped.
spring version is 3.2.15. lombok version 1.18.16
It's working fine with below
#Autowired
public TestController(#Qualifier("userDAO") final Test testDAO) {
this.testDAO = testDAO;
}
How to resolve this?
Adding only an #AllArgsConstructor isn't enough, as it will add the constructor but it doesn't add #Autowired. Because that is missing Spring will look for the default constructor.
To fix you can do 1 of 3 things
Upgrade to Spring 4.3 or higher, as that will automatically use the single constructor and autowire it
Instruct lombok to add #Autowired to the constructor.
Ditch lombok and just provide the constructor yourself.
The first should be pretty easy (include a newer version of Spring in your dependencies). The second requires some additional code.
#Controller
#RequestMapping(value = "/test")
#AllArgsConstructor(onConstructor = #__(#Autowired))
public class TestController {
private final Test testDAO;
}
The #Qualifier won't work (and should be removed) as it should be on the constructor argument.
I would just ditch Lombok for this case and just add the constructor (option 3).
#Controller
#RequestMapping(value = "/test")
public class TestController {
private final Test testDAO;
#Autowired
public TestController(#Qualifier("userDAO") Test testDao) {
this.testDao=testDao;
}
}
I want to create two spring-boot projects which communicate via rest calls. The first one contains the UI part with loginForm. The second project should communicate with the DB and should fetch the information about the user and then send it back to the UI.
The service project contains two modules: data module and impl module. The data project should contain the common data shared between the UI and the service project. It should be only a jar which I will add as a dependency in the UI project and the impl module in the service project.
The impl module should contain entities, repositories, restcontrollers and a service layer containing the real back-end logic of the application. I have already created the UI project but I have problems with the service. In the data module I have created the classes with the user information in a package org.tu.userdata. In the service impl I have an userController like this:
package org.tu.userserviceimpl.controller;
#RestController
#RequestMapping("/user")
public class UserController {
private final UserAuthenticationService userService;
#Autowired
public UserController(UserAuthenticationService userService) {
this.userService = userService;
}
#PostMapping(value = { "/logUser" })
public UserDto logUser(#RequestBody AuthenticateUserDto authenticateUserDto) throws Exception {
return userService.logUser(authenticateUserDto);
}
#PostMapping(value = { "/register" })
public UserDto register(#RequestBody RegisterUserDto registerUserDto) throws Exception {
return userService.registerUser(registerUserDto);
}
}
It injects the UserAuthenticationService which is an interface implemented like this:
package org.tu.userserviceimpl.service.impl;
#Service
public class UserAuthenticationServiceImpl implements UserAuthenticationService {
private final UserRepository userRepository;
#Autowired
public UserAuthenticationServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDto registerUser(RegisterUserDto registerUserDto) throws AuthenticationException {
return new UserDto();
}
#Override
public UserDto logUser(AuthenticateUserDto authenticateUserDto)
throws UserPrincipalNotFoundException, AuthenticationException {
return new UserDto();
}
}
the UserRepository:
package org.tu.userserviceimpl.repository;
#Repository
public interface UserRepository extends JpaRepository<UserEntity, Long> {
UserEntity findByUsername(String username);
boolean existsByUsername(String username);
boolean existsByEmail(String email);
}
and an application class:
package org.tu.userserviceimpl;
#SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
When I run it I get:
*************************** APPLICATION FAILED TO START
Description:
Parameter 0 of constructor in
org.tu.userserviceimpl.service.impl.UserAuthenticationServiceImpl
required a bean of type
'org.tu.userserviceimpl.repository.UserRepository' that could not be
found.
I thought that's strange because the UserRepository should be visible there since its a directory below the application class. To solve this I added a ComponentScan annotation on the application class:
#ComponentScan("org.tu.userserviceimpl.repository")
After that the project builds and deploys fine but I cannot access it. I got an 404 error. I even added an method like this one in the UserController just to troubleshoot it:
#GetMapping("/hello")
public String hello() {
return "hello";
}
But still cannot access it. The application is deployed on port 8082 but when I try to access "http://localhost:8082/user/hello" I cannot. After that I tried to remove the code in the UserAuthenticationServiceImpl which injects the UserRepository and I removed the componentScan annotation as well. After this code removal I was able to reach "http://localhost:8082/user/hello" and I got the message "hello" there. This means that the problem is somewhere in the Repository. Then I tried to add:
#EnableJpaRepositories("org.tu.userserviceimpl.repository")
#EntityScan("org.tu.userserviceimpl.entity")
on top of the application class and I added the code which injects the repository in the UserAuthenticationServiceImpl again. This time the outcome was a different error:
Parameter 0 of constructor in org.tu.userserviceimpl.service.impl.UserAuthenticationServiceImpl required a bean named 'entityManagerFactory' that could not be found.
I deleted the EntityScan annotation but the result was the same. Any ideas? What I am doing wrong?
I uploaded almost the same project in github: https://github.com/lei-gustavson/user-service.git
You have already created an argument based constructor in UserAuthenticationServiceImpl .
as below:
public UserAuthenticationServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
So NO argument constructor can't be created by JVM automatically.
and the below line has also not autowired
private final UserRepository userRepository;
Please add no argument constructor or remove the existing to resolve this issue.
Can you try putting below statement ?
#EntityScan("org")
I also have faced same issue but when i have used above statement for my directory structure it works.
Note :
You are confused between #ComponentScan and #EntityScan.
Just do one thing both above annotation annote like,
#ComponentScan("org"),
#EntityScan("org") and
#EnableJPARepository("org")
Mostly it will work for you
Thank you all for trying to help me! I find a solution. The problem was that i didnt have JPAConfig file. This solved the problem:
#Configuration
#EnableJpaRepositories("org.tu.userserviceimpl.repository")
public class JPAConfig {
}
After that i deleted the ComponentScan annotation from the SpringBootApplication class and everything was up and running
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
Here are the files that I use:
component.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<context:component-scan
base-package="controllers,services,dao,org.springframework.jndi" />
</beans>
ServiceImpl.java
#org.springframework.stereotype.Service
public class ServiceImpl implements MyService {
#Autowired
private MyDAO myDAO;
public void getData() {...}
}
ServiceImplTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath*:conf/components.xml")
public class ServiceImplTest{
#Test
public void testMyFunction() {...}
}
Error:
16:22:48.753 [main] ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#2092dcdb] to prepare test instance [services.ServiceImplTest#9e1be92]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'services.ServiceImplTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private services.ServiceImpl services.ServiceImplTest.publishedServiceImpl; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [services.ServiceImpl] found for dependency: 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.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) ~[spring-beans.jar:3.1.2.RELEASE]
Make sure you have imported the correct package. If I remeber correctly there are two different packages for Autowiring. Should be :org.springframework.beans.factory.annotation.Autowired;
Also this looks wierd to me :
#ContextConfiguration("classpath*:conf/components.xml")
Here is an example that works fine for me :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/applicationContext_mock.xml" })
public class OwnerIntegrationTest {
#Autowired
OwnerService ownerService;
#Before
public void setup() {
ownerService.cleanList();
}
#Test
public void testOwners() {
Owner owner = new Owner("Bengt", "Karlsson", "Ankavägen 3");
owner = ownerService.createOwner(owner);
assertEquals("Check firstName : ", "Bengt", owner.getFirstName());
assertTrue("Check that Id exist: ", owner.getId() > 0);
owner.setLastName("Larsson");
ownerService.updateOwner(owner);
owner = ownerService.getOwner(owner.getId());
assertEquals("Name is changed", "Larsson", owner.getLastName());
}
I've done it with two annotations for test class: #RunWith(SpringRunner.class) and #SpringBootTest.
Example:
#RunWith(SpringRunner.class )
#SpringBootTest
public class ProtocolTransactionServiceTest {
#Autowired
private ProtocolTransactionService protocolTransactionService;
}
#SpringBootTest loads the whole context, which was OK in my case.
A JUnit4 test with Autowired and bean mocking (Mockito):
// JUnit starts with spring context
#RunWith(SpringRunner.class)
// spring loads context configuration from AppConfig class
#ContextConfiguration(classes = AppConfig.class)
// overriding some properties with test values if you need
#TestPropertySource(properties = {
"spring.someConfigValue=your-test-value",
})
public class PersonServiceTest {
#MockBean
private PersonRepository repository;
#Autowired
private PersonService personService; // uses PersonRepository
#Test
public void testSomething() {
// using Mockito
when(repository.findByName(any())).thenReturn(Collection.emptyList());
Person person = new Person();
person.setName(null);
// when
boolean found = personService.checkSomething(person);
// then
assertTrue(found, "Something is wrong");
}
}
For Spring 5.x and JUnit 5, writing unit tests is quite different.
We have to use #ExtendWith to register Spring extensions (SpringExtension). This brings Spring into play which activates part of the application context (instantiates and manages beans from selected configuration classes).
Note that this is different from the effect of #SpringBootTest which loads the full application context (and IMHO cannot be considered a unit test).
For example, let's create a configuration class FooConfig which produces a bean named foo1:
#Configuration
public class FooConfig
{
#Bean
public String foo1() { return "Foo1"; }
}
Now, let's write a JUnit 5 test case which injects foo1:
import static org.junit.jupiter.api.Assertions.*;
// ... more imports ...
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {
helloworld.config.FooConfig.class,
})
class FooTests
{
#BeforeAll
static void setUpBeforeClass() throws Exception {}
#AfterAll
static void tearDownAfterClass() throws Exception {}
#BeforeEach
void setUp() throws Exception {}
#AfterEach
void tearDown() throws Exception {}
#Autowired
private String foo1;
#Test
void test()
{
assertNotNull(foo1);
System.err.println(foo1);
}
}
In Spring 2.1.5 at least, the XML file can be conveniently replaced by annotations.
Piggy backing on #Sembrano's answer, I have this. "Look ma, no XML".
It appears I to had list all the classes I need #Autowired in the #ComponentScan
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(
basePackageClasses = {
OwnerService.class
})
#EnableAutoConfiguration
public class OwnerIntegrationTest {
#Autowired
OwnerService ownerService;
#Test
public void testOwnerService() {
Assert.assertNotNull(ownerService);
}
}
I think somewhere in your codebase are you #Autowiring the concrete class ServiceImpl where you should be autowiring it's interface (presumably MyService).
You should make another XML-spring configuration file in your test resource folder or just copy the old one, it looks fine, but if you're trying to start a web context for testing a micro service, just put the following code as your master test class and inherits from that:
#WebAppConfiguration
#RunWith(SpringRunner.class)
#ContextConfiguration(locations = "classpath*:spring-test-config.xml")
public abstract class AbstractRestTest {
#Autowired
private WebApplicationContext wac;
}
You can use #Import annotation. It's more readable and shorter than using the #ComponentScan annotation.
import org.springframework.context.annotation.Import;
#Import(value = {MyService.class, MyInjectedService.class})
public class JUnitTest {
#Autowired
private MyService service;
// ...
}