How to handle POST restful webservice in Spring MVC which consume and produce data and image both - spring

I am developing webservice which contain some information with image , for example , develop webservice which contain user information with photo. I want this done by POST request. How can I achieve this?
I want to store only image path in database.
What changes should i make in controller to retrive image from mobile and store it in database? I am taking UserInfoTemp object as request body.
To developing webservice I am using Spring MVC 4.0.3.Release.
Here is my code please review it:
#Entity
public class UserInfoTemp
{
#Id
#GeneratedValue
#Column(name="UserId")
private Long id;
#Column(name="FirstName")
private String firstName;
#Column(name="LastName")
private String lastName;
#Column(name="Email")
#JsonProperty(value="email")
private String email;
#Column(name="Phone")
private String phone;
#Column(name="ProfilePicLink")
private String profilePicLink;
#Column(name="ProfilePicThumbnailLink")
private String profilePicThumbnailLink;
//getter setter
}
Controller:-
// for registering user
#RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity<Object> register(#RequestBody UserInfoTemp userInfoTemp)
{
try
{
userInfoService.save(userInfoTemp);
return new ResponseEntity<Object>(userInfoTemp, HttpStatus.CREATED);
}
catch(Exception e)
{
Message message = new Message();
message.setStatus(false);
message.setMessage("User information can not be null");
return new ResponseEntity<Object>(message, HttpStatus.CREATED);
}
}

Related

Spring redirect simple rest POST with body (json) on another port

I have 2 spring rest applications.
When I send data to the first one,
private Long id;
private String name;
private String surname;
private String productName;
private Double productValue;
First I create a client entry in DB with the fields:
private Long id;
private String name;
private String surname;
and than
I would like to make a redirect post to another port, another application
handling product data with body including the two fields:
private String productName;
private Double productValue;
private Long clientId;
to create a product entry in the db
after creating product, I would like to redirect back to the first app and show the saved client.
The question is, how should I build my Controller?
Do I have to use ModelAndView? - this is only a backend rest, without any front (run from postman :)
You may like to do this way first autowire RestTemplate and then use it to call another api -
#RestController
public class ProductResource {
#Autowired
RestTemplate restTemplate;
#Autowired
private ProductRepository repository;
#PostMapping
public ResponseEntity<Product> saveProduct(#RequestBody Product product) {
Product productSavedAtClient = repository.save(product);
Product savedProduct = restTemplate.postForObject("http://some.other.app/product", productSavedAtClient, Product.class);
return ResponseEntity.ok().body(savedProduct);
}
}

Spring Boot JPA update after fething ID is not working

#Autowired
LessonService lsnService;
#PutMapping(path = "/{id}")
public ResponseEntity<Object> updateLesson(#PathVariable("id") Long id, #Valid #RequestBody LessonDto dto) {
try {
lsnService.findById(id);
dto.setId(id);
lsnService.save(dto);
return ResponseEntity.ok(dto);
}
catch (Exception e) {
ApiErrorMessage errorMessage = new ApiErrorMessage();
errorMessage.setStatusCode(400L);
errorMessage.setMessage(e.getMessage());
errorMessage.setDescription("The server cannot or will not process the request due to an apparent client error");
return ResponseEntity.badRequest().body(errorMessage);
}
}
Here's my problem. When I remove lsnService.findById(id);, update is working.
If I didn't add that code if a user update with unexisting ID, it will save another data.
Another problem is when I remove dto.setId(id);, both method from lsnService; findById(id); and save(dto); are working! But as you can see, repo must update the entity but it won't!!!
So, I tried to put #Transactional in saving. And I even try putting Thread.sleep(5000); 5 secs delay between those two services. Like this,
lsnService.findById(id);
Thread.sleep(5000);
dto.setId(id);
lsnService.save(dto);
But it doesn't work either!
#Autowired
private LessonJpaRepository repo;
#Override
public LessonDto findById(Long id) {
// TODO Auto-generated method stub
Lesson lesson = repo.getOne(id);
LessonDto dto = new LessonDto(lesson);
return dto;
}
#Override
public void save(LessonDto dto) {
// TODO Auto-generated method stub
repo.save(dto.getEntity());
System.out.println(dto.getId()+dto.getTitle()+dto.getStructure()+dto.getExplanation());
}
And then, I check output of that dto. It's all there! repo is not saving it! It's so strange to me. Got any ideas?
public class LessonDto {
private Long id;
#NotNull(message = "Title must not be null")
#NotBlank(message = "Title must not be blank")
#ValidLessonTitle(message = "Title must begin with uppercase character")
private String title;
#NotNull(message = "Structure must not be null")
#NotBlank(message = "Structure must not be blank")
private String structure;
#NotNull(message = "Explanation must not be null")
#NotBlank(message = "Explanation must not be blank")
private String explanation;
public LessonDto() {
}
public LessonDto(Lesson lesson) {
this.id=lesson.getId();
this.title=lesson.getTitle();
this.structure=lesson.getStructure();
this.explanation=lesson.getExplanation();
}
#java.beans.Transient
public Lesson getEntity() {
Lesson lesson = new Lesson();
lesson.setId(this.id);
lesson.setTitle(this.title);
lesson.setStructure(this.structure);
lesson.setExplanation(this.explanation);
return lesson;
}
//getters and setters
}
This is the entity
#Entity
public class Lesson implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2239534946567783017L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "title")
private String title;
#Column(name = "structure")
private String structure;
#Column(name = "explanation")
private String explanation;
//getters and setters
}
There are 2 ways to make that work
Update instance that is retured by findById with values from DTO
Dont use findById as it fetches entity pointer (at least) to the cache and this might be the origin of problems. Try to use existsById instead

Spring MVC Based Rest Services Validations for request body

I have Rest Controller in my application which has the code snippet like below:-
#RestController
#RequestMapping("/api/v1/user")
public class UserRestControllerV1 {
#PostMapping("")
public Response registerUser(#RequestBody #Valid final Request<UserDto> request,
final HttpServletRequest httpServletRequest,
BindingResult result){
Response response = new Response(request);
if(result.hasErrors()){
response.setData(new String("Error"));
}else {
response.setData(new String("Test"));
}
return response;
}
The Request Class:-
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Request<T> {
#JsonProperty(value = "co-relation-id")
private String coRelationID;
#NotNull(message = "The request body should be present")
private T data;
/*
..... various other fields
Getters / Setters
*/
}
The UserDto Class :-
public class UserDto {
#NotNull(message = "The username should not be null")
private String username;
#NotNull(message = "The password should not be null")
#JsonIgnore
private String password;
/*
..... various other fields
Getters / Setters
*/
}
Issue : I am having issues with my validations here. The field private T data in the request class gets validated but the fields inside T - in the case UserDto are not getting validated.
So I need to know the approach or code snippet to achieve this.
I have tried configuring the hibernate validator bean in the configuration but it is of no help in the scenario
#Valid constraint will instruct the Bean Validator to delve to the type of its applied property and validate all constraints found there.
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Request<T> {
#JsonProperty(value = "co-relation-id")
private String coRelationID;
//#NotNull(message = "The request body should be present")
#Valid
private T data;
/*
..... various other fields
Getters / Setters
*/
}

How to create REST endpoint service consume multipart using Spring 4.x?

I am trying to create a REST service that consumes the "multipart/form-data" with text and attachment objects. For files i can use "org.springframework.web.multipart.MultipartFile", but how do i specify the service method for Text objects?
Below is the expected client call to service.
create Rest endpoint by using this way
public void sendEmail(#RequestParam String to,#RequestParam String from,#RequestParam String cc,#RequestParam String body, #RequestParam(required = false)MultipartFile[] file){
}
or
create pojo class for strings
public class Email{
private String from;
private String to;
private String cc;
private String body;
// getters and setters
}
//email should be json string
public void sendEmail(#RequestParam String email,#RequestParam(required = false) MultipartFile[] file){
ObjectMapper mapper=new ObjectMapper();
Email email_pojo=mapper.readValue(email,Email.class);
}
Just create the controller as specified below:
#RequestMapping(value = "/uploadFiles", headers = ("content-type=multipart/*"), method = RequestMethod.POST)
public AppDTO uploadFile(UploadFiles uploadFiles, HttpServletRequest request) {
Now create a pojo class for what ever things you need to submit along with a multipartfile member where the file will bind to. refer below code for pojo
class UploadFiles
{
private String cc;
private String to;
private String from;
private MultipartFile attachment;
//create getters and setters
}
MultipartFile here used is provided by spring
import org.springframework.web.multipart.MultipartFile;
If you have more than one attachment you can use MultipartFile[] in POJO

Spring Request Mapping post vs put, same method, same logic, but

I have a 2 method:
first one create product:
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> create(#Validated ProductDTO productDTO){
productService.addProduct(productDTO);
return new ResponseEntity<>("Maxsulot ro'yhatga qo'shildi", HttpStatus.OK);
}
another one update product:
#RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<?> update(#Validated ProductDTO productDTO){
productService.update(productDTO);
return new ResponseEntity<>("Maxsulot ma'lumotlari yangilandi", HttpStatus.OK);
}
Now, I am surprized that, if I sent same data post method works fine(screen1), but put(screen2) method return validation error.
screen1(post)
screen2(put)
What the problem is?
MyDTO class:
public class ProductDTO {
private Long id;
private MultipartFile file;
#NotNull
#Size(min = 2, max = 50)
private String productName;
#NotNull
private Long productPrice;
private String productInfo;
#NotNull
private Long categoryId;
private String unitOfMeasurement;
// getters and setters
}
I can see you have #Validated that should validate your request body according to JSR-303.
Seems like it is not consistent when you POST and PUT. It validates/not validating and return an error because your body does not match the validation rules you placed on ProductDTO.
In all the docs I saw you should do something like #Valid #RequestBody instead of just putting #Validated.
Try to change it to the above and see if it now work more consistently.

Resources