Spring getting error in get attribute method - java

I want setting the attribute in first modelandview method with the help of bean and trying to get the attributes in other modelandview method in same controller but getting null value my code is below
#RequestMapping(value="/insert",method=RequestMethod.POST)
public ModelAndView inserData(#ModelAttribute SavingBeansavingBean,HttpServletRequestrs,Model m) {
System.out.println(savingBean.getFirstName());
if (savingBean != null)
System.out.println("abho");
SavingBean saving = persionalService.insertData(savingBean);
custid = saving.getCustomerId();
System.out.println(custid);
m.addAttribute("customId",saving);
System.out.println(saving.getDisgnProf());
List<SavingBean> list = new ArrayList<SavingBean>();
list.add(saving);
return new ModelAndView("AccountInfo","list", list);
}
#RequestMapping(value="/accinsert",method=RequestMethod.POST)
public ModelAndView inserData(#ModelAttribute AccountBean accbean,HttpServletRequest rs,Model m) {
SavingBean b = new SavingBean();
System.out.println("saas" + b.getCustomerId());
session = rs.getSession();
System.out.println("xxx" + rs.getAttribute("customId"));
accbean.setCustid((Long) rs.getAttribute("customId"));
AccountBean accbean1 = persionalService.insertacc(accbean);
return new ModelAndView("welcome");
}

From the first look to your code , I notice that your request method not specified. At this case (When using #ModelAttribute) you have to make it as (POST) request.
#RequestMapping(value = "/insert", method = RequestMethod.POST)
#RequestMapping(value = "/accinsert" , method = RequestMethod.POST)
Why ? because actually your object will be retrieved due to Form Submission which is treated as POST request. Try that thing and check the results. If the problem is still maybe you have some real problem in your Presentation Layer (e.g JSP Page) that is responsible about submitting the data.
Good Luck !

Related

Get back an Object List from a Spring controller to a AJAX request

I want to return a List of object from a Spring controller to an AJAX request.
AJAX request:
function doAjaxPost(date) {
$.ajax({
type : "POST",
contentType : "application/json",
url : "<%="/water-consumer" + homepageURL + "/hourConsumption"%>",
data : date,
dataType : 'json',
success : function(response) {
if(response != null)
showHourConsumption(response);
}
});
}
Spring controller:
#RequestMapping(value = "/{username}/hourConsumption", method=RequestMethod.POST, produces="application/json")
public #ResponseBody List<HourConsumption> getHoursConsumptions(#RequestBody String day, HttpSession session, Model model) {
// do something ....
Household household = (Household)session.getAttribute("household");
List<HourConsumption> consumptions = this.mrs.getHoursConsumption(household.getSmart_meter().getOid(), day);
// do something
if(consumptions == null) //check if what get back from something is not null
return null;
else
return consumptions;
}
Now, the AJAX request goes right, so I receive the request from the controller and it generates the correct consumptions (List) but when it returns the List, the browser gives me back the following error:
Failed to load resource: the server responded with a status of 406
(Not Acceptable)
Someone could tell me how can I do this things or the correct way to do so?
Thank you very much!
Make sure that following 2 jar's are present in class path.
If any one or both are missing then this error will come.
jackson-core and jackson-mapper
A few pointers:
The http method can be a GET iso a POST.
Remove session and model parameters. If you need session then you can obtain it from an Autowired HttpServletRequest.
Make sure you have Jackson as dependency
The problem is with the data you are returning, to the browser is not well formed JSON. Then I would remove the attribute "produces" from your Controller, and leave the Spring Jackson transformer to create the json entities.
Change your code to this:
#RequestMapping(value = "/{username}/hourConsumption", method=RequestMethod.POST)
public #ResponseBody List<HourConsumption> getHoursConsumptions(#RequestBody String day, HttpSession session, Model model) {
// do something ....
Household household = (Household)session.getAttribute("household");
List<HourConsumption> consumptions = this.mrs.getHoursConsumption(household.getSmart_meter().getOid(), day);
// do something
if(consumptions == null) //check if what get back from something is not null
return null;
else
return consumptions;
}
Try using Google's gson (https://mvnrepository.com/artifact/com.google.code.gson/gson) to send Json format String to the page.
Spring Controller
#RequestMapping(value = "/{username}/hourConsumption", method=RequestMethod.POST)
public #ResponseBody String getHoursConsumptions(#RequestBody String day, HttpSession session, Model model) {
String jsonFormatData = "";
// do something ....
Household household = (Household)session.getAttribute("household");
List<HourConsumption> consumptions = this.mrs.getHoursConsumption(household.getSmart_meter().getOid(), day);
// do something
// **Using Gson**
// You can include this in your bean definition and autowire it
// and use the singleton created by Spring.
// For this example I am instantiating Gson myself
Gson gson = new Gson();
jsonFormatData = gson.toJson(consumptions);
return jsonFormatData;
}

Spring MVC + Thymeleaf: passing objects through pages

I'm developing a simple web application using spring MVC and thymeleaf. I have a form correctly handled by this method in my controller
#RequestMapping(value = "/list", method = RequestMethod.POST)
public ModelAndView searchJob(
#ModelAttribute(SEARCH_PARAMS) #Valid SearchParams params,
BindingResult bindingResult) {
ModelAndView output = null;
if (!bindingResult.hasErrors()) {
JobsAPIImplService service = new JobsAPIImplService();
JobsAPI api = service.getJobsAPIImplPort();
ArrayList<NoaJob> jobs = (ArrayList<NoaJob>) (api.search(JobUtils.toSearchParams(params))).getItem();
output = new ModelAndView("scheduler/list");
output.addObject("jobs", jobs);
} else {
// errors handling
}
return output;
}
So in my result page I can access to the ArrayList "jobs" in this way:
<tr th:each="job : ${jobs}">
...
</tr>
In the same page, I have a simple link which calls another GET method on the same controller. The goal here is to have the same ArrayList in another page in order to implement a "back" button without re-executing the search logic (a call to a web service).
Here is the method called
#RequestMapping(value="/list/{id}", method = RequestMethod.GET)
public ModelAndView details(#PathVariable("id") String jobUuid,
#ModelAttribute("jobs") ArrayList<NoaJob> jobs) {
ModelAndView output = new ModelAndView("scheduler/details");
LOGGER.info("Size jobs list: " + jobs.size());
NoaJob job = new NoaJob();
job.setJobUuid(jobUuid);
output.addObject("job", job);
output.addObject("jobs", jobs);
return output;
}
the problem is that the arraylist here is always null! I read that in GET requests Spring allocates a new ModelAttribute, so how can I pass this object throug pages?
Define a session attribute like this in the head of your controller:
#SessionAttributes({ "myFancyList"})
#Controller
public class HomeController {
// your code here
}
Now.. when you have to insert the "list" to be viewable via thymeleaf:
output.addObject("myFancyList", jobs);
and modify thymleaf pseudocode accordingly.
in the "post" of the search "override" the session attribute with the current search result..
i think this should do the trick for you

Spring 3.2 mvc, how to rewrite url within controller as part of redirectview with permanent status code sent

#RequestMapping(value = "/Foo/{id}/{friendlyUrl:.*}", method = RequestMethod.GET)
public ModelAndView getFoo(#PathVariable final Long id, #PathVariable final String friendlyUrl) {
So it matches ID, and any string. But I want the user to see a string I specify.
foo = fooService.get(id); //use id from pathvariable
redirectView = new RedirectView(foo.getCorrectUrl()); //set url to correct url, not that in path
redirectView.setStatusCode(HttpStatus.MOVED_PERMANENTLY); //moved permanently
modelAndView = new ModelAndView(redirectView);
modelAndView.setViewName("myFoo.jsp");
return modelAndView;
Everything works fine, except the url the user see's is incorrect.
It is (supposed to be) the same functionality as when a question title gets changed on a existing question on the stackoverflow site.
Edit, now doing the below that almost works
return new ModelAndView("redirect:/Foo/"+id+"/"+foo.getUrl());
But that returns a temporarily moved status code, I want permanent 301.
is their a way to get both a rewritten url, and a permanently moved status code using spring-mvc controllers ?
In your code you have
foo = fooService.get(id); //use id from pathvariable
redirectView = new RedirectView(foo.getCorrectUrl()); //set url to correct url, not that in path
redirectView.setStatusCode(HttpStatus.MOVED_PERMANENTLY); //moved permanently
modelAndView = new ModelAndView(redirectView);
modelAndView.setViewName("myFoo.jsp");
return modelAndView;
The call to modelAndView.setViewName("myFoo.jsp"); effectively replaces the value of View (redirectView reference) that was passed to ModelAndView contructor.
So you should not call setViewName in this case.

Persisting object data between controllers in Spring

I have an object called Request which is the main object of my portal that stores all the information of a request, the user, their form selections, etc. How to I persist all the previous information in between the different forms? In each .GET I have to set the request object, and then in each .POST, the only information that is passed to it is what is in the forms on the .GET pages. So on each page I have to have hidden fields such as
<form:input path='requestId' style='display:none' />
<form:input path='currentUserId' style='display:none' />
<form:input path="step" style='display:none' />
I need these fields, and would also like to have the rest of the fields in the request object that are not on the form without having to repeat that for each and every field in my object.
#RequestMapping(value = "/review", method = RequestMethod.GET)
public ModelAndView showCorReview(#RequestParam(value = "requestId") String requestId,
#CookieValue(value = "EMP_ID", defaultValue = "168") int userId)
{
Request request = requestManager.getRequestById(Integer.parseInt(requestId));
request.setCurrentUserId(userId);
String pageTitle = "2.1: Initiate New Service Request -- (Review)";
ModelAndView mav = new ModelAndView();
mav.setViewName("newRequest/review");
mav.addObject("title", pageTitle);
mav.addObject("request", request);
mav.addObject("cpm", userManager.getUserById(request.getCpm()).getName());
return mav;
}
#RequestMapping(value = "/review", method = RequestMethod.POST)
public String saveReview(Request request, #RequestParam(value = "commentData", required = false) String[] additionalComments)
{
if (additionalComments != null)
commentLogManager.addCommentLog(additionalComments, request);
if (request.getRejectReason() == "")
{
request.setCpm(admin.getCPM(request.getContract()).getId());
request.setCor(admin.getCOR(request.getContract()).getId());
requestManager.updateRequest(request);
}
else
{
if (request.getSubmitType().equals("return"))
{
request.setNextStep(1);
requestManager.moveRequestToStep(request);
}
}
return worksheetUrl + request.getId();
}
Alternatately I could also in the .POST do the
Request request = requestManager.getRequestById(Integer.parseInt(requestId))
Then use setters on all the form fields, but again, I would prefer the data to actually persist on it's own without explicitly calling that.
#Tim, if I understood your requirement correctly, you have a sequence of forms and you would like to transfer information from one form to the next without having to hit a database or copy over request variables from one form to another. I could support #JB Nizel's suggestion of employing HTTP Session, but you may not want to make the session "heavy"; after all, it is the next most persistent scope after application-scope.
Spring Web Flow may be the answer. Flow-scope will allow you to build up form-state as the user progresses from one form to the next. Plus you don't have to worry about form-scoped variables when the flow finishes, unlike session variables that you don't want to have lingering around.

When the validator finds form errors, the form page is redisplayed at the POST url

An item is displayed at this URL:
/item/10101
using this Controller method:
#RequestMapping(value = "/item/{itemId}", method = RequestMethod.GET)
public final String item(HttpServletRequest request, ModelMap model,
#PathVariable long itemId)
{
model = this.fillModel(itemId);
return "item";
}
The page contains a form that submits to the following method in the same controller:
#RequestMapping(value = "/process_form", method = RequestMethod.POST)
public final String processForm(HttpServletRequest request,
#ModelAttribute("foo") FooModel fooModel,
BindingResult bindResult,
ModelMap model)
{
FooModelValidator validator = new FooModelValidator();
validator.validate(FooModel, bindResult);
if (bindResult.hasErrors())
{
model = this.fillModel(fooModel.getItemId());
return "item";
}
return "account";
}
If the validator finds errors in the form, it redisplays the item but instead of displaying it at the original url:
/item/10101
it displays it at its own url:
/process_form
Is it possible to redisplay the form at the original URL?
/item/10101
(I've tried getting the referrer and redirecting to it in processForm but then all of the model contents end up displayed as URL name/value pairs:)
#RequestMapping(value = "/process_form", method = RequestMethod.POST)
public final String processForm(HttpServletRequest request,
#ModelAttribute("foo") FooModel fooModel,
BindingResult bindResult,
ModelMap model)
{
String referrer = request.getHeader("referer");
FooModelValidator validator = new FooModelValidator();
validator.validate(FooModel, bindResult);
if (bindResult.hasErrors())
{
model = this.fillModel(fooModel.getItemId());
return "redirect:" + referrer;
}
return "account";
}
Short answer: No.
What happens is a server-side redirect (forward), which is within the same request, and so the submitted values are preserved (and displayed in the form)
The url will change if you use a client-side redirect (return "redirect:item";), but in that case a new request will come and the submitted values will be lost.
But here are two options that you have:
use the same URL in the mappings for both methods and distinguish them based on request method - GET for the former, POST for the latter. This might be confusing, so document it.
find / implement flash scope for spring-mvc. There's nothing built-in. The flash scope means that values are preserved (in the session usually) for a submit and the subsequent redirect. This option includes the manual handling, by putting the submitted object in the session, and later retrieving & removing it

Categories

Resources