How to get more than one model data in Spring Controller - spring-boot

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);

Related

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

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.

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;
}

Mvc: Alternative for form collection to better handle huge amount of parameters

I have a form that has just 3 fields and I am writing this
to a database by passing the values using a form collection to
the business layer.
Assuming I have 35 fields on my form and wants to write this
to the database. Is there a better way of doing this than
listing 35 fields in my code. I want to reduce the amount of code
I write.
[HttpPost]
Public ActionResult Create(FormCollection objFrmCollect)
{
Employee employee = new Employee();
employee.Name = objFrmCollect["Name"];
employee.Gender = objFrmCollect["Gender"];
employee.City = objFrmCollect["City"];
EmployeeBusinessLayer empBus = new EmployeeBusinessLayer();
empBus.AddEmployee(employee);
return RedirectToAction("Index");
}
You should use Model Binder like this:
public ActionResult Create(Employee employee)
It will automatically populate employee model with posted values.
Here is more information about model binding:
http://www.codeproject.com/Articles/710776/Introduction-to-ASP-NET-MVC-Model-Binding-An-Absol
Automatic conversion of form collection to a model class can't be direct. So the best way you should use is from the view where you are fetching the form collection, you should use directly model properties. i.e. you should bind it to a model.
So the alternative for form collection to handle huge amount of parameters is binding it to model

Spring MVC: How to retrieve data apart from the Model submitted to a view

I have the following requirement. I submit a Model object to a view as follows...
#RequestMapping(value ="/addItem", method = RequestMethod.GET)
public ModelAndView showContacts() {
ModelAndView modelAndView = new ModelAndView("addItem", "command", new Item());
return modelAndView;
}
But on post, I need to retrieve a value apart from the "Item" object (model) that is returned to me. I can't have this variable be a part of the Item model object because it does not belong there. But I need it returned in order to act on that value. How can I get about doing this ?
I.e. In my JSP file, I have the following fields...
<form:input type="text" path="val1"/>
<form:input type="text" path="val2"/>
<form:input type="text" path="val3"/>
Out of the above, only fields val1 and val2 have mappings to the Item object, where as val3 does not. Nevertheless, I need the value of val3 passed back to my controller as well. The code I have right now to handle the POST is as follows, but I can't figure out how to get the value for val3. The code does not compile right now because it says that there is no field or appropriate getter method in the Item class for val3.
#RequestMapping(value = "/postItem", method = RequestMethod.POST)
public String postItem(#ModelAttribute("item") Item item , BindingResult result) {
logger.info("Post Item:");
return "home";
}
How can I modify the above code to suite my requirement ?
Some guidance on this matter will be highly appreciated.
You can pass a map as the model, and include all sorts of different things in there. You are not limited to a single domain object, that constructor is there as a convenience, it is not the only way to do it. There is a variation of the constructor:
public ModelAndView(Object view,
Map model)
Create a new ModelAndView given a View object and a model.
Parameters:
view - View object to render (usually a Servlet MVC View object)
model - Map of model names (Strings) to model objects (Objects).
Model entries may not be null, but the model Map may be null if
there is no model data.

Setup knockoutJS view model to bind to one-to-many property

I have a controller in grails that I am sending an ajax JSON post to with a knockoutJS view model. The view model (along with a javascript object) looks like this:
var childProperty= function(name, id) {
this.name = name;
this.id = id;
};
//KnockoutJS - Main view model
var viewModel = {
id: ko.observable(1),
childProperty: ko.observable(new childProperty("Chuck",1))
}
The data model on the controller side is trying to automatically use the Spring binding magic and bind the JSON request parameters to a new instance of my data model like so:
def jUpdate = {
def update = new SomeObject(params)
}
The problem comes in when I want the Spring binding to detect that childProperty.id is a one-to-many relationship in the data model and to go fetch the related property in the data model. The Grails documentation says this:
Data binding and Associations
If you have a one-to-one or many-to-one association you can use
Grails' data binding capability to update these relationships too. For
example if you have an incoming request such as:
/book/save?author.id=20
Grails will automatically detect the .id
suffix on the request parameter and look-up the Author instance for
the given id when doing data binding such as:
def b = new Book(params)
I am using the ko.toJS utility function and the simple properties are binding correctly. How can I set the view model child property up so that when it is posted to the grails controller, Spring detects it properly and fetches the associated record and builds the object?
I was never able to get the automagic spring bindings to work, so I just passed over the id for the child objects and manually set them on the server side in the params map. After that, GORM fetches the record appropriately. Something like this:
def update = {
params.put("childObject.id",params.childObjectId)
params.remove("childObjectId")
def parentObject = new ParentObject(params)
}
This fetches the related items and builds the object. If you had a lot of related fields, this would become a painful process.

Resources