Why do I get Status 400, Bad Request on my POST URL (using postman) - spring-boot

I am trying to follow a Spring Boot Tutorials on youtube and I get stuck at Post.
I tried searching for fix but I can't find an specific answer why I can't access the post URL?
I tried both #PostMapping and #RequestMapping(Method = POST)
still same results.
Maybe I am accessing my URL wrong?
I am trying to Post at /api/sis/student_reg
need help, thanks!
#RestController
#RequestMapping(path = "/api/sis")
public class StudentController {
#Autowired
private StudentService studentService;
#GetMapping(path = "/student")
public List<Student> displayStudent(){
return studentService.getStudent();
}
#RequestMapping(method = RequestMethod.POST, value = "/reg_student")
public void registerStudent(#RequestBody Student student){
studentService.addStudent(student);
}
}
#Service
public class StudentService {
#Autowired
private StudentRepository studentRepository;
private Student students = new Student();
public List<Student> getStudent(){
List<Student> student = new ArrayList<>();
studentRepository.findAll()
.forEach(student::add);
return student;
}
public void addStudent(Student student){
studentRepository.save(student);
}
#Entity
#Table
public class Student {
UUID uuid = UUID.randomUUID();
#Id
#SequenceGenerator(
name = "student_sequence",
sequenceName = "student_sequence",
allocationSize = 1
)
#GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "student_sequence"
)
private String id;
private String FirstName;
private String LastName;
private String email;
// Method Converting UUID into string
public String genID(){
id = uuid.toString();
return id;
}
//Constructor, getters and setters
Edited again:
I receive error 400 when using the "Post" while 405 "Get" on the post URL.
apologies for the confusion.

It is not about wrong url. If that would have been the case you would get 404 Not Found error and not 400 i.e., Bad Request.
This means your request is not proper. Can you please also update the whole request body which you are using in postman and also attributes of your Student Class.

Related

Why does not delete data in rest api

I am working on rest api. I got error while delete data by id. All code is complete but don't know why postman fire error. I can map two table with unidirectional mapping using hibernate.
Here down is error in postman:
"message": "Required request body is missing: public org.springframework.http.ResponseEntity<org.springframework.http.HttpStatus> com.rest.RestApiPojo.Controller.PojoController.deleteAddressPerson(com.rest.RestApiPojo.Entity.Person,java.lang.Integer)"
Here down is my code:
Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer person_id;
private String name;
#JsonManagedReference
#OneToOne(cascade = CascadeType.ALL, mappedBy = "person")
private Address address;
// getter setter
}
#Table(name = "address_master")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer address_id;
private String city;
private String country;
#JsonBackReference
#OneToOne(cascade=CascadeType.ALL, targetEntity = Person.class)
#JoinColumn(name = "person_id")
private Person person;
// getter setter
}
SeviceImpl
#Override
public void deleteAddressPerson(Integer personId) {
personRepo.deleteById(personId);
}
Controller
#RequestMapping(value = "/dltpersonaddress/{personId}", method = RequestMethod.DELETE)
public ResponseEntity<HttpStatus> deleteAddressPerson(#RequestBody Person person, #PathVariable Integer personId)
{
pojoService.deleteAddressPerson(personId);
return new ResponseEntity<>(HttpStatus.OK);
}
You have an unused #RequestBody Person person parameter in your controller method.
#RequestMapping(value = "/dltpersonaddress/{personId}", method = RequestMethod.DELETE)
public ResponseEntity<HttpStatus> deleteAddressPerson(#RequestBody Person person, #PathVariable Integer personId)
{
pojoService.deleteAddressPerson(personId);
return new ResponseEntity<>(HttpStatus.OK);
}
The error message explains that this param is obligatory, and requests without it wont be processed.
Remove the param to solve the issue.

Spring Framework Responses from POST

What is the standard object design for accepting a POST request from a client, saving the record to the database, and then returning a response back to the client? I'm working with the Spring framework.
Should I be sending back the entity and hiding properties that aren't necessary for the response?
#RestController
public class SomeController {
private final SomeService service;
#PostMapping(value = "/post/new", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomeEntity> post(#RequestBody final SomeEntity someEntity) {
SomeEntity savedEntity = service.save(someEntity);
return ResponseEntity.ok(savedEntity);
}
}
#Entity
#Table(name = "posts")
public class SomeEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "title")
private String title;
#Column(name = "body")
#JsonIgnore
private String body;
#JsonIgnore
#Column(name = "deleted_ind")
private boolean deleted;
#JsonIgnore
#Column(name = "author")
private String author;
#Column(name = "created_at")
private LocalDateTime createdAt;
}
or would I accept some sort of POST request object that I convert to an entity, then re-assemble the entity into a response?
#JsonIgnoreProperties(ignoreUnknown = true)
public class SomePostRequestResource {
private String title;
private String body;
private String createdAt;
}
#RequiredArgsConstructor
#RestController
public class SomeController {
private final SomeService service;
private final SomeResourceAssembler resourceAssembler;
#PostMapping(value = "/post/new", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomePostRequestResource> post(
#RequestBody final SomePostRequestResource someResource
) {
SomeEntity savedEntity = service.convertToEntityAndSave(someResource);
SomePostRequestResource response = resourceAssembler.toResource(savedEntity);
return ResponseEntity.ok(response);
}
}
But then maybe I only want to send back the createdAt, would I hide the other properties in the SomePostRequestResource, or do I need another object to represent the response, which only has the property I want to send back?
I would also appreciate any book or article suggestions related to desigining objects for use with a RESTful API. I have seen articles concerning how to design and name the endpoints, but not so many concerning how to design the objects on the backend.
I would recommend you create a DTO class for the incoming/outgoing data containing the filed that are set/viewable by the client like:
public class SomeEntityIncomingDto {
private String title;
....
}
public class SomeEntityOutgoingDto {
private Long id;
private String title;
....
}
On the other hand, You won't need to map your persistence entities to DTOs and vice versa manually, you can use a library like ModelMapper or MapStruct that handles the conversion automatically.

SPRING REST controller - return image AND json values

I have built a rest web service, using SPRING and Hibernate.
I have 2 entities : Image and user, linked with a oneToOne annotation.
When I try to return the user details AND the image corresponding to this user, I get this error :
"org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation"
When I do it separately It works fine, but when I do it in one route, I get this error.
Here is my controller :
#CrossOrigin(
origins = "*",
methods = {RequestMethod.POST, RequestMethod.GET, RequestMethod.OPTIONS, RequestMethod.DELETE},
allowedHeaders = "*")
#RestController
#RequestMapping(path = "/user")
public class UserController {
#Autowired
UserRepository userRepository;
#Autowired
ImageRepository imageRepsository;
doesn't work--> #RequestMapping(value="/{userId}/getUserAndImage",method=RequestMethod.GET,produces = MediaType.IMAGE_JPEG_VALUE )
public Optional<User> getUserAndImage(#PathVariable Long userId) {
return userRepository.findById(userId);
}
works fine--> #RequestMapping(value="/{userId}/image", method=RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public byte[] getUserImage(#PathVariable Long userId) {
byte[] image = (imageRepsository.findImageWithUserId(userId)).getImage();
return image;
}
Here are entities :
User entity :
#Entity
#Table(name="users")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#NotNull
#Size(max=100)
#Column
private String nom;
#NotNull
#Size(max=250)
#Column
private String prenom;
#OneToOne(fetch=FetchType.EAGER,
cascade = CascadeType.PERSIST)
private Image image;
//getters and setters
}
Image entity :
#Entity
#Table(name="images")
public class Image {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="image")
#Lob
private byte[] image;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name="user_id")
private User user;
//getters and setters
}
in the annotation, produce set as MediaType.IMAGE_JPEG_VALUE, then your code return response as User object. As result it throw that exception because spring expect your code to return JPEG type file only.
What can i suggest here,use produces = MediaType.APPLICATION_JSON_VALUE, and convert your image from byte[] to base64 string then return response as json object

How to send model property, the property is the model too in spring

I have two models.
#Entity
class Product {
#Id
private String id;
private String name;
#ManyToOne(optional = false)
#JoinColumn(name = "category_id", referencedColumnName = "id")
#NotNull(groups = {CREATE.class, UPDATE.class})
private Category category;
...
}
#Entity
class Category {
#Id
private String id;
private String name;
...
}
#RestController
#RequestMapping(path = "/product")
class ProductController {
#RequestMapping(method = RequestMethod.POST)
public void create(#ModelAttribute Product product) {
...
}
}
I want send request to ProductController:
http POST http://localhost:8080/product name=='Product 1' category=1
The param category is id of Category into db, but spring does not understand it.
Is it possible to do this?
Well, your entitiy classes are ok, but it's really weird to see parameters in the POST request especially in so sort as you have it placed here.
Here is my sample that is working properly
public class Product {
private String id;
private String name;
private Category category;
******
}
public class Category {
private String id;
private String name;
*******
}
#RestController
#RequestMapping(path = "/product")
public class ProductController {
#RequestMapping(method = RequestMethod.POST)
public void create(#ModelAttribute Product product) {
Product prd1 = product;
prd1.getId();
}
}
And just in case here is an appConfig:
#Configuration
#EnableWebMvc
public class AppConfig {
}
That is all. Now your contorller is expecting to get a message that is a Product instance.
Let's go onward. It's pretty weird to see parameters in the POST query. I've had some test and they are ok - just pass the data as a request body! Whatever you cose. For instance let's modify controller as it shown below:
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public void create(#ModelAttribute Product product) {
Product prd1 = product;
prd1.getId();
}
}
And now you have to send a POST message with a body that contains a Product data in a JSON format, i.e
{ "id": 1 }
and it works for all other formats that are supported by spring

Enhanced Spring Data Rest delivers empty relations

in my current implementation using Spring-Boot, -HATEOAS, -Rest-Data I'm trying to spare some further rest calls and enhance my rest resource for credits to also deliver relations of a credit (see below account as ManyToOne and creditBookingClassPayments as OneToMany).
The problem now is that I'm not able to get it run. The call always delivers empty relations. I really would appreciate some help on this.
Here are the surroundings:
Credit.java
#Entity
#Getter
#Setter
public class Credit {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Setter(NONE)
#Column(name = "id")
private Long itemId;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="account_id", nullable = false)
private Account account;
#OneToMany(mappedBy = "credit")
private List<CreditBookingClassPayment> creditBookingClassPayments = new ArrayList<>();
#NotNull(message="Please enter a valid short name.")
#Column(length = 10, nullable = false)
private String shortName;
#NotNull(message="Please enter a valid name.")
#Column(nullable = false)
private String name;
...
}
CreditRepositoryCustomImpl.java
uses QueryDsl to enhance the credit resource with its realation
...
#Override
public List<Credit> findDistinctByAccountItemIdNew(Long accountId) {
QCredit credit = QCredit.credit;
QAccount account = QAccount.account;
QCreditBookingClassPayment creditBookingClassPayment = QCreditBookingClassPayment.creditBookingClassPayment;
QBookingClass bookingClass = QBookingClass.bookingClass;
BooleanExpression hasAccountItemId = credit.account.itemId.eq(accountId);
List<Credit> credits = from(credit).where(hasAccountItemId)
.innerJoin(credit.account, account)
.leftJoin(credit.creditBookingClassPayments, creditBookingClassPayment)
.leftJoin(creditBookingClassPayment.bookingClass, bookingClass).groupBy(credit.itemId).fetch();
return credits;
}
...
CreditController.java
looking into responseBody here all (account and credit payments) is available for credits
#RepositoryRestController
public class CreditController {
#Autowired
private CreditRepository creditRepository;
#RequestMapping(value = "/credit/search/findAllByAccountItemIdNew", method= RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
#ResponseBody
public ResponseEntity<Resources<PersistentEntityResource>> findAllByAccountItemIdNew(#RequestParam Long accountId, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
List<Credit> credits = creditRepository.findDistinctByAccountItemIdNew(accountId);
Resources<PersistentEntityResource> responseBody = new Resources<PersistentEntityResource>(credits.stream()
.map(persistentEntityResourceAssembler::toResource)
.collect(Collectors.toList()));
return ResponseEntity.ok(responseBody);
}
}
CreditResourceIntegrTest.java
here creditResourcesEntity hold the credit but account is null and creditBookingClassPayment is an empty array
#Test
public void testFindAllByAccountItemId() throws URISyntaxException {
URIBuilder builder = new URIBuilder(creditFindAllByAccountItemIdRestUrl);
builder.addParameter("accountId", String.valueOf(EXPECTED_ACCOUNT_ID));
builder.addParameter("projection", "base");
RequestEntity<Void> request = RequestEntity.get(builder.build())
.accept(MediaTypes.HAL_JSON).acceptCharset(Charset.forName("UTF-8")).build();
ResponseEntity<Resources<Resource<Credit>>> creditResourcesEntity =
restTemplate.exchange(request, new ParameterizedTypeReference<Resources<Resource<Credit>>>() {});
assertEquals(HttpStatus.OK, creditResourcesEntity.getStatusCode());
//assertEquals(EXPECTED_CREDIT_COUNT, creditResourcesEntity.getBody().getContent().size());
}
Do I miss something?
Thanks for your help!
Karsten
Okay, PersistentEntityResourceAssembler doesn't support relations. But this could be handled by using projections.
CreditProjection.java
#Projection(name = "base" , types = Credit.class)
public interface CreditProjection {
String getShortName();
String getName();
List<CreditBookingClassPaymentProjection> getCreditBookingClassPayments();
BigDecimal getValue();
BigDecimal getInterestRate();
BigDecimal getMonthlyRate();
}
CreditBookingClassPaymentProjection.java
#Projection(name = "base" , types = CreditBookingClassPayment.class)
public interface CreditBookingClassPaymentProjection {
BookingClass getBookingClass();
CreditPaymentType getCreditPaymentType();
}
CreditController.java
#RepositoryRestController
public class CreditController {
#Autowired
private ProjectionFactory projectionFactory;
#Autowired
private CreditRepository creditRepository;
#RequestMapping(value = "/credit/search/findAllByAccountItemIdNew", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE)
#ResponseBody
public ResponseEntity<Resources<?>> findAllByAccountItemIdNew(#RequestParam Long accountId,
PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
List<Credit> credits = creditRepository.findDistinctByAccountItemIdNew(accountId);
List<PersistentEntityResource> creditResources = new ArrayList<>();
for (Credit credit : credits) {
// credit.getCreditBookingClassPayments()
PersistentEntityResource creditResource = persistentEntityResourceAssembler.toResource(credit);
creditResources.add(creditResource);
}
Resources<CreditProjection> responseBody = new Resources<CreditProjection>(credits.stream()
.map(credit -> projectionFactory.createProjection(CreditProjection.class, credit))
.collect(Collectors.toList()));
return ResponseEntity.ok(responseBody);
}
}

Resources