Spring boot CrudRepo Define a bean - java

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>

Related

JAVA - Can I delete #Autowire directly?

after my teammates merged her changes (implements #EnableFeignClients for our SpringBootApplication and created some feign clients, properties and configs from the main branch), when boot the application it will pop up the The dependencies of some of the beans in the application context from a cycle: xxx
To resolve this issue I deleted some #Autowired from some involved controller/service classes and make them private and then the application can be boot successfully:
before my change:
#Autowired
MyUtil myUtil; //#Component
#Autowired
MyConfig myConfig; //#Component
#Autowired
MyApi myApi; //Interface class
public void myFunction(){
String id = myUtil.getId();
String name = myConfig.getNameById(id);
myApi.sendInfo(id, name);
}
after my change:
private MyUtil myUtil; //#Component
private MyConfig myConfig; //#Component
private MyApi myApi; //#Component
public void myFunction(){
String id = myUtil.getId();
String name = myConfig.getNameById(id);
myApi.sendInfo(id, name);
}
Spring version:
<groupID>org.springframework.boot</groupID>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.11</version>
and here are my concerns:
Will there be any impact after my changes (functional, performance, etc.)?
In my case (or in most scenarios in the future development), should i use #Autowired? When need to? When doesn't need to?
TL DR. You cannot delete #Autowired directly.
#Autowired is used by Spring in order to do dependency injection ( I know this is a fancy word)
#Autowired
ChickenService chickenService
#Autowired is almost equivalent to ChickenService chickenService = new ChickenService();
After your change,private MyConfig myConfig; //#Component myConfig will be null and therefore you introduced a bug.
Suppose that you have an EggService
#Service
public class ChickenService {
#Autowired
private EggService eggService;
}
The chicken holds a reference to the egg
#Service
public class EggService {
#Autowired
private ChickenService;
}
Now you have a chicken and egg problem.
https://www.baeldung.com/circular-dependencies-in-spring
#Autowired help the spring to find where it should inject classes.
The impact is that spring will not create objects of the classes where you removed the annotation.
Additional way to create objects in spring are with setter or constructor injection.
Example of constructor injection will be something like:
public YourClassName(MyUtil myUtil, MyConfig myConfig, MyApi myApi){
this.myUtil = myUtil;
this.myConfig = myConfig;
this.myApi = myApi;
}
I think also good idea as well to check why #Autowired not working. Can you provide full error? Does your class annotated with #Service or something

Why does autowired repository result in a NullPointerException in Junit4 context?

I'm new to Java development so sorry in advance if I'm not using the appropriate terms.
Whenever I run a test on a class that needs to save something in my database, I face a NullPointerException on the Autowired repository.
I use Junit4, here are code snippets :
application-test.properties
spring.datasource.url=jdbc:tc:mysql:8.0.29://localhost:3306/MYSERVICE
MyService.java
#Component
class MyService {
#Autowired MyRepository myRepository;
public void mainFunction() {
myRepository.saveSomething();
}
}
MyRepository.java
#Repository
public interface MyRepository extends JpaRepository<T, Long> {
void saveSomething();
}
MyServiceTest.java
public class myServiceTest extends TestConfiguration {
#Rule
public MySQLContainer mysql = new MySQLContainer();
#InjectMocks MyService myService;
#Test
public void mainFunctionTest() {
myService.mainFunction()
}
}
MyServiceTestApplication.java
#SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class
})
public class MyServiceTestApplication{
}
TestConfiguration.java
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyServiceTestApplication.class)
#ActiveProfiles("test")
public abstract class TestConfiguration {
}
When I run the test in debug mode, I can see that myRepository is null
Any help would be highly appreciated
Thanks :)
Edit 01/08/2022 : Add #Component on MyService
Edit 01/08/2022 (2) : Add MyServiceTestApplication.java and TestConfiguration.java
It seems, you forgot to annotate the class MyService with #Service.
With this annotation being made at that class, the Spring framework will recognize it:
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
Given that the rest of the configuration is working, the #Autowired dependency injection mechanism will hereby provide you with an instance of the #Repository you requested, at runtime, here your test setup.

Java +Vaadin +Spring Security

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
}
}

Java Spring declare bean in service class

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

#autowired Did not work in Spring MVC

I developed a basic app containing 2 projects. First one is data layer and the second is a web app (mvc project)
data layer contains the following
#Entity
#Table(name="users")
public class User implements Serializable {
.....
}
public interface UserBase {
.....
}
#Repository
public interface UserRepository extends JpaRepository <User, Long>{
}
#Service
public class UserImpl implements UserBase {
private final UserRepository repository;
#Autowired
public UserImpl(UserRepository repository) {
this.repository = repository;
......
}
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("Config/applicationContext.xml")
public class testcase1 {
#Autowired
private UserImpl userImpl;
#Test
public void test() {
.....
UserImpl.save(user);
.....
}
web app
#Controller
public class ManageUser {
#Autowired
UserImpl userImpl;
#RequestMapping("/addUser/")
public ModelAndView addUser() {
UserImpl.save(user);
.....
}
}
When I run the unit test the code succeeded and no error found.
But when I put the output jar from data layer into the spring mvc web app the lib folder and added reference to the data layer in the build bath , I have an error message
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.my.domin.impl.UserImpl
Note:
I use tomcat.
I use the flowing config:
<jpa:repositories base-package="com.sanatech.repository" />
<context:component-scan base-package="com.my.repository"/>
<context:component-scan base-package="com.my.domin.impl"/>
<context:component-scan base-package="com.my.domin"/>
<context:component-scan base-package="com.my"/>
<context:component-scan base-package="com.my.manageuser.controller"/>
<tx:annotation-driven/>
<context:annotation-config />
Edit
when I separated the unit test to a new project and added reference to the data layer jar in the build bath I found the same exception.
Are you sure this exception is't raised from your testcase:
public class testcase1 {
#Autowired
private UserImpl userImpl;
You can explicitly set bean name in #Service annotation and use this name in #Autowired to make sure of correct configuration.

Categories

Resources