I have a repository, annotated with #Repository
package com.jeppa.interfaces;
import com.jeppa.entities.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends CrudRepository<User, String> {
User findByUserEmailIgnoreCase(String useremail);
}
Part of my controller:
package com.jeppa.controllers;
import com.jeppa.entities.ConfirmationToken;
import com.jeppa.entities.User;
import com.jeppa.interfaces.TokenRepository;
import com.jeppa.interfaces.UserRepository;
import com.jeppa.mail.EmailSenderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class UserAccountController {
#Autowired
private UserRepository userRepository;
#Autowired
private TokenRepository tokenRepository;
#Autowired
private EmailSenderService emailSenderService;
#RequestMapping(value = "/register", method = RequestMethod.GET)
public ModelAndView displayRegistration(ModelAndView modelAndView, User user){
modelAndView.addObject("user", user);
modelAndView.setViewName("register");
return modelAndView;
}
//////////////
And, finnaly, my #SpringBootApplication:
package com.jeppa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class RunApplication {
public static void main(String[] args) {
SpringApplication.run(RunApplication.class, args);
}
}
and i keep getting this error
*************************** APPLICATION FAILED TO START
Description:
Field userRepository in com.jeppa.controllers.UserAccountController
required a bean of type 'com.jeppa.interfaces.UserRepository' that
could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.jeppa.interfaces.UserRepository'
in your configuration.
what am i doing wrong? here's my project structure:
structure
With Spring Boot, you should generally rely on Spring Boot starters to autoconfigure your dependencies. In case of Spring Data add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
into your pom file to autoconfigure Spring Data instead of directly relying on Spring Data (spring-data-jpa), which requires further manual configuration.
Also don't forget to add and configure an actual implementation as well (h2, jdbc, etc.)
Related
Basically, I have created all of the pojo and layers(including the repository layer) necessary for Spring Boot to automatically implement MySql commands. When I trying to run the programme, I get the following command:
Description:
Parameter 0 of constructor in com.fsse2207.project_backend.api.ProductApi required a bean of type 'com.fsse2207.project_backend.service.ProductService' that could not be found.
Action:
Consider defining a bean of type 'com.fsse2207.project_backend.service.ProductService' in your configuration.
It turns out there's sth wrong about the bean in my ProductApi. It says "
Could not autowire. No beans of 'ProductService' type found." How do I fix it?
The following is the interface under the service layer:
package com.fsse2207.project_backend.service;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import org.springframework.stereotype.Service;
public interface ProductService {
ProductDetailData createProductData (ProductCreateData productCreateData) throws ProductFoundByIdException;
}
The following is the service class:
package com.fsse2207.project_backend.service.impl;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.data.entity.ProductEntity;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import com.fsse2207.project_backend.repository.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ProductServiceImpl {
private ProductRepository productRepository;
#Autowired
public ProductServiceImpl(ProductRepository productRepository){
this.productRepository=productRepository;
}
public ProductDetailData createProductData (ProductCreateData productCreateData) throws ProductFoundByIdException {
ProductEntity productEntity=new ProductEntity(productCreateData);
if(productRepository.existsById(productEntity.getpId())){
throw new ProductFoundByIdException();
}
return new ProductDetailData(productRepository.save(productEntity));
}
}
The following is the Api:
package com.fsse2207.project_backend.api;
import com.fsse2207.project_backend.data.ProductCreateData;
import com.fsse2207.project_backend.data.ProductDetailData;
import com.fsse2207.project_backend.data.dto.CreateRequestDto;
import com.fsse2207.project_backend.data.dto.CreateResponseDto;
import com.fsse2207.project_backend.exception.ProductFoundByIdException;
import com.fsse2207.project_backend.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ProductApi {
private ProductService productService;
#Autowired
public ProductApi(ProductService productService){
this.productService=productService;
}
#PostMapping
public CreateResponseDto createResponseDto(#RequestBody CreateRequestDto createRequestDto) throws ProductFoundByIdException {
ProductCreateData productCreateData=new ProductCreateData(createRequestDto);
ProductDetailData productDetailData =productService.createProductData(productCreateData);
return new CreateResponseDto(productDetailData);
}
}
I found the problem:
I didn't add the implements keyword in the class definition of ProductServiceImpl so it was not connected to the bean, aka the interface, aka the service layer.
First of all you should not add annotation #Service for ProductService interface.
Moreover this can happen when you have your Class Application in "another package".
You can solve the problem using annotation #ComponentScan (basePackages = {"your.company.domain.package"})
i'm a beginner and i'm testing springboot, creating a simple api.
When testing my post request via postman, it gives me a 404 error.
postman
package com.ecommerce.microcommerce;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan("com.ecommerce.microcommerce.repository")
public class MicrocommerceApplication {
public static void main(String[] args) {
SpringApplication.run(MicrocommerceApplication.class, args);
}
}
UserRepository :
package com.ecommerce.micocommerce.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ecommerce.microcommerce.model.User;
public interface UserRepository extends JpaRepository<User, Long> {
}
UserService :
package com.ecommerce.microcommerce.service;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ecommerce.micocommerce.repository.UserRepository;
import com.ecommerce.microcommerce.model.User;
#Service
#Transactional
public class UserService {
#Autowired
private UserRepository userRepository;
public void saveUser(User user) {
userRepository.save(user);
}
UserController :
package com.ecommerce.microcommerce.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ecommerce.microcommerce.model.User;
import com.ecommerce.microcommerce.service.UserService;
#RestController
public class UserController {
#Autowired
private UserService userService;
#PostMapping("/Users")
public void addUser(#RequestBody User user) {
System.out.println(user);
userService.saveUser(user);
}
}
application.properties :
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:8889/microcommerce?createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=root
#Hibernate
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
I noticed that since I added the #ComponentScan annotation, postman returns me a 404.
But I have to use this one because otherwise #Autowired does not work.
Thanks for your help.
Your #ComponentScan is not scanning your Controller neither your Service.
In fact, having it is not needed at all when using #SpringBootApplication. This should scan all packages that it's part of, in your case, com.ecommerce.microcommerce.
Perhaps your Repository has not been scanned/autowired because of a type on your package name?
micocommerce vs microcommerce.
tip: use constructor injection instead of autowiring
#RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// methods
}
Edit #ComponentScan("com.ecommerce.microcommerce.repository") to #ComponentScan("com.ecommerce.microcommerce) so that it scans Controller, Services and Repositories in your base package. Please check link how Springboot uses #SpringBootApplication annotation(as it already enables #ComponentScan feature):
Please do check the package name(micocommerce) you have provided for the UserRepository class.
I'm learning Spring: I've a simple JUnit test based on Spring, but I can't understand why one test is failing and the other not, since I'm expecting the #Autowired annotation to work in both of them
I have 2 classes:
package it.euphoria.data.service;
import it.euphoria.data.entity.Customer;
import it.euphoria.data.entity.Seller;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import javax.validation.constraints.NotNull;
import java.util.Set;
public interface CustomerRepository extends JpaRepository<Customer, Long> {
#Query("SELECT cust FROM Customer cust WHERE cust.seller = :seller")
Set<Customer> getBySeller(#NotNull #Param("seller") Seller seller);
}
and a Service class:
package it.euphoria.data.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CustomerService {
private CustomerRepository customerRepository;
#Autowired
public CustomerService(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
public CustomerRepository getCustomerRepository() {
return customerRepository;
}
}
If , while testing, I autowire CustomerRepository it works fine, but if I autowire CustomerService I get an UnsatisfiedDependencyException
This is the working test with CustomerRepository:
package it.euphoria.data.service;
import it.euphoria.data.entity.Customer;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#DataJpaTest
public class CustomerRepositoryTest {
#Autowired
CustomerRepository customerRepository;
#Test
public void getBySeller() {
//test things...
}
}
And this is the broken one with CustomerService as only difference:
package it.euphoria.data.service;
import it.euphoria.data.entity.Customer;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#DataJpaTest
public class CustomerRepositoryTest {
#Autowired
CustomerService customerService; //<-- The error is here
#Test
public void getBySeller() {
//test things...
}
}
This is the stacktrace:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'it.euphoria.data.service.CustomerRepositoryTest': Unsatisfied
dependency expressed through field 'customerService'; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'it.euphoria.data.service.CustomerService'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
I've found this question and answer , but it didn't solve the problem.
Could you please help me understanding what I'm doing wrong here?
#DataJpaTest loads the beans which are relevant to the work with the database, read Repositories and more low level stuff (DataSources, Transaction manager, etc).
These tests are used to check the correctness of your SQL queries and any code that resides in the DAO.
It doesn't load the whole application in any case but only a certain part of it.
Now the service is a place where you usually write a business logic and it doesn't interact with database directly (only via DAOs, repositories, etc.)
So spring doesn't load services in #DataJpaTest
This is the error which i am getting:
Description:
Field andiRepository in com.service.datafetcher.AllAndisDataFetcher required a bean of type 'com.repositories.AndiRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.repositories.AndiRepository' in your configuration.
This is the data fetcher file which is requiring a bean:
import com.models.Andi;
import com.repositories.AndiRepository;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
#Component
public class AllAndisDataFetcher implements DataFetcher<List<Andi>> {
#Autowired
AndiRepository andiRepository;
#Override
public List<Andi> get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception {
return andiRepository.findAll();
}
}
this is the main method which resides in "com".
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#ComponentScan("com.repositories")//to scan repository files
#EntityScan("com.models")
#EnableJpaRepositories("com.repositories.AndiRepository")
public class DynamoDBApplication {
public static void main(String[] args) {
SpringApplication.run(DynamoDBApplication.class, args);
}
}
The models, repositories, service, packages are inside the main com package.
This is the repository file:
package com.repositories;
import com.andiskillsmaxmodels.Andi;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface AndiRepository extends CrudRepository<Andi, Integer> {
}
Thank you
Correct your package names. They're all over the place. You have imported classes from different packages it seems. Make sure that AndiRepository is in the com.repositories package. And Andi class in your com.models package. After correcting these mistakes do the following.
Remove #ComponentScan("com.repositories"). You don't need this, since #SpringBootApplicationautomatically does it for you.
And replace #SpringBootApplication with #SpringBootApplication(scanBasePackages = "com")
I am working on Spring and hibernate project. For database communication we have conventional two layered implementation (i.e DAO layer and Service layer). I have following files:
DemoDao.java
package net.dao;
import java.util.List;
import net.domain.Demo;
public interface DemoDao
{
public List<Demo> get();
}
DemoDaoImpl.java
package net.dao;
import java.util.List;
import net.domain.Demo;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
#Repository
public class DemoDaoImpl implements DemoDao
{
#Autowired
SessionFactory sessionFactory;
public List<Demo> get()
{
Session session=sessionFactory.openSession();
List<Demo> list=session.createQuery("from Demo").list();
session.close();
return list;
}
}
That was DAO layer
Follwing is from service layer:
DemoManager.java
package net.service;
import java.util.List;
import net.domain.Demo;
public interface DemoManager
{
public List<Demo> get();
}
DemoManagerImpl.java
package net.service;
import java.util.List;
import net.dao.DemoDao;
import net.domain.Demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class DemoManagerImpl implements DemoManager
{
#Autowired
DemoDao demoDao;
public List<Demo> get()
{
List<Demo> list=demoDao.get();
return list;
}
}
Follwing is my controller
FromDualLayerView.java
package net.spring;
import java.util.List;
import net.domain.Demo;
import net.service.DemoManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class FromDualLayerView
{
#Autowired
DemoManager demoManager;
#RequestMapping("/dualLayer")
public ModelAndView toResult(ModelMap map)
{
List<Demo> list=demoManager.get();
map.addAttribute("listData", list);
return new ModelAndView("result");
}
}
My Question
Actually everything works fine, but my question over here is that i am not annotating the DemoDao and DemoManager interface, but i am autowiring them. According to the autowiring definition the entities which are annotated are injected.
The how come the dependency is injected by Spring container?
And how does it work like an Impl class?
Thanks in advance.
DemoManagerImpl is annotated as a service and is the only qualifying bean to be injected in the FromDualLayerView class, as it's the only component which is instance of DemoManager. I suppose you have the component scan turned on as well.
The #Repository annotation and the #Service annotation mean you are annotating them. It's actually a spring best practice to annotate the implementations and not the interfaces.
Your spring config file is scanning the classpath, thus those beans are detected. Turn spring logging up to TRACE and you'll probably see output along the lines of:
"scanning classpath, found target DemoDaoImpl"