Error 415 Web service Rest with Spring - spring

i'm having a problem with my service. I'm trying to send the datas to the database. However, i'm receiving this message:
Error 415
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
I'm using Postman to sendo the code below:
Postman
Controller:
package br.com.standard.controller;
import java.util.List;
import br.com.standard.bean.Client;
import br.com.standard.service.ClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ClientController {
#Autowired
ClientService clientService;
#RequestMapping(value = "/addClient", method = RequestMethod.POST, headers = "Accept=application/json")
public void addClient(#RequestBody Client client) {
clientService.addClient(client);
}
}
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;
#Entity
#Table(name="client")
public class Client {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
#Column(name="name")
String nome;
public Client() {
super();
}
public Client(int id, String nome) {
super();
this.id = id;
this.nome = nome;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
I know that it probably is a simple question, but i tried a lot of ways without success.
Thanks in advance.

Two (alternative) solution proposals:
Be sure to send the header: Accept=application/json! (with your client.)
...or change headers = "Accept=application/json" to
consumes = org.springframework.http.MediaType.APPLICATION_JSON (leaving everything else as is)

Related

Spring boot controller not getting scanned error 404 not found

I am trying to create restful api but my controller is not working and I'm getting the error shown below:
{
"timestamp": "2020-06-11T15:28:18.103+00:00",
"status": 404,
"error": "Not Found",
"message": "",
"path": "/path/findCarsAfterYear/2020"
}
Please help me to resolve this.
Entity Class
package com.example.demo.data;
import javax.persistence.*;
#Entity
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private long id;
#Column
private String model;
#Column
private Integer year;
// standard getters and setters
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
}
Repository Class
package com.example.demo.Repository;
import com.example.demo.data.Car;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface CarRepository extends JpaRepository<Car, Integer> {
#Query("Select wds from Car wds where year=?1 ")
List<Car> findCarsAfterYear(Integer year);
}
Service class
package com.example.demo.service;
import com.example.demo.Repository.CarRepository;
import com.example.demo.data.Car;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
#Service
public class CarService {
#Autowired
CarRepository carRepository;
public List<Car> findCarsAfterYear(Integer id) {
return carRepository.findCarsAfterYear(id);
}
}
Controller class
package com.example.demo.Controller;
import com.example.demo.data.Car;
import com.example.demo.service.CarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#Controller
#RequestMapping(path="/test")
public class CarController {
#Autowired(required=true)
private CarService carService;
#GetMapping(value="/findCarsAfterYear/{id}")
public List<Car> findCarsAfterYear(Integer id) {
return carService.findCarsAfterYear(id);
}
}
Application Class
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#Configuration
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
#EnableJpaRepositories("com.example.demo.Repository")
#EntityScan("com.example.demo.data")
#ComponentScan(basePackages="com.example.demo.service,com.example.demo.Controller")
#EnableCaching
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
In you want to use #Controller then you have to provide #ResponseBody explicitly.
#Controller
#RequestMapping(path="/test")
public class CarController {
#Autowired(required=true)
private CarService carService;
#GetMapping(value="/findCarsAfterYear/{id}")
#ResponseBody
public List<Car> findCarsAfterYear(Integer id) {
return carService.findCarsAfterYear(id);
}
}
But in case #RestController, which is combination of #Controllerand #ResponseBody
#RestController
#RequestMapping(path="/test")
public class CarController {
#Autowired(required=true)
private CarService carService;
#GetMapping(value="/findCarsAfterYear/{id}")
public List<Car> findCarsAfterYear(Integer id) {
return carService.findCarsAfterYear(id);
}
}
I hope this will be helpful.

Spring boot - Post function get error while Get and Delete function still be ok

I'm newly get to spring framework and handing-on basic steps however I got a error which didn't where it come from. I just use Postman to communicate with data. Get and delete function were smooth, however Post and Put didn't.
This is my code:
Class EmployeeRepo
package com.employee.demo.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import com.employee.demo.model.Employee;
public interface EmployeeRepo extends JpaRepository<Employee, Integer>{
}
Class Employee
package com.employee.demo.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Employee {
#Id
private int id;
private String name;
private double salary;
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;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Employee with [ID: " + id + ", name: " + name + " and salary: " + salary + "]";
}
}
Class EmployeeController
package com.employee.demo.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.employee.demo.dao.EmployeeRepo;
import com.employee.demo.model.Employee;
#RestController
public class EmployeeController {
#Autowired
EmployeeRepo repo;
#RequestMapping("/")
public String home() {
return "home.jsp";
}
#DeleteMapping("/employee/{id}")
public String deleteEmployee(#PathVariable int id) {
Employee empl = repo.getOne(id);
repo.delete(empl);
return "deleted";
}
#PostMapping("/employee")
public Employee addEmployee(Employee empl) {
repo.save(empl);
return empl;
}
#GetMapping(path = "/employees")
public List<Employee> getEmployees() {
return repo.findAll();
}
#PutMapping(path = "/employee", consumes = {"application/json"})
public Employee saveOrUpdateEmployee(#RequestBody Employee empl) {
repo.save(empl);
return empl;
}
#RequestMapping("/employee/{id}")
public Optional<Employee> getEmployee(#PathVariable int id) {
return repo.findById(id);
}
}
And this is what I got from postman for Post query
Problem is with your POST method (addEmployee)- Whatever you are sending in request body is not accepted by addEmployee method. You can verify in DB after a POST call.
employee table will have data something like
Use #RequestBody annotation with argument as:
public Employee addEmployee(#RequestBody Employee empl)
And it will work as expected.

Error: Action : Consider defining a bean of type "package" in your configuration

the following error I am getting :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field employeeDAO in com.example.demo.controller.EmployeeController required a bean of type 'com.example.demo.dao.EmployeeDAO' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.dao.EmployeeDAO' in your configuration.
my folder structure:
below are the files:
1.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#SpringBootApplication
#EnableJpaRepositories
public class RestCrudDemo1Application {
public static void main(String[] args) {
SpringApplication.run(RestCrudDemo1Application.class, args);
}
}
2.
package com.example.demo.controller;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.dao.EmployeeDAO;
import com.example.demo.model.Employee;
#RestController
#RequestMapping("/company")
public class EmployeeController {
#Autowired
EmployeeDAO employeeDAO;
#PostMapping ("/employee")
public Employee createEmployee(#Valid #RequestBody Employee emp){
return employeeDAO.save(emp);
}
#GetMapping ("/findAll")
public List<Employee> findAll(){
return employeeDAO.findAll();
}
#GetMapping("/employees/{id}")
public ResponseEntity<Employee> getEmployeeById(#PathVariable(value = "id") Long empid){
Employee emp = employeeDAO.findOne(empid);
if (emp==null){
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok().body(emp);
}
#PutMapping("/employees/{id}")
public ResponseEntity<Employee> updateEmployee(#PathVariable(value = "id") Long empid, #Valid #RequestBody Employee empDetails){
Employee emp = employeeDAO.findOne(empid);
if (emp==null){
return ResponseEntity.notFound().build();
}
emp.setName(empDetails.getName());
emp.setDesignation(empDetails.getExpertise());
emp.setExpertise(empDetails.getExpertise());
Employee updateEmployee = employeeDAO.save(emp);
return ResponseEntity.ok().body(updateEmployee);
}
#DeleteMapping("/employees/{id}")
public ResponseEntity<Employee> deleteEmployee(#PathVariable(value = "id") Long empid){
Employee emp = employeeDAO.findOne(empid);
if (emp==null){
return ResponseEntity.notFound().build();
}
employeeDAO.delete(emp);
return ResponseEntity.ok().build();
}
}
3.
package com.example.demo.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.example.demo.model.Employee;
import com.example.demo.repository.EmployeeRepository;
public class EmployeeDAO {
#Autowired
EmployeeRepository employeeRepository;
public Employee save(Employee emp){
return employeeRepository.save(emp);
}
public List<Employee> findAll(){
return employeeRepository.findAll();
}
public Employee findOne(Long empid){
return employeeRepository.findOne(empid);
}
public void delete(Employee emp){
employeeRepository.delete(emp);
}
}
4.
package com.example.demo.model;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
#Entity
#Table(name = "Employees")
#EntityListeners(AuditingEntityListener.class)
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
#NotBlank
private String name;
#NotBlank
private String designation;
#NotBlank
private String expertise;
#NotBlank
#Temporal(TemporalType.TIMESTAMP)
#LastModifiedDate
private Date createdAt;
public long getId() {
return Id;
}
public void setId(long id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getExpertise() {
return expertise;
}
public void setExpertise(String expertise) {
this.expertise = expertise;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
}
5.
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.model.Employee;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
public Employee findOne(Long empid);
}
From the error, I get to know that employee dao bean has not been created for autowiring into the controller.
By analysing your employee dao class, you forgot to annotate with #Repository due to which bean has not been created by context scanning.
Annotate empoyeedao class with #Repository. It should solve your problem.

Jersey - get parameter always null

I changed my code according to R4J answer.
I think there's something more to correct since I can't display anything now...
result I get - console is clear (no errors)
Could anyone be so kind and help me find the issue?
Below I describe my project:
DB:
database table "users"
TestUser.java
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 = "USERS")
public class TestUser {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "email", nullable = false)
private String email;
#Column(name = "password", nullable = false)
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
TestService.class
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.test.testapp.dao.UserDao;
import com.test.testapp.model.TestUser;
#Component
public class TestService {
#Autowired
UserDao userDao;
public List<TestUser> getUsers() {
return userDao.findAll();
}
}
UserDao.class
import java.util.List;
import javax.persistence.PersistenceException;
import com.test.testapp.model.TestUser;
public interface UserDao /* extends CrudRepository<TestUser, Integer>*/{
public List<TestUser> findAll() throws PersistenceException;
}
UserDaoImpl.java
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.jvnet.hk2.annotations.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.test.testapp.dao.UserDao;
import com.test.testapp.model.TestUser;
#Repository("userDao")
#Service
public class UserDaoImpl implements UserDao {
#Autowired
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public TestUser findPersonById(Integer id) {
return entityManager.find(TestUser.class, id);
}
#Override
#Transactional
public List<TestUser> findAll() {
try {
return entityManager.createQuery("SELECT u FROM Users u ORDER BY p.id", TestUser.class).getResultList();
} finally {
entityManager.close();
}
}
}
TestWebApi.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Controller
#Path("test")
public interface TestWebApi {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/")
public Response getUsers();
}
TestWebApiImpl.java
import java.util.List;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import com.test.testapp.model.TestUser;
import com.test.testapp.service.TestService;
import com.test.testapp.web.TestWebApi;
public class TestWebApiImpl implements TestWebApi {
#Inject
TestService testService;
#Override
public Response getUsers() {
List<TestUser> test = testService.getUsers();
return Response.ok().entity(test).build();
}
}
You are mixing JAX-RS annotations with Spring-MVC annotations. If you want to stick to JAX-RS then your code should look like this:
#Path("users")
#Component
public class UserController {
#Inject
UserService userService;
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/")
public List<User> getUsers() {
return userService.findAll();
}
#GET
#Path("/users/{name}")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserByName(#NotNull #PathParam("name") String username) {
User user = userService.findByName(username);
return Response.ok().entity(user).build();
}
}
Currently, you have #RestController on your Class which makes it a Spring Rest Controller. So Spring scans all methods and finds '#RequestMapping("/user/{name}")' and '#RequestMapping("/users")' so it binds these methods to default GET operations and ignores completely #PathVariable annotation because it comes from JAX-RS not Spring.
Spring-MVC version of your code would be:
#RestController
#RequestMapping("/")
public class UserController {
#Inject
UserService userService;
#RequestMapping(value = "/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public List<User> getUsers() {
return userService.findAll();
}
#RequestMapping(value = "/users/{name}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Response getUserByName(#NotNull #PathVariable("name") String username) {
User user = userService.findByName(username);
return Response.ok().entity(user).build();
}
}

Test Spring REST API. How to save entity with subobject in JUnit test?

I have two classes: Course and Lesson. Course is #OneToMany relationship with Lesson. Using Spring Boot I've created a simple REST API to manage the classes. I've tested the API manually with postman and it looks like everything is working.
Next, I've writen simple JUnite to test the API automatically. When the test finishes, Course entity was saved correctly in the database but Lesson throws an error:
2014-10-15 20:19:15.162 ERROR 5812 --- [nio-8080-exec-2] s.d.r.w.AbstractRepositoryRestController : Could not read JSON: Template must not be null or empty! (through reference chain: com.mbury.elearning.domain.Lesson["course"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Template must not be null or empty! (through reference chain: com.mbury.elearning.domain.Lesson["course"])
Looks like #OneToMany relationship was not correctly mapped but I don't know how to handle this. Does anyone have an idea how to configure Spring REST with an entity that contains subobject to work correctly?
Bellow I've attached all my code:
LessonTest.java
package com.mbury.elearning;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.util.MatcherAssertionErrors.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;
import com.mbury.elearning.domain.Course;
import com.mbury.elearning.domain.Lesson;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class LessonTest {
final String BASE_URL_COURSE = "http://localhost:8080/courses/";
final String BASE_URL_LESSON = "http://localhost:8080/lessons/";
#Test
public void shouldCreateNewLesson() {
final String COURSE_TITLE = "test";
final String COURSE_DESCRIPTION = "test";
final String LESSON_TOPIC = "test";
Course course = new Course();
course.setTitle(COURSE_TITLE);
course.setDescription(COURSE_DESCRIPTION);
Lesson lesson = new Lesson();
lesson.setTopic(LESSON_TOPIC);
lesson.setCourse(course);
RestTemplate rest = new TestRestTemplate();
ResponseEntity<Course> response = rest.postForEntity(BASE_URL_COURSE, course,
Course.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.CREATED));
ResponseEntity<Lesson> response1 = rest.postForEntity(BASE_URL_LESSON, lesson,
Lesson.class);
assertThat(response1.getStatusCode(), equalTo(HttpStatus.CREATED));
}
}
Course.java
package com.mbury.elearning.domain;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "course")
public class Course {
#Column(name = "description")
private String description;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Integer id;
#OneToMany(mappedBy = "course")
private List<Lesson> lesson;
#Column(name = "title")
private String title;
public String getDescription() {
return description;
}
public Integer getId() {
return id;
}
public List<Lesson> getLesson() {
return lesson;
}
public String getTitle() {
return title;
}
public void setDescription(String description) {
this.description = description;
}
public void setId(Integer id) {
this.id = id;
}
public void setLesson(List<Lesson> lesson) {
this.lesson = lesson;
}
public void setTitle(String title) {
this.title = title;
}
}
Lesson.java
package com.mbury.elearning.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "lesson")
public class Lesson {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "topic")
private String topic;
#ManyToOne(optional = false)
#JoinColumn(name = "ID_COURSE")
Course course;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
}
CourseRepository.java
package com.mbury.elearning.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.mbury.elearning.domain.Course;
#RepositoryRestResource
public interface CourseRepository extends CrudRepository<Course, Integer> {
}
LessonRepository .java
package com.mbury.elearning.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.mbury.elearning.domain.Lesson;
#RepositoryRestResource
public interface LessonRepository extends CrudRepository<Lesson, Integer> {
}
Application .java
package com.mbury.elearning;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#ComponentScan
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The root of the problem is that you're trying to reuse your domain objects, Lesson and Course, to create the JSON payloads that you're sending to your REST API. This doesn't work as the REST API's view of a Lesson or Course is different from the implementation's JPA-based view of them. For example, on the server, the id of a Lesson or Course is an int, whereas in the REST API the id is a URI.
Given that Course and Lession are both quite simple types, it's probably easiest to use a Map when you're sending a request to the REST API. For example, you can create a course like this:
Map<String, Object> course = new HashMap<String, Object>();
course.put("title", "test");
course.put("description", "test");
I mentioned above that, in the REST API, a URI is used to identify a course. This means that when you create a lesson, you need the URI of the course to which it belongs. You get that URI from the Location header of the response that's returned when you create the course:
ResponseEntity<Void> courseResponse = rest.postForEntity(BASE_URL_COURSE, course, Void.class);
assertThat(courseResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
URI courseLocation = courseResponse.getHeaders().getLocation();
You can then use this URI to create the Map for the lesson and make the API call to create it:
Map<String, Object> lesson = new HashMap<String, Object>();
lesson.put("topic", "test");
lesson.put("course", courseLocation);
ResponseEntity<Void> lessonResponse = rest.postForEntity(BASE_URL_LESSON, lesson, Void.class);
assertThat(lessonResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
Putting this all together gives you this test method:
#Test
public void shouldCreateNewLesson() {
Map<String, Object> course = new HashMap<String, Object>();
course.put("title", "test");
course.put("description", "test");
RestTemplate rest = new TestRestTemplate();
ResponseEntity<Void> courseResponse = rest.postForEntity(BASE_URL_COURSE, course, Void.class);
assertThat(courseResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
URI courseLocation = courseResponse.getHeaders().getLocation();
Map<String, Object> lesson = new HashMap<String, Object>();
lesson.put("topic", "test");
lesson.put("course", courseLocation);
ResponseEntity<Void> lessonResponse = rest.postForEntity(BASE_URL_LESSON, lesson, Void.class);
assertThat(lessonResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
}
I am getting a 404 error. It looks like the issue could be with calling the BASE_URL_LESSON.

Resources