Spring REST ResponseEntity how to return response when we have two objects - spring

1. For example UserProfile which has 3 properties name,dob, age
2. And 2nd class let's say UserProfileResponse which has only "id"
public ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile)
{
UserProfileResponse userProfileResponse = new UserProfileResponse();
userProfileResponse.setId(??) // How do I set ID?
**createUserProfileData(userProfile) /// This is used to create DB record**
return new ResponseEntity<UserProfileResponse>(userProfileResponse,HTTPStatus.OK);
}
So for this userProfileResponse.setId(??) how can I set the ID value?
can I directly do like this userProfileResponse.setId(userProfileResponse.getId());
Or I can Pass one more request body like this
ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile, #RequestBody ID)
Thanks in advance.

You can call createUserProfileData method and return the id of the newly inserted object from it.
In createUserProfileData method, you can call saveAndFlush method of the repository which will save the userProfile Object.
This will return the id of the newly inserted object.
Finally your code will look like below:
public ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile)
{
UserProfileResponse userProfileResponse = new UserProfileResponse();
int id = createUserProfileData(userProfile)
userProfileResponse.setId(id)
return new ResponseEntity<UserProfileResponse>(userProfileResponse,HTTPStatus.OK);
}

If you want to get a value from the RequestBody UserProfile which it didn't contain it actually.Sorry it's impossible.
And we only could receive one requestBody at one time,so we need to use some other ways to collect the info.There is some other solutions:
Use #PathVariable to get ID from url
Use #RequestParam to get Id from requestParam
Add a new field named Id into your UserProfile
Use other way that that could get your Id,this depend how you persistent or generate the Id.
In your case,I'm not sure what you are going to do with the id.
If the "createUserProfileData" method means you need to offer an id first for persistence.
Well,I dont know which database and what kind of framework you are using.As I know,most of framework and database has the ability to generate the id automatically.But if you insist to generate id by your self,I recommend you UUID.
If the "createUserProfileData" method is saving the UserProfile to the database literally and the id is generated by the database itself,then you just do it and put the Id represent the record you just saved to UserProfileResponse.
As to how to get the id represent the record you just saved?It's up to the framework you're using and precisely how the code is written.

Related

How to pass ID parameter for GET method without it being directly in the uri

For my school project I'm trying to build an API that allows students to basically CRUD school applications. API is divided into two modules, first one uses IDs directly in uris to access the data like in example below:
#GetMapping("/students/{id}/applications")
public ResponseEntity<List> getStudentApplications(#PathVariable Long id){
Optional<Student> studentById = studentRepo.findById(id);
if(studentById.isPresent()){
return new ResponseEntity<>(studentById.get().getApplications(), HttpStatus.OK);
}
else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
And the second module consumes previous API while not using variables like studentID in uri, because students wont be able to browse other's applications so why include them:
#GetMapping("/my-applications")
public ResponseEntity<List> getApplications(){
return restTemplate.getForEntity("http://localhost:8081/students/{id}/applications", List.class, 1L);
}
My question is how can I pass the id variable to the restTemplate, without it being explicitly in the uri. Example above is obviously hardcoded for the id to be 1

Insert images in database

I'm making a real estate app in spring boot - thymeleaf and I really need to ask you how to store images. I was thinking about making a table just for images and anotate it manyToOne, and insert it into Property entity because one property can have 10,15,20 images and that is the part I know how to do.
But I'm not sure how to handle the rest of the code. How to make file upload in the /add method?
And also howadd and show them in thymeleaf?
This is my /properties/add method without the option of inserting images:
#RequestMapping("/add")
public String add(Model theModel) {
Property theProperty = new Property();
User theUser = new User();
theProperty.setUser(theUser);
List<User> userList = userService.findAll();
Address theAddress = new Address();
theProperty.setAddress(theAddress);
List<Address> addressList = addressService.findAll();
theModel.addAttribute("property", theProperty);
theModel.addAttribute("user", userList);
theModel.addAttribute("address", addressList);
return "properties/property-form";
}
I don't expect you to type it but maybe somebody know the most similar project
I don't think you wanna store the images directly to the database but having a table as a reference to the image itself.
You can do it the same way as you are doing with the userList.
theProperty.addAttribute("images", imageList);

How to get more than one model data in Spring Controller

I'm a spring newbie.
I'm doing this spring-boot project where I have 2 tables for users viz user and user_details. I've made 2 models corresponding to the tables.
When the client fills up the user form, the data for both the user model and user_details model are coming from a same stream. In such a case, how do I handle 2 data models in the controller?
A case for getting a single model object, the controller function would be:
#RequestMapping(method = RequestMethod.POST, value= "/user")
public void add(#RequestBody User user) {
// do stuffs on model
}
How do we address the issue if two models' data are arriving in that post request?
You can use MultiValueMap, something like below ,replace string with your custom objects.
//Create a multimap to hold the named parameters
MultiValueMap parameters = new LinkedMultiValueMap(); parameters.add("userName", marshalRequest(userNameObj)); parameters.add("password", marshalRequest(passwordObj));
// Create the http entity for the request HttpEntity> entity = new HttpEntity>(parameters, headers);

How to update a row by id in jpa hibernate?

I was trying to update a row in db by fetching the idByName, but instead it's adding a new row? Please help me out.
This is my controller code:
#PostMapping("/retailer/update")
public ModelAndView updateRetailer(#ModelAttribute("retailer") Retailer retailerDetails)
{
System.out.println(retailerDetails.toString());
System.out.println("method called");
UUID id=repository.findIdByName(retailerDetails.getBusinessName());
System.out.println(retailerDetails.getBusinessName());
System.out.println(id);
String name=retailerDetails.getBusinessName();
System.out.println(name);
//Retailer retailer=repository.findOne(rid);
if(id == null)
{
return null;
}
retailerDetails.setBusinessName(retailerDetails.getBusinessName());
retailerDetails.setCity(retailerDetails.getCity());
retailerDetails.setIsActive(retailerDetails.getIsActive());
retailerDetails.setStartDate(retailerDetails.getStartDate());
retailerDetails.setUrl(retailerDetails.getUrl());
repository.save(retailerDetails);
return new ModelAndView("welcome");
}
This is my Repository code:
public interface RetailerRepository extends JpaRepository<Retailer, UUID>{
#Query("SELECT r.id FROM Retailer r where r.businessName=:name")
UUID findIdByName(#Param("name") String name);
}
You should forget to set the "id" to the retailerDetails entity. Spring JPA will only execute the update action when the primary key is set.
Added the following line in your code.
retailer.setId(id);
repository.save(retailer);
You should simply fetch by BusinessName.
Repository method be:
Retailer findByBusinessName(#Param("name") String name);
updateRetailer method be like:
Retailer retailer = findByBusinessName(retailerDetails.getBusinessName());
if(retailer!=null){
retailer.setBusinessName(retailerDetails.getBusinessName());
retailer.setCity(retailerDetails.getCity());
retailer.setIsActive(retailerDetails.getIsActive());
retailer.setStartDate(retailerDetails.getStartDate());
retailer.setUrl(retailerDetails.getUrl());
repository.save(retailer);
}
Your controller looks great and so is your repository. There is something that you should know when it comes to updating an entity with hibernate. Hibernate will save(create new object) if the id for the given item is null during the transaction and hibernate will save(update the current instance in the database) if the id exist.
The flow for this update I presume is when the request to update is requested, you retrieve the object based on the specified entity then return to the view. One thing to take note of is to carry your id with your even in the view.
Make sure you include the id in a hidden input like
from there the id will be submitted in addition to the updated data to the post method.
Most update issues similar to this can be fixed by versioning entity with the #Version
Use the format of the Spring Data JPA to successfully query without writing any query.
#Repository
public interface RetailerRepository extends JpaRepository{
// Assuming there is an attribute businessName in the Retailer entity.
UUID findByBusinessName(String businessName);
}

Manipulate WebAPi POST

I have a WebAPI POST controller like the one below:
[ResponseType(typeof(Product))]
public async Task<IHttpActionResult> PostProduct(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = product.Id }, product);
}
To be valid, it expects several values, lets say Name, Price, URL, ManufactureID, StatusID.
However, the POST will not always contain a value for StatusID for example, and therefore the above will fail, as i cannot be null.
But when the value is not sent by the POST, i want to 'intercept' and set the value in code. Let say to int 1.
How would i go about this?
I have been using DTOes for extraxting data from the API, in a nice and viewable way. Can DToes be used in POST also? If so, how? Or any other approach, to setting data, if it does not excist in the POST?
I would say create your Product request model which will be defined in your WebAPI models and there your can define your StatusID as a nullable. After your receive request you can map your Product request data to ProductDto and in that mapping you set your default values if you need them.
Altough you can intercept request on client side and update it but I'm not sure is that something that will work for you.
You should create a POST product class that is agnostic of the persistence. Don't use the generated Product class of your ORM. Using your example above, you should have a ProductModel class that will only contain the properties that the API client can update. Then do the mapping of the DTO to your product data model.
public async Task<IHttpActionResult> PostProduct(ProductModel model)
{
...
var product = db.Products.New();
//mapping here
product.Name = model.Name;
product.Price = model.Price;
}

Resources