Unable to create JPA/CRUDRepository bean - java

I am creating first-time spring rest services with Spring Data JPA.
and getting below error.
APPLICATION FAILED TO START
Description:
Field product_repo in com.example.demo.controller.AddProduct required a bean of type 'com.example.demo.repository.ProductRepositroy' 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.example.demo.repository.ProductRepositroy' in your configuration.
My class and interfaces are :
Controller
#RestController
public class AddProduct {
#Autowired
private ProductRepositroy product_repo;
#GetMapping("/add")
public String addproduct() {
Product p1 = new Product();
p1.setId(1);
p1.setName("Amit");
Product p2 = new Product();
p1.setId(2);
p1.setName("Sumit");
product_repo.save(p1);
product_repo.save(p2);
return "added successfully the recod";
}
}
Entity
#Entity
public class Product {
#Id
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Repository
public interface ProductRepositroy extends CrudRepository<Product, Integer> {
}
Application Test
#SpringBootApplication
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}

Add #Repository annotation on ProductRepositroy interface. Also instead of extending CrudRepository extend JpaRepository.

You should use #Repository in the repository to register this class in the bean.
Code should be something like this.
#Repository
public interface ProductRepositroy extends CrudRepository<Product, Integer> {
}
happy coding! :)

Related

Parameter 0 of constructor in .... Spring Boot

I am a fish in Spring Boot and Data Jpa, I Tried to create a basic Spring boot application but every time I am encountering the error. Can you help me?
That's my code:
Spring Boot Application class:
#SpringBootApplication
#ComponentScan(basePackages = "com.project.*")
#EnableJpaRepositories(basePackages = "com.project.repository.*")
#EntityScan(basePackages = "com.project.entities.*")
#EnableAutoConfiguration
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
Controller Class:
#RestController
#RequestMapping(value = "/api")
public class controller {
private IUserServices userServices;
#Autowired
public controller(IUserServices userServices) {
this.userServices = userServices;
}
#GetMapping(value = "/merhaba")
public String sayHello(){
return "Hello World";
}
#GetMapping(value = "/getall")
public List<User> getAll(){
return this.userServices.getAllUsers();
}
}
Repository Class:
#Repository
public interface UserRepository extends JpaRepository<User,Long> {
}
IServices Class:
#Service
public interface IUserServices {
void saveUser(User user);
List<User> getAllUsers();
}
ServicesImpl Class:
#Service
public class UserServicesImpl implements IUserServices{
private UserRepository userRepository;
#Autowired
public UserServicesImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public void saveUser(User user) {
this.userRepository.save(user);
}
#Override
public List<User> getAllUsers() {
return this.userRepository.findAll();
}
}
Entity Class:
#Entity
#Table(catalog = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
AND THIS MY ERROR MESSAGE:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.project.services.UserServicesImpl required a bean of
type 'com.project.repository.UserRepository' that could not be found.
Action:
Consider defining a bean of type 'com.project.repository.UserRepository' in your
configuration.
Process finished with exit code 0
SO This is application properties file:
spring.jpa.properties.hibernate.dialect =
org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/u
spring.datasource.username=postgres
spring.datasource.password=1234
spring.jpa.properties.javax.persistence.validation.mode = none
There are some issues that you should fix them.
First
When you have the spring boot application with #SpringBootApplication you don't need other stuff such as #EnableAutoConfiguration and etc, So remove them all.
You can read more about it here.
Second
You don't need to annotate your service interface with #Service, because you did it in the UserServicesImpl class.
Third
You defined id as an integer in your user entity but in the repository, you wrote your id as Long. It's wrong. It should be something like this.
#Repository
public interface UserRepository extends JpaRepository<User,Integer> {
}
Try the above solutions and let me know the result.

Spring Boot Application- Ambiguous mapping Cannot map method

i am creating a simple spring boot project when i run the project ran into the problem with Spring Boot Ambiguous mapping. Cannot map method. i have create two various controller those are student and course controller.i completly attached the error below.
i attached the full
**gub link here** https://github.com/raguram1986/SpringSecuritys
Full Error i attached below
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'studentController' method
com.example.studentmanagement.Controller.StudentController#saveStudent(Student)
to {POST [/save]}: There is already 'courseController' bean method
com.example.studentmanagement.Controller.CourseController#saveCourse(Course) mapped.
Controller
#Controller
public class StudentController {
#Autowired
private StudentService service;
#GetMapping("/Student")
public String viewHomePage(Model model) {
List<Student> liststudent = service.listAll();
// model.addAttribute("liststudent", liststudent);
System.out.print("Get / ");
return "Student";
}
#GetMapping("/addStudent")
public String add(Model model) {
List<Student> liststudent = service.listAll();
model.addAttribute("liststudent", liststudent);
model.addAttribute("student", new Student());
return "addstudent";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String saveStudent(#ModelAttribute("student") Student std) {
service.save(std);
return "Student";
}
#RequestMapping("/edit/{id}")
public ModelAndView showEditStudentPage(#PathVariable(name = "id") int id) {
ModelAndView mav = new ModelAndView("addstudent");
Student std = service.get(id);
mav.addObject("student", std);
return mav;
}
#RequestMapping("/delete/{id}")
public String deleteStudentPage(#PathVariable(name = "id") int id) {
service.delete(id);
return "Student";
}
Student
#Entity
public class Student {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String stname;
private String course;
private int fee;
public Student() {
}
public Student(Long id, String stname, String course, int fee) {
this.id = id;
this.stname = stname;
this.course = course;
this.fee = fee;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStname() {
return stname;
}
public void setStname(String stname) {
this.stname = stname;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public int getFee() {
return fee;
}
public void setFee(int fee) {
this.fee = fee;
}
StudentRepository
#Repository
public interface StudentRepository extends JpaRepository<Student, Long>{
}
Service
#Service
public class StudentService
{
#Autowired
private StudentRepository repo;
public List<Student> listAll() {
return repo.findAll();
}
public void save(Student std) {
repo.save(std);
}
public Student get(long id) {
return repo.findById(id).get();
}
public void delete(long id) {
repo.deleteById(id);
}
}
In your StudentController you have the endpoint /save
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String saveStudent(#ModelAttribute("student") Student std) {
service.save(std);
return "Student";
}
But you haven't included the CourseController class in your question, which is mentioned in the error.
If you have defined an endpoint /save in that CourseController, then you have to rename it. Otherwise, when you invoke /save which controller needs to be invoked cannot be determined.
Add #RequestMapping above StudentController as below
#Controller
#RequestMapping("/students")
public class StudentController {
...
}
You are getting exception because there is already a mapping defined for path
/save
without being any controller mapping, so the first with root mapping is considered, but the next time it encounters same mapping it is already registered hence it is complaining. For clarity i'd suggest to add #RequestMapping to CourseController as well.
So now your course controller also becomes:
#Controller
#RequestMapping("/courses")
public class CourseController {
...
}
The best practice is to always add a request mapping at class level as well, like in your case, add a mapping like "/students" for SutdentController and "/course" for CourseController itself and then all other methods will be under that i.e. "/student/save" and then you will not face this issue anymore.

Am I missing something if I use my entity class without #Id in Spring Data JDBC?

I am new to spring.
I just tried successfully using an entity class without #Id in Spring Data JDBC
Custom query was added in my repository for retrieving data from 2 mysql tables and returning an entity having the joined table data.
If I plan to use only custom queries, am I missing anything here?
Here's my entity class without #Id or #Entity:
public class Item
{
private long id;
private String code;
private String itemName;
private String groupName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
}
Repository layer:
#Repository
public interface ItemRepository extends PagingAndSortingRepository<Item, Long>
{
#Query("SELECT a.id, a.code, a.name AS item_name,
b.name as group_name from item a, item_group b
WHERE a.group_id = b.id AND a.id=:id")
Item findItemById(#Param("id") Long id);
}
Service layer:
#Service
public class ItemServiceImpl implements ItemService
{
private final ItemRepository itemRepository;
public ItemServiceImpl(ItemRepository itemRepository)
{
this.itemRepository = itemRepository;
}
#Override
#Transactional(readOnly=true)
public Item findItemById(Long id)
{
return itemRepository.findItemById(id);
}
}
My updated main Configuration class in response to answer of Jens:
#SpringBootApplication
#EnableJdbcRepositories
public class SpringDataJdbcApplication extends AbstractJdbcConfiguration
{
public static void main(String[] args)
{
SpringApplication.run(SpringDataJdbcApplication.class, args);
}
#Bean
#ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource()
{
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
return dataSourceBuilder.build();
}
#Bean
NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource)
{
return new NamedParameterJdbcTemplate(dataSource);
}
#Bean
PlatformTransactionManager transactionManager()
{
return new DataSourceTransactionManager(dataSource());
}
}
If you don't get any exceptions you should be fine. There shouldn't be anything in Spring Data JDBC that silently breaks when the id is not specified.
The problem is though: I don't consider it a feature that this works, but just accidental behaviour. This means it might break with any version, although replacing these methods with custom implementations based on a NamedParameterJdbcTemplate shouldn't be to hard, so the risk is limited.
The question though is: Why don't you add the #Id annotation, after all your entity does have an id. And the whole idea of a repository conceptually requires an id.
If it's working and you really don't want to use the annotations, you can do it. But I think that it's unnecessary complication. You can expect errors that would not be there if you had used the annotations and code will be harder to debug. If you are new in Spring I recommend to use annotations. But after all it depend on you how will you design your applications. For sure advantage of approach without annotations is higher control about database.

How to write Junit test cases for spring boot application?

I have to write some junit test cases to check entity. I'm using postgres as my database.
My entity class
#Entity
#Table(name = "display")
public class Display {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String group;
public Display() {
}
public Display(Long id, String title, String grp) {
this.id = id;
this.title= title;
this.group= grp;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return this.id;
}
public void setGroup(String id) {
this.group = id;
}
public String getGroup() {
return this.group;
}
public void settitle(String title) {
this.title = title;
}
public String gettitle() {
return this.title;
}
}
My repository
#Repository
public interface DisplayRepository extends CrudRepository<Display, Long> {
}
Interface
public interface IDisplayService {
List<Display> findAll();
}
Service class
#Service
public class DisplayService implements IDisplayService {
#Autowired
private DisplayRepository repository;
#Override
public List<Display> findAll() {
List<Display> d = (List<Display>) repository.findAll();
return d;
}
}
I tried writing junit test cases but I get Could'nt load Application. Whats the right way to write junit test cases for this?
This is the test case I wrote for service
folder : test/java/example/demo/Test.java
#RunWith(MockitoJUnitRunner.class)
#TestPropertySource("classpath:conn.properties")
public class DisplayServiceTest {
#Value("${id}")
private String value;
#Mock
private DisplayRepository DisplayReps;
#InjectMocks
private DisplayService DisplayService;
#Test
public void whenFindAll_thenReturnProductList() {
Menu m = new Menu()
m.setId(value);
List<Display> expectedDisplay = Arrays.asList(m);
doReturn(expectedDisplay).when(DisplayReps).findAll();
List<Display> actualDisplay = DisplayService.findAll();
assertThat(actualDisplay).isEqualTo(expectedDisplay);
}
in test/java/example/demo/resources
conn.properties
id=2
Its returning 0 for value
Whats the issue?
Thanks
I have managed to make your code to work. I will post only the changed classes:
The interface:
public interface DisplayRepository extends CrudRepository<Display, Long> {
Optional<Display> findByTitle(String name);
}
The test class:
#RunWith(SpringRunner.class)
#AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
#DataJpaTest
public class DisplayRepositoryTest {
#Autowired
private TestEntityManager testEntityManager;
#Autowired
private DisplayRepository productRespository;
#Before()
public void setUp(){
Display m = new Display();
// m.setId(2L); // The ID is autogenerated; can retrieve it from the persistAndFlush result
m.setCategory("Group1");
m.setTitle("Product2");
testEntityManager.persistAndFlush(m);
}
#Test
public void whenFindByName_thenReturnProduct() {
// when
Display product = productRespository.findByTitle("Product2").orElseThrow(() -> new RuntimeException("Product not found"));
// then
assertThat(product.getTitle()).isEqualTo("Product2");
}
#Test
public void whenFindAll_thenReturnProductList() {
// when
List<Display> products = (List<Display>) productRespository.findAll();
// then
assertThat(products).hasSize(1);
}
}
When trying to run the code you provided, there were a few issues:
you were using the reserved word group as a field in the Display class. Because of this, Hibernate couldn't create the table, so I renamed it to category.
there was a compilation issue because the method findByName wasn't defined in the repository; also, there was no field name in the Display class to which the mapping to be made; because of this, I've added the method findByTitle because it's an existing field and it seemed to match the value you queried in the test method.
because the ID field is autogenerated, the test setup() failed when persisting the Display.
If you want to use #Mock for mocking classes, you must call:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
You can then mock responses as usual: Mockito.when(DisplayReps.findByTitle("A")).thenReturn(Optional.of(new Display(2L, "ALFA", "GRP1")));

Repository related methods return only null values

I have a Spring Boot application in which I have created an entity, a repository and a service.
I save entities in the database via transactions and everything works fine, my database is populated as I would expect. Also, I should mention that my database is created in PHPMyAdmin.
I also created a repository in order to fetch some data from the database by extending the Crud Repository. I also have a service which stores the methods that call the repository.
Though, none of the methods I have return anything ( my database is not empty ) and I do not know why. I have also tried adding #EnableJpaRepositories and #ComponentScan for the entity, but this did not work. Below are my classes:
The entity ( I will not put all the getters and setters here) :
#Entity
#Table(name = "matches", schema = "tennis", catalog = "")
public class MatchesEntity {
private int id;
private String namePlayer1;
private String namePlayer2;
private int setsPlayer1;
private int setsPlayer2;
private String odd1;
private String odd2;
private String competition;
private String surface;
private String status;
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "Name_player1")
public String getNamePlayer1() {
return namePlayer1;
}
public void setNamePlayer1(String namePlayer1) {
this.namePlayer1 = namePlayer1;
}
#Basic
#Column(name = "Name_player2")
public String getNamePlayer2() {
return namePlayer2;
}
// other getter & setters
}
The repository:
#Repository
public interface MatchesRepository extends CrudRepository<MatchesEntity,
Integer> {
List<MatchesEntity> getAllBySurface(String surface);
}
The service:
#Service
public class MatchesService {
#Autowired
MatchesRepository matchesRepository;
public int countMatchesOnHard() {
return matchesRepository.getAllBySurface("hard").size();
}
public MatchesEntity findMatchById() {
return matchesRepository.findById(2378).get();
}
}
The main class:
#SpringBootApplication
#EnableJpaRepositories(basePackageClasses={MatchesRepository.class})
#EntityScan(basePackageClasses=MatchesEntity.class)
public class PicksApplication {
#Autowired
static MatchesService matchesService;
public static void main(String[] args) {
MatchesEntity matchesEntity = matchesService.findMatchById();
int numberOfMatchesOnHard = matchesService.countMatchesOnHard();
System.out.println(numberOfMatchesOnHard);
}
}
Any method I try which is repository related returns null.
Can anyone help me with a suggestion ?
Your main class PicksApplication is troublesome. The main method must trigger SpringApplication.run for the spring boot to initialize itself & the context for autowires to work. You are breaking all that within your code. You can utilize CommandLineRunner and add your code in run() method.
Like this;
#SpringBootApplication
public class PicksApplication implements CommandLineRunner {
#Autowired
private MatchesService matchesService;
public static void main(String[] args) {
SpringApplication.run(PicksApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
MatchesEntity matchesEntity = matchesService.findMatchById();
int numberOfMatchesOnHard = matchesService.countMatchesOnHard();
System.out.println(numberOfMatchesOnHard);
}
}
then it ought to work, rest of the code looks OK

Categories

Resources