What data is sent as part of http response - spring

What is actually sent within a http request response ?
In below simple spring controller a String is sent to client. But this string is wrapped in some html elements that the browser understands ? Is this response always the same but different frameworks just provide different convenient methods/annotations to make the process simpler ?
#RequestMapping(value="myrequest", method = RequestMethod.GET)
public String redirect(#RequestParam String param) {
return "test";
}

In Spring MVC Framework, the lifecycle of an HTTP Request is something like this:
The user makes a request of a resource, and Spring' DispatcherServlet delegates that request to an specific controller method (like redirect). This is made through a Handler Mapping that can use -for example- the annotations (like #RequestMapping) in the controllers to select an appropriate one.
Tipically, Controller methods return instances of ModelAndViews, that are the classes responsible of generating some Markup (HTML, JSON, XLS a.k.a the View) and show some information in that Views (The Model). It is possible also that Controllers return Views Logical Names (like test)that should be later resolver in ModelAndView instances by a View Resolver.
The View Resolver selects and appropriate view based on the Logical Name returned by the Controller, and then the View generates the Markup that is sent to the browser. For example, JstlView generates HTML Markup and AbstractExcelView generates XLS files.
So to answer your question, you must find what View Resolver is configured in your application context and find what markup is produced.

Related

Does ModelAndView serialize model before sending response to client

In spring mvc, when we return ModelAndView / Model object, does this get serialized to be sent on HTTP?
Just like it happens in REST API that the #ResponseBody annotated method returned value is serialized.
If not, how is Model object transferred over HTTP in Spring MVC as I have read that objects can't be transferred over HTTP without serialization?
It depends. It depends on the view technology in use. But for most they will be exposed as request attributes and that is done in the View. The AbstractView has code for this which is used by most View implementations.
For something like Freemarker the model is exposed both as request attributes but also added to the Freemarker internal model object. This is so that Freemarker can render the page and you could also use tags in the template to retrieve the request attributes.
Depending on the actual view technology used if something gets serialized depends. For things generating HTML, PDF, Excel etc. nothing will be serialized. All the rendering and processing is done on the server and the end result (the complete view) is being sent to the client.
However, for view technologies like the MappingJackson2JsonView (there are others as well) that will actually serialize the model using Jackson. But in the end, this will be JSON that is sent over HTTP.
So what is sent over HTTP is at least never the actual model but depends on the view technology in use.

How do I test form submission with Spring MVC test?

Most of my experience with creating controllers with Spring are for REST controllers that consume JSON formatted requests. I've been searching for documentation on how to do testing for form submission, and so far this is how I understand it should go using MockMvc:
MvcResult result = mockMvc.perform(post("/submit")
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
However, I'm not sure how to map the form parameters to a model object. I've seen the #ModelAttribute annotation pop up in my searches but I can't figure out how it should be used for mapping. In addition, this quick start guide from the official documentation does not elaborate on how things like th:object and th:field translate to HTML and subsequently to URL encoded form.
I have my controller code similar to the following:
#PostMapping('/submit')
def submit(#ModelAttribute WriteUp writeUp) {
//do something with writeUp object
'result'
}
I discovered through trial and error that my specific problem might have been Groovy specific. There test code and the controller code, it turns out, have no issues. To reiterate, for testing form submission, use the param method through perform method of MockMvcRequestBuilders. Another thing to note is that this doesn't seem to work if content type is not specified. Here's a sample test code that works for me:
MvcResult result = webApp.perform(post("/submit")
.contentType(APPLICATION_FORM_URLENCODED) //from MediaType
.param('title', 'test title')
.param('description', 'test description'))
.andReturn()
As you can see, it's not much different from what I posted originally. The controller code is pretty much just the same, with #ModelAttribute working just fine.
The problem with my setup though was that since I was using Groovy, I assumed that getters and setters were automatically generated in my WriteUp class. Here's how the WriteUp class looked originally:
class WriteUp {
private String title
private String description
}
I haven't written code in Groovy for a while, and the last time I did, classes like the one above can be assumed to have getters and setters implicitly. However, it turns out that is not the case. To solve my specific issue, I updated the access modifier in the fields to be default (package level):
class WriteUp {
String title
String description
}
I've seen the #ModelAttribute annotation pop up in my searches but I
can't figure out how it should be used for mapping.
When you mark your writeUp object with #ModelAttribute, then the Spring container populates the parameters (like title, description, etc..) from HttpServletRequest object & injects the object to the controller method, when the request comes to the server from the client (could be a Browser or MockMvc unit test client or anything else).
Also, few other basic points for your quick understanding:
(1) Controller methods are mapped to an URI and RequestMethod (like POST/GET/DELETE/PUT et..) like shown below:
#RequestMapping(value="/submit", method=RequestMethod.POST)
public String submit(#ModelAttribute WriteUp writeUp) {
//Call the service and Save the details
model.addAttribute("Writeup details added successfully");
return "writeUpResult"; //Returns to the View (JSP)
}
(2) #ModelAttribute will be mapped to an object (like your writeUp) for http POST/PUT requests where the html formd data is part of http body.
(3) #RequestParam or #PathParam will be used for http GET requests where the parameters are part of URL (i.e., not part of http body).
You can look here for understanding the DispatcherServlet request handling & Spring MVC basic web flow.

#ModelAttribute returns a new instance on form submit

I am working on a Spring MVC based application. The process flow is as follows:
Fetch the data from DB (table mapped to a POJO)
Display a form backed by the POJO (from step 1). Not all the fields are displayed (like Primary Key etc).
User can update some field value in the form and will then submit.
On receving the updated POJO using #ModelAttribute annotation in my Controller, I found that not all the fields are populated in the POJO received via #ModelAttribute. All the fields which were not mapped on the JSP (like primary key) are set to null or their default value in case of primitives. Due to this I am not able to update the same in the DB.
One solution that I found is I can use fields but that does not sound much efficient solution as I have a large number of attributes which are not displayed on the JSP page.
A model attribute is simply a glorified request attribute. Request attributes only live for the duration of one request-response cycle.
HTTP request -> Get POJO from DB -> Add POJO to model attributes -> Render JSP -> HTTP response
After that, the request attributes are eventually GC'ed since they are no longer reachable by the application (the servlet container makes sure of that).
The next request you send will have its set of new request attributes with no relation to the previous requests'.
When you generate a <form> from a model attribute, Spring creates the <input> elements from the fields of the model attribute which you choose. When you eventually submit the form, only those values will be sent as request parameters in the request. Your application will therefore only have access to those to generate the new model attribute.
You seem to need Session attributes or Flash attributes (which are really just short-lived session attributes).
Please if somebody know a better solution please let me know, but on my application we are always sending back all those id´s and others values that we want to persist in the request response with hidden fields, but I think is a little bit risk, for example in case of id´s. which could be used for SQLInjections attacks.
You could use path variable to transport the primary key (kind of rest url ...) and make use of all the magic of Spring :
create a DefaultFormattingConversionService bean (to keep default conversions)
register (in that ConversionService) a Converter converting a String in your POJO (string -> primary key -> object from database)
directly use the path variable in your controller methods
#RequestMapping(value=".../{data}/edit", method=RequestMethod.GET)
public String edit(#ModelAttribute("data") Pojo pojo) {
return "view_with_form";
}
#RequestMapping(value=".../{data}/edit", method=RequestMethod.POST)
public String update(#ModelAttribute("data") Pojo pojo, BindingResult result) {
if (result.hasErrors()) {
return "view_with_form";
}
return "redirect:.../data/edit";
}
When you give a ModelAttribute to a controller method, Spring tries to find it in the session or in a path variable. And even if you didn't asked for it, the error management is not very expensive ...

ASP.NET Web API Deserialize Query Parameters into Nested POCO Action Parameter

Already checked this question but didn't answer.
Background
I have a fully functional RESTful web service written using ASP.NET Web API and it currently supports CORS effectively for cross-origin access from browsers that support CORS. Problem is that current business needs require support of browsers that don't support CORS. I am adding JSON-P support to my web service in addition to supporting CORS and through the magic of action selectors and type formatters, my actual web service code hasn't changed....yet.
Currently I use nested POCO objects (objects that contain other objects) as parameters, for example, for my Post actions. Since I'm supporting XML and JSON incoming, the POST data gets deserialized nicely into the POCO objects, since both XML and JSON support nested deserialization. But to support JSON-P, I have to now emulate a POST through Query Parameters. Getting to the Post action method is successful via an httpMethod Query Parameter and a custom action selector.
Question(s)
First of all, and I ask this after reading responses to other questions, will the registered type formatters even access the Query Parameters for deserializing if I have no request body? The JSON-P request is going to be a simple GET request with no body, so I'm not even sure if it is possible to have a POCO in my action parameter and have it deserialized with a GET request and only Query Parameters.
EDIT: Looks like I may be able to do some MediaTypeFormatter magic with a custom formatter and using the QueryStringMapping. Not sure yet though.
Second, is it possible to deserialize Query Parameters into nested properties of the POCO object? And if so, what is the naming convention for Query Parameters to do this? For example XML of Bob would get deserialized into Message.User.FirstName if the action parameter was of type Message.
EDIT: FormUrlEncodedMediaTypeFormatter has some of the functionality that I want if I could just redirect it to use the Query String instead of the body. But I also don't want a JToken object -- I'd like my POCO, but I think I can deserialize a JToken with JSON.NET. So I'm probably going to steal the code from FormUrlEncodedMediaTypeFormatter and the relate internal class FormUrlEncodedJson to make a custom formatter. Just need to make sure question #1 is possible first.
Example POCOs
public class User
{
public string FirstName { get; set;}
}
public class Message
{
public User User { get; set; }
}
Example "standard" RESTful POST
POST /api/messages
Content-Type: text/xml
<Message><User><FirstName>Bob</FirstName></User></Message>
Example Hypothetical JSON-P Simulated POST
<script type="text/javascript"
src="https://api.mydomain.com/api/messages?callback=MyCallback&httpMethod=Post&User.FirstName=Bob">
</script>
EDIT: Overall Goal: I'm trying to leave the action methods alone right now if possible since they currently handle RESTful CORS-enabled requests. My goal is to add JSON-P support to the calls without changing the method signature. I've got that mostly accomplished; all I have left is being able to deserialize the Query Parameters into the action method parameters when it's a JSON-P request.
Try adding [FromUri] to your action definition, i.e.:
public HttpResponseMessage YourAction([FromUri] YourModel model)
{
...
}
At this point in time it seems that I must create two different paths in the API. Because of the way request parameter deserialization works, and model binding vs. media type formatters, and the lack of a hook in this particular area, I cannot have one single Web API method and have the parameters taken from either the query string or the content based upon various request factors.

how to organize & implement jsp file structure using Spring

I'm a php programmer now doing a Java web project using Spring framework. I'm trying to organize my JSP files the way i would have organized my .tpl files in php.
So if it would have been php i would have done it like this:
index.tpl
includes one of layout.tpls (ajax.tpl, mobile.tpl, general.tpl, simplified.tpl . . .)
includes the header of the page
includes menus
includes the actual content of the page
includes the page footer
then from the php controller i would be able to do something like this:
setLayout('general');
showTopMenu(false);
setContent('mySexyPage');
beside that i would have organized my stuff so that my views (tpl files) will be organized in folderы each corresponding to a single controller. like this:
userManager
addUSer.tpl
editUser.tpl
editUserPermissions.tpl
articleManager
addArticle.tpl
editArticle.tpl
and in each controller somehow define from which folder to load my content template.
Now in Spring i have a controller with methods handling requests and each of the methods returning what the view should be. I can extend all my controllers from a single abstract class where i will create an instance of ModelAndView with all default values set, then request handling methods will add what they need to the instance their daddy already created and return it.
The problem with the above approach is that i'm not forcing the coder who's writing controllers to use the ModelAndView object i created, he way still return anything he wants from the handling method he wrote.
Is there some interface containing a method like ModelAndView getModelAndView() my daddy controller will implement so Spring will ignore whatever handler methods are returning?
Or is there some better way to do this ?
Content Template Issue
The Java world has a (more than one actually, but I'm sticking with the one I know) solution for this problem, it is called Tiles. check out section 16 of the Spring 3.0.5 Reference.
ModelAndView Issue
This is more interesting. First, you can use Model with out view and have your controllers just return the view name (i.e. return a String). I believe you want to create the initial Model somewhere. Then have each controller hander method accept an argument of type Model.
Here is what I tend to do (no claim that it is a best practice):
Have a Controller.get(Model model) method that sets the initial values.
#RequestMapping(method = RequestMethod.GET)
public String get(Model model)
{ ... set default stuff ... }
Every Handler method is a variation of this:
#RequestMapping(value = "/search", method = RequestMethod.POST)
public String search(Model model, ... other stuff as needed ...)
{ ... set stuff in model ... }

Resources