I'm new to REST APIs and Spring Boot. I have been trying to create the REST APIs using STS and MySQL that stores Employees data.
Everything seems fine but when I POST the data in Postman, empty rows are storing in the MySQL and body.
Somebody please help me.
//My employee class in the model
package com.example.SpringBootApplicationProject.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
//We need to make this simple Employee class to JPA annotation
#Data
#Entity
#Table(name="employees")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
#Column(name = "salary")
private long salary;
}
//Employee Controller Class
package com.example.SpringBootApplicationProject.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.SpringBootApplicationProject.model.Employee;
import com.example.SpringBootApplicationProject.service.EmployeeService;
#RestController
#RequestMapping("/api/employees")
public class EmployeeController {
private EmployeeService employeeService;
public EmployeeController(EmployeeService employeeService) {
super();
this.employeeService = employeeService;
}
//Build employee REST API
#PostMapping
public ResponseEntity<Employee> saveEmployee(#RequestBody Employee employee){
return new ResponseEntity<Employee>(employeeService.saveEmployee(employee), HttpStatus.CREATED);
}
}
//Employee Repository class
package com.example.SpringBootApplicationProject.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.SpringBootApplicationProject.model.Employee;
//This is an interface.
//JPA repository automatically provides #Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long>{
//public interface EmployeeRepository extends JpaRepository<Employee, Long>{
//Employee save(Employee employee);
}
//Employee Service Class
package com.example.SpringBootApplicationProject.service;
import com.example.SpringBootApplicationProject.model.Employee;
public interface EmployeeService
{
Employee saveEmployee(Employee employee);
}
//Employee Service Impl
package com.example.SpringBootApplicationProject.service.impl;
import org.springframework.stereotype.Service;
import com.example.SpringBootApplicationProject.model.Employee;
import com.example.SpringBootApplicationProject.repository.EmployeeRepository;
import com.example.SpringBootApplicationProject.service.EmployeeService;
#Service
public class EmployeeServiceImpl implements EmployeeService{
private EmployeeRepository employeeRepository;
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
super();
this.employeeRepository = employeeRepository;
}
#Override
public Employee saveEmployee(Employee employee) {
return employeeRepository.save(employee);
}
}
Postman blank data[MySQL Empty DB][1]
Related
Hey I am pretty new to using the Spring Framework and was just trying to get an application to work for practice but I am getting the following error in my stack trace:
Cannot invoke "com.gabriel.schoolapp.repository.UsersRepo.findAll()" because "this.usersRepo" is null
This is my model layer for the Users:
package com.gabriel.schoolapp.models;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#ToString
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer usersID;
#Column(nullable = false)
private String firstName;
public void FirstName(String firstName){
this.firstName = firstName;
}
#Column(nullable = false)
private String lastName;
public void ClassDesc(String lastName){
this.lastName = lastName;
}
#Column(nullable = false)
private String username;
public void Username(String username){
this.username = username;
}
}
This is my repository layer:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.gabriel.schoolapp.models.Users;
#Repository
public interface UsersRepo extends JpaRepository<Users, Integer>{
Users findByUsername(String firstName);
}
And this is my service layer:
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.gabriel.schoolapp.models.Users;
import com.gabriel.schoolapp.repository.UsersRepo;
#Service
public class UsersService {
#Autowired
private UsersRepo usersRepo;
#Autowired
public UsersService(UsersRepo usersRepo){
this.usersRepo = usersRepo;
}
public UsersService(){
}
public Users createUser(Users user){
Users checkIfUserInDb = usersRepo.findByUsername(user.getFirstName());
if(checkIfUserInDb != null){
System.out.println("Username already in DB");
return null;
}
System.out.println("User is valid");
return usersRepo.save(user);
}
public List<Users> getAllUsersById(){
return this.usersRepo.findAll();
}
}
Whenever I try to call a method from the service layer like so:
#SpringBootApplication
public class SchoolAppApplication {
public static void main(String[] args) {
SpringApplication.run(SchoolAppApplication.class, args);
UsersService serv = new UsersService();
serv.getAllUsersById();
}
}
It returns with the aforementioned error (this.usersRepo is null)
Any help would be greatly appreciated thank you!!
The UserService you created is not managed by Spring, hence the repo is not autowired. You need a few things:
implement CommandLineRunner in SchoolAppApplication
Autowire your service in SchoolAppApplication
Override method run in SchoolAppApplication and run your service there:
#Override
public void run(String... args) {
serv.getAllUsersById();
}
I read many people asked the same question but I have followed all the rules, and I don't know what am I missing
I have following:
Main
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Model
package com.example.demo.model;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
#Entity
#Table(name = "ivsd_account")
public class Account implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "acc_id")
private Long accId;
#Column(name = "acc_uid", unique = true, nullable = false)
private String accUid;
#Column(name = "acc_created_by_acc_uid")
private String accCreatedByAccUid;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "acc_created_date")
private Date accCreatedDate;
#Column(name = "acc_updated_by_acc_uid")
private String accUpdatedByAccUid;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "acc_updated_date")
private Date accUpdatedDate;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "acc_sync_tst")
private Date accSyncTst;
#Column(name = "acc_enabled")
private Boolean accEnabled;
#Column(name = "acc_name")
private String accName;
#Column(name = "acc_email")
private String accEmail;
#Column(name = "acc_username")
private String accUsername;
#Column(name = "acc_password")
private String accPassword;
getters and setters
DTO
package com.example.demo.dto;
import com.example.demo.model.Account;
import java.util.Date;
public class AccountDTO {
private Long accId;
private String accUid;
private String accCreatedByAccUid;
private Date accCreatedDate;
private String accUpdatedByAccUid;
private Date accUpdatedDate;
private Date accSyncTst;
private Boolean accEnabled;
private String accName;
private String accEmail;
private String accUsername;
private String accPassword;
getters and setters
Repository
package com.example.demo.repository;
import com.example.demo.model.Account;
import org.springframework.stereotype.Repository;
#Repository
public interface AccountRepository extends CustomRepository<Account, Long> {
Account findOneByAccName(String name);
Account findByAccUid(String uid);
Account findByAccEmail(String email);
void deleteAccountByAccUid(String uid);
}
Service
package com.example.demo.service;
import com.example.demo.dto.AccountDTO;
import com.example.demo.mapper.AccountMapper;
import com.example.demo.model.Account;
import com.example.demo.repository.AccountRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
#Service
public class AccountService {
#Autowired
private AccountRepository accountRepository;
#Autowired
private AccountMapper accountMapper; // Could not autowire. No beans of AccountMapper type found
#Transactional(readOnly = true)
public List<AccountDTO> loadAll() {
List<Account> res = accountRepository.findAll();
List<AccountDTO> resF = accountMapper.entitiesToDto(res);
return resF;
}
Controller
package com.example.demo.controller;
import com.example.demo.service.AccountService;
import com.example.demo.dto.AccountDTO;
import com.example.demo.system.ResponseWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping("/api")
public class AccountController {
#Autowired
private AccountService accountService;
#RequestMapping(value = "/accounts", method = RequestMethod.GET)
public ResponseEntity<?> loadAll() {
List<AccountDTO> res = accountService.loadAll();
return new ResponseEntity(new ResponseWrapper(res), HttpStatus.OK);
}
Mapper
package com.example.demo.mapper;
import com.example.demo.dto.AccountDTO;
import com.example.demo.model.Account;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.ReportingPolicy;
import java.util.List;
#Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring")
public interface AccountMapper {
AccountDTO entityToDto(Account entity);
Account dtoToEntity(AccountDTO entity);
Account updateEntityFromDto(AccountDTO dto, #MappingTarget Account entity);
List<AccountDTO> entitiesToDto(List<Account> entities);
}
I get an error in Service:
Field accountMapper in com.example.demo.service.AccountService required a bean of type 'com.example.demo.mapper.AccountMapper' that could not be found.
I have placed all the classes in sub packages of the package from Main class.
If I add annotation #ComponentScan("com.example.demo.mapper") then it works only for mapper package, other packages are not scanned. Sorry for stupid question. Any help I appreciate
Thank you
Check if you have properly configured mapstruct.
Run a mvn clean install before starting the application, mapstruct will generate the mapper class that will be annotated with #Component.
I am relatively new to development and to spring framework.
What I want to do is to create a small project where I have a company that has lines, which has projects, which has employees. Also, I am using a Neo4J docker image to save all these objects.
This is my project structure.
These are my nodes, Employee, Line, Project, respectively.
package com.thebman.neo4jstudy.node;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Relationship;
#Data
#AllArgsConstructor
#NoArgsConstructor
#NodeEntity
public class Employee {
#Id
#GeneratedValue
private Long Id;
private String name;
private int age;
}
package com.thebman.neo4jstudy.node;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Relationship;
import java.util.Set;
#Data
#AllArgsConstructor
#NoArgsConstructor
#NodeEntity
public class Line {
private String name;
#Id
#GeneratedValue
private long id;
#Relationship(type = "belongs_to", direction = Relationship.Direction.INCOMING)
private Set<Project> projectSet;
}
package com.thebman.neo4jstudy.node;
import com.sun.istack.internal.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Relationship;
import java.util.Set;
#Data
#AllArgsConstructor
#NoArgsConstructor
#NodeEntity
public class Project {
#Id
#GeneratedValue
private Long entityId;
private String name;
private String location;
#Relationship(type = "works_for", direction = Relationship.Direction.INCOMING)
private Set<Employee> employee;
}
This is my controller class:
package com.thebman.neo4jstudy.controller;
import com.thebman.neo4jstudy.node.Line;
import com.thebman.neo4jstudy.node.Project;
import com.thebman.neo4jstudy.node.Employee;
import com.thebman.neo4jstudy.service.LineService;
import com.thebman.neo4jstudy.service.ProjectService;
import com.thebman.neo4jstudy.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
#RestController
#RequestMapping(value = "/api/company")
public class CompanyController {
#Autowired
private ProjectService projectService;
#Autowired
private PersonService personService;
#Autowired
private LineService lineService;
#PostMapping("/line/projects")
ResponseEntity saveProject(#RequestBody Project project) {
return new ResponseEntity(projectService.saveProject(project), HttpStatus.CREATED);
}
#GetMapping("/line/projects")
ResponseEntity getProjects() {
return new ResponseEntity(projectService.getProjects(), HttpStatus.OK);
}
#DeleteMapping("/line/projects/{project_name}")
ResponseEntity deleteProject(#PathVariable String project_name) {
projectService.deleteProject(project_name);
return new ResponseEntity(HttpStatus.OK);
}
#PostMapping("/line/projects/employee")
ResponseEntity saveEmployee(#RequestBody Employee employee) {
return new ResponseEntity(personService.savePerson(employee), HttpStatus.CREATED);
}
#PostMapping("/line")
ResponseEntity saveLine(#RequestBody Line line) {
return new ResponseEntity( lineService.saveLine(line), HttpStatus.CREATED);
}
}
What I want to do is to add employee to {project} with POST request where the endpoint is "/line/projects/{project_name}/employee". However, I really don't know how to do this. One idea of mine is to call a ProjectService instance and add the employee to that project with add method of a Set, but I cannot use
#Autowired
private Project project;
inside ProjectService class. When I do that I get error.
How can I achieve what I want to do?
Any help is appreciated.
best,
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Hello Friends i am creating an Library Management application with Thymeleaf, i already mapped the relations and created some relations, and the Many to Many ones are working, for example you will register a Book(Only the name), then it will have a link named details where you will be able to complete the register and select the Authors and Themes, both are Many to Many relation and its working
Book Register Details shows one created book
Now my problem is in the Many to One relationship, it works the same way, you will create a Library, then in Details you will be able to add Books to that library
And in the project that i am creating One Library can have multiple Books, but one Book can be in one Library Only, its unique to that library, when i try to add the book and submit i get an Error saying:
No value present
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:141)
And i am trying to solve this for a couple hours, and my guess is that the controller are not able to find the Book id, but i dont have idea why...
Here is my code above:
Ps: i know i have work to do, create the DTOs and make cleaner, i just want to make it work first
Library COntroller here is where i am trying to add the created book in the ediLib method
package com.msoftwares.librarymanager.controller;
import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Entities.Library;
import com.msoftwares.librarymanager.models.Repo.LibraryRepository;
import com.msoftwares.librarymanager.models.Services.BookService;
import com.msoftwares.librarymanager.models.Services.LibraryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import java.util.List;
#RestController
#RequestMapping(path ="/api/library")
public class LibraryController {
#Autowired
LibraryService libraryService;
#Autowired
BookService bookService;
#GetMapping(path = "/all")
public ModelAndView getLibraries(){
ModelAndView modelAndView = new ModelAndView("libraryTemplate");
modelAndView.addObject("newLibrary", new Library());
modelAndView.addObject("getLibraries", libraryService.getLibrary());
return modelAndView;
}
#GetMapping(path = "/details/{id}")
public ModelAndView getDetails(#PathVariable("id") Integer id){
Library library = libraryService.findLibById(id);
ModelAndView modelAndView = new ModelAndView("libraryEdit");
modelAndView.addObject("library", library );
List<Book> unselectedBooks = bookService.getBooks();
unselectedBooks.removeAll(library.getBook());
modelAndView.addObject("availableBooks", unselectedBooks);
return modelAndView;
}
#PostMapping(path = "/editLib")
public RedirectView editLib(#ModelAttribute Book book, #RequestParam Integer libId){
Library library = libraryService.findLibById(libId);
book = bookService.getBookById(book.getIsbn());
libraryService.saveLibrary(library);
return new RedirectView("http://localhost:8080/api/library/details/" + libId);
}
#PostMapping(path = "/create")
public RedirectView createLibrary(#ModelAttribute Library library){
libraryService.saveLibrary(library);
return new RedirectView("http://localhost:8080/api/library/all");
}
}
Book Controller
package com.msoftwares.librarymanager.controller;
import com.msoftwares.librarymanager.models.Entities.Author;
import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Entities.BookTheme;
import com.msoftwares.librarymanager.models.Entities.Library;
import com.msoftwares.librarymanager.models.Repo.AuthorRepository;
import com.msoftwares.librarymanager.models.Repo.BookRepository;
import com.msoftwares.librarymanager.models.Repo.BookThemeRepository;
import com.msoftwares.librarymanager.models.Repo.LibraryRepository;
import com.msoftwares.librarymanager.models.Services.AuthorService;
import com.msoftwares.librarymanager.models.Services.BookService;
import com.msoftwares.librarymanager.models.Services.BookThemeService;
import com.msoftwares.librarymanager.models.Services.LibraryService;
import org.dom4j.rule.Mode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import javax.swing.text.html.HTML;
import java.util.List;
#RestController
#RequestMapping(path ="/api/books")
public class BookController {
#Autowired
BookService bookService;
#Autowired
AuthorService authorService;
#Autowired
BookThemeService bookThemeService;
//get all books
#GetMapping(path = "/all")
public ModelAndView getBooks(){
ModelAndView modelAndView = new ModelAndView("booksTemplate");
modelAndView.addObject("newBook", new Book());
modelAndView.addObject("getAuthors", authorService.getAuthors());
modelAndView.addObject("getBooks", bookService.getBooks());
modelAndView.addObject("getThemes", bookThemeService.getThemes());
return modelAndView;
}
//create book
#PostMapping(path = "/create")
public RedirectView createBook(#ModelAttribute Book book) {
bookService.saveBook(book);
return new RedirectView("http://localhost:8080/api/books/all");
}
//get details
#GetMapping(path = "/details/{id}")
public ModelAndView getDetails(#PathVariable("id") Integer id){
Book book = bookService.getBookById(id);
ModelAndView modelAndView = new ModelAndView("bookDetails");
modelAndView.addObject("bookId", book);
List<Author> unselectedAuthors = authorService.getAuthors();
List<BookTheme> unselectedBookThemes = bookThemeService.getThemes();
unselectedAuthors.removeAll(book.getAuthors());
unselectedBookThemes.removeAll(book.getBookThemes());
modelAndView.addObject("authors", unselectedAuthors);
modelAndView.addObject("bookThemes", unselectedBookThemes);
return modelAndView;
}
//register authors
#PostMapping(path = "/registerDetails")
public RedirectView registerDetails(#ModelAttribute Author author, #RequestParam Integer isbn){
Book book = bookService.getBookById(isbn);
author = authorService.getAuthorById(author.getId());
book.getAuthors().add(author);
bookService.saveBook(book);
return new RedirectView("http://localhost:8080/api/books/details/" + isbn);
}
//register themes
#PostMapping(path = "/registerTheme")
public RedirectView registerThemes(#ModelAttribute BookTheme bookTheme, #RequestParam Integer isbn){
Book book = bookService.getBookById(isbn);
bookTheme = bookThemeService.getThemeById(bookTheme.getId());
book.getBookThemes().add(bookTheme);
bookService.saveBook(book);
return new RedirectView("http://localhost:8080/api/books/details/" + isbn);
}
}
Library Service
package com.msoftwares.librarymanager.models.Services;
import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Entities.Library;
import com.msoftwares.librarymanager.models.Repo.LibraryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class LibraryService {
#Autowired
LibraryRepository libraryRepository;
#Autowired
BookService bookService;
//get all
public List<Library> getLibrary(){return libraryRepository.findAll();}
//get by id
public Library findLibById(int id){return libraryRepository.findById(id).get();}
//save
public void saveLibrary(Library library){libraryRepository.save(library);}
//delete
public void deleteLibrary(Library library){libraryRepository.delete(library);}
}
Book Service (Where the finById method are)
package com.msoftwares.librarymanager.models.Services;
import com.msoftwares.librarymanager.models.Entities.Author;
import com.msoftwares.librarymanager.models.Entities.Book;
import com.msoftwares.librarymanager.models.Repo.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
#Service
public class BookService {
#Autowired
BookRepository bookRepository;
//get all books
public List<Book> getBooks(){
return bookRepository.findAll();
}
//save book
public void saveBook(Book book){
bookRepository.save(book);
}
//find books by id
public Book getBookById(int id){
return bookRepository.findById(id).get();
}
//delete
public void deleteBook(Book book){
bookRepository.delete(book);
}
}
Library Entity
package com.msoftwares.librarymanager.models.Entities;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Library {
public Library(String name, String address) {
this.name = name;
this.address = address;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int id;
#Column
private String name;
#Column
private String address;
#ManyToMany(fetch = FetchType.LAZY)
private List<Client> clients = new ArrayList<>();
#OneToMany
private List<Book> book = new ArrayList<>();
}
Book Entity
package com.msoftwares.librarymanager.models.Entities;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Book {
public Book(String title) {
this.title = title;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int isbn;
#Column
private String title;
#ManyToMany(fetch = FetchType.LAZY)
private List<Author> authors = new ArrayList<>();
#ManyToMany(fetch = FetchType.LAZY)
private List<BookTheme> bookThemes = new ArrayList<>();
#ManyToOne
private Library library;
}
I see that the findById method.get it came from an Optional interface where it checks if it have the value or not, but the id is on my DB, he just isnt able to find the id, i try to make the relation on Book Controller and it worked, but in the Library controller it doesnt.
You have to annotate Book Entity's library Object with #JoinColumn(name = "column_name_who_points_to_LibraryID") annotation. And also include mappedBy property in your Library Entity.
Book Entity
package com.msoftwares.librarymanager.models.Entities;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Book {
// Book constructor and other code
#ManyToOne
#JoinColumn(name = "library_id") // here library_id is a foreign key in Book table
private Library library;
}
Library Entity
package com.msoftwares.librarymanager.models.Entities;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Library {
// Library Constructor and other code
#OneToMany(mappedBy = "library") // this is a object name in Book Entity
private List<Book> book = new ArrayList<>();
}
I am new to Spring boot. I have a MYSQL table "customer" with data as shown:
Data in the table When testing the API output using Postman, there seems to be rows of empty JSON output.
API Output
Below is my code:
package com.semika.customer;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="address")
private String address;
public Customer() {
super();
}
}
CustomerRepository
package com.semika.customer;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long>{
}
CustomerService
package com.semika.customer;
public interface CustomerService {
public Iterable<Customer> findAll();
}
CustomerServiceImpl
package com.semika.customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CustomerServiceImpl implements CustomerService{
#Autowired
private CustomerRepository customerRepository;
public Iterable<Customer> findAll() {
return customerRepository.findAll();
}
}
CustomerController
package com.semika.customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class CustomerController {
#Autowired
private CustomerService customerService;
#RequestMapping("/customers")
#ResponseBody
public Iterable<Customer> findAll() {
Iterable<Customer> customers = customerService.findAll();
return customers;
}
}
I don't know what else I need to modify in the controller to be able to see the output with data.
At first look your code seems fine. So, I copied your code and try to run it and got an empty response just like you. After spending some time I figured out the reason why.
Use getter and setter in you customer class and recompile the code.
It will solve your problem. Also do the following changes:
1) Annotate CustomerRepository with #Repository
2) use #EnableJpaRepositories("package path") in your application's main class if your repository is not in the same or sub package.
3) use method type or #GetMapping annotation in your controller.
For your convenience I am writing your code after all the modifications:
TestDemoApplication.java
package testdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories("put repository path here")
public class TestDemoApplication {
public static void main(String[] args) {
SpringApplication.run(TestDemoApplication.class, args);
}
}
CustomerServiceImpl.java
package testdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CustomerServiceImpl implements CustomerService{
#Autowired
private CustomerRepository customerRepository;
public Iterable<Customer> findAll() {
return customerRepository.findAll();
}
}
CustomerService.java
package testdemo;
public interface CustomerService {
public Iterable<Customer> findAll();
}
CustomerRepository.java
package testdemo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CustomerRepository extends CrudRepository<Customer, Long>{
}
CustomerController.java
package testdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class CustomerController {
#Autowired
private CustomerService customerService;
#GetMapping(value = "/customers")
public Iterable<Customer> findAll() {
Iterable<Customer> customers = customerService.findAll();
return customers;
}
}
Customer.java
package testdemo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="address")
private String address;
public Customer() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
Also, CrudRepository returns a Iterable<> in findAll(). It is the JpaRepository which returns List<> so, no worries about it.
You may need to iterate over the dataset and add the results to a List or as Vishal stated, change your interfaces and implementations to return a List rather than an Iterable.
package com.semika.customer;
import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
#RestController
public class CustomerController {
#Autowired
private CustomerService customerService;
#RequestMapping("/customers")
#ResponseBody
public Iterable<Customer> findAll() {
List<Customer> results = new ArrayList<>();
Iterator<Customer> iter = customerService.findAll().iterator();
while (iter.hasNext()) results.add(iter.next());
return results;
}
}
In the following post, Andy states,
While a List is guaranteed to be an Iterable an Iterable may not be a List. This means that if you do cast an Iterable to a List it may fail at runtime. Even if it works, there's no guarantee that it will continue to work in the future as it could change in new versions of Spring Data JPA without breaking the interface's contract.
Instead of using a cast, you should declare your own query methods that return List.
Also noted in that post, you can use JpaRepository rather than CrudRepository because JPA will return a List rather than an Iterable as mentioned here.