AngularJs how to access Model Attribute value from Spring MVC controller - java

I have a Spring MVC Controller returning a page with an attribute as followed
#RequestMapping(method = RequestMethod.GET, value = "/create")
public ModelAndView getAddAccountView() {
ModelAndView model = new ModelAndView("protected/accounts/AccountAddView");
List<Client> clients=clientService.findAll();
model.addObject("listClients", clients);
return model;
}
Client is a #Entity
in my AccountAddView.jsp file, i'm trying to use the ng-init as follow:
<div class="row-fluid" ng-controller="accountsController as ctrl" ng-init="clients=${listClients}">
and in my app.js, in my controller, i try to access the list of client as followed
var listOfClients=$scope.clients;
but I'm still getting the following error
angular.min-1.5.3.js:116 Error: [$parse:lexerr] http://errors.angularjs.org/1.5.3/$parse/lexerr?p0=Unexpected%20nextharacter%20&p1=s%2033-33%20%5B%40%5D&p2=clients%3D%5Bsoftbank.ui.model.Client%4042%2C%softbank.ui.model.Client%4041%2C%softbank.ui.model.Client%4043%5D
at Error (native)
at http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:6:416
at gc.throwError (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:212:149)
at gc.lex (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:211:16)
at Object.ast (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:216:103)
at Object.compile (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:225:232)
at hc.parse (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:252:380)
at e (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:123:317)
at m.$eval (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:142:463)
at pre (http://localhost:8080/softbank/resources/js/angular.min-1.5.3.js:271:500)
please what is wrong here. why is ng-init generating this errors?
thanks in advance for your answer.

I'm just starting with Angular with Spring so what I'll do is explain how I did it and you can see if it's a viable option for you.
For one, I didn't try to go through the ModelAndView for my data. I let my "regular" controller return the view but got my data via the angular controller and service along with a #RestController on the Spring side (that's two separate Spring controllers then).
To return only the view you have at least two options that I'm aware of. One, you can just return a ModelAndView without a model like so:
public ModelAndView yourView() {
return new ModelAndView("yourView");
}
Or two, return the name of the view as a string like so:
public String yourView() {
return "yourView";
}
In both cases you'd obviously need the correct #RequestMapping.
In my view I had an angular controller function that made a call to my associated angular service which in turn called my #RestController and so on. I initiated the data like so:
ng-controller="MyController as ctrl" ng-init="ctrl.allThings()"
Examples of the code:
Angular controller:
self.allThings = function () {
ThingService.things()
.then(
function (data) {
self.things = data;
},
function (errResponse) {
console.error("Error retrieving thing list");
}
);
};
Angular service:
things: function() {
return $http.get('/things')
.then(
function(response) {
return response.data;
},
function (errResponse) {
return $q.reject(errResponse);
}
);
},
Spring REST controller:
#RequestMapping(value = "/things", method = RequestMethod.GET)
public List<Thing> things() {
return thingService.findAll();
}
I imagine you know the remaining code for the Spring side. Jackson will handle all the object conversions for you.

Old Post but still I would like to answer so that anyone who is using Angular with Spring MVC get some help.
Using model attribute is a challenge with Angular. Earlier I was setting employee data in model attribute like mav.addObject("employee",employee), but when I was trying to use ${employee} inside the jsp, Angular wasn't able to set the java object using ng-init directive because it was expecting a java script object. So I set json inside the model Attribute mav.addObject("employeeJson", empJson) and parsed it using json.Parse() to convert it into Java Script Object and was able to use it with Angular expressions on the jsp Below are the steps which I followed:
1. Spring Controller
In your controller, set json in the model attribute. For e.g.
mav.addObject("employeeJson", empJson);
Make sure before adding it to ModelAttribute, replace quotes with html entity " otherwise there will be error while parsing the json
empJson.replaceAll("\"", "\&\quot;");
2. Jsp
Use angular init directive, data-ng-init="yourController.getEmployeeData('${employeeJson}')"
3. In Angular js parse this json to get the json
var vm = this;
vm.employee = {};
vm.getEmployeeData = function(employeeJson){,
vm.employee = JSON.parse(employeeJson);
};
4. Inside jspI can access employee name as
{{yourController.employee.firstName}}

Related

How to test with Postman a controller's method that has one or more objects parameters (and not simple params) in Spring?

I am a newbie in Spring development. I need to create a simple application, a controller that has a method that takes as parameter an object of a custom designed entity class into the project. The prototype looks like this:
#RestController
public class JobsController {
#PostMapping("/search")
public ResponseEntity<?> search() {
log.info("JobsController -> search method");
//JobSearchEntity jobSearchEntity = modelMapper.map(jobSearch, JobSearchEntity.class);
List<JobEntity> jobs = jobService.searchJobs();
//log.info(String.format("Job found: %s ", jobSearch));
return ResponseEntity.ok(jobs);
}
}
Can someone who is more advanced into this staff with Postman testing tell me how to do that , how to test a controller method which takes parameters?
You can use postman to submit parameters in JSON format after adding # requestbody annotation on the method, or submit parameters directly in form without annotation
You can use this example. Is very simple exemple.
#RestController
#RequestMapping("/root")
public class RootController {
private final RootService service;
public RootController(final RootService service) {
this.service = service;
}
#PostMapping("/exemple")
public void createRoot(#RequestBody final RootDto dto) {
service.createRoot(dto);
}
}
Then you can send request to POST host/root/exemple with your JSON.
More exampls you can find here: https://www.baeldung.com/spring-request-response-body
It seems you are missing an honest search on google about the subject.
You can make use of #RequestBody annotation to accept method arguments.
Check these page for examples --
#RequestBody and #ResponseBody annotations in Spring
https://stackabuse.com/get-http-post-body-in-spring/
https://www.twilio.com/blog/create-rest-apis-java-spring-boot
These set of playlist on youtube are very good starter course for SpringBoot -
https://www.youtube.com/c/JavaBrainsChannel/playlists
Postman Tutorial--
https://www.youtube.com/watch?v=VywxIQ2ZXw4
To get data from api is preferred to use GET method :
#RestController
public class JobsController {
#GetMapping("/search")
public ResponseEntity<?> search(#RequestParam("id") String id,#RequestParam("desc") String desc) {
log.info("JobsController -> search method");
//JobSearchEntity jobSearchEntity = modelMapper.map(jobSearch, JobSearchEntity.class);
List<JobEntity> jobs = jobService.searchJobs();
//log.info(String.format("Job found: %s ", jobSearch));
return ResponseEntity.ok(jobs);
}
}
you call this api with post man this way :
#PostMapping used usually to save new data (example : create job )
Take look on rest resource naming guide

Spring #SessionAttributes shared between controllers?

I'm using Spring 4.3.7, and I got two form controllers with forms rendering using Spring form taglib in corresponding views. To preserve form data between requests (for rendering invalid forms) I store them in SessionAttributes.
LabCreateController:
#Controller
#RequestMapping(path = "/labs/create")
#SessionAttributes("form")
public class LabCreateController {
#ModelAttribute("form")
public LabCreateForm form() {
return new LabCreateForm();
}
#GetMapping
public String showForm() {
return "lab_create";
}
}
WallController:
#Controller
#RequestMapping(path = "/group/{id}/wall")
#SessionAttributes("form")
public class WallController {
#ModelAttribute("form")
public PostCreateForm form() {
return new PostCreateForm();
}
#GetMapping(path = "/new")
public String newPostGet() {
return "communities_newpost";
}
}
I open /labs/create in browser, everything is fine. Then I open /group/4/wall/new and get a following error:
Invalid property 'text' of bean class
[...LabCreateForm]
i.e it means that attribute form from LabCreateController somehow passed to WallController, though Spring documentation says:
Session attributes as indicated using this annotation correspond to a
specific handler's model attributes.
I believe it means they shouldn't be shared between controllers. Also this answer says that it is so since Spring 3.
Is it a bug or I'm missing something? If not, what is the appropriate way of storing a form inside one controller?

how to access model value in angular controller

I want to access model attribute values in angular controller. I have returned from spring controller like this.
#RequestMapping(value="/helloWorld", method=RequestMethod.GET)
public void helloWorld(HttpRequest req, Model model) {
String typeOfMoney = req.getSession().getAttribute("typeOfMoney").toString();
model.addAttribute("typeOfMoney",typeOfMoney);
return "MyJsp";
}
That typeOfMoney need to assign in my angular controller. How can I get this typeOfMoney in angular controller.like the below
var app = angular.module('App', ['ui.bootstrap']);
app.controller('fcController', function($scope) {
var y = typeOfMoney;
});
I think Model and view(i.e attributes of request or response or Session) is specific to Spring(i.e Java) It can't be accessed in Angular Js directly.

Routing in Java web-application

I created a web-application using Spring MVC/jsp. To navigate from one view to another I am using spring controller like the following -
#RequestMapping(value = { "/transaction" }, method = RequestMethod.GET)
public ModelAndView defaultPage() {
return new ModelAndView("transaction");
}
#RequestMapping(value = {"/getPartnerList"}, method = RequestMethod.POST)
#ResponseBody
List<PartnerList> viewTransactionReport() {
logger.info("inside getPartnerList");
List<PartnerList> partnerList = CommonQuery.getPartnerList();
logger.info("Partner List Size " + partnerList.size());
return partnerList;
}
I first send the view request to the controller and after that I place the data-driven call to get JSON data.
Had I been using AngularJS, I could have used ng-route for navigation and sent only data-driven calls to the controller.
Is my approach correct in terms of efficiency and best practices? Thanks.

Spring MVC and thymeleaf ModelAttribute either null or not evaluated

I'm developing a web application with Spring MVC and Thymeleaf as my ViewResolver. I have the following controller handler method:
#RequestMapping(value = "/something", method = RequestMethod.POST, params = "submit")
public String doSomething(#ModelAttribute("error") String error /*, other attributes */) {
// find out if there is an error
error = getErrorMessage();
return "someHTMLfile";
}
My view contains this line:
<p><span th:text="${error}">Error Message goes here</span></p>
When executed, the tag does not render to anything. This is probably due to ${error} evaluating to an empty string but I can't understand why. Doesn't Spring's #ModelAttribute annotation add the object to the model map automatically, where Thymeleaf can find it?
If I instead have:
#RequestMapping(value = "/something", method = RequestMethod.POST, params = "submit")
public String doSomething(ModelMap map /*, other attributes */) {
// find out if there is an error
String error;
error = getErrorMessage();
map.addAttribute("error", error);
return "someHTMLfile";
}
The view is rendered perfectly fine with the error message. Does #ModelAttribute not add the object to the request model?
Edit: I've tried doing both:
#RequestMapping(value = "/something", method = RequestMethod.POST, params = "submit")
public String doSomething(#ModelAttribute("error") String error, ModelMap map /*, other attributes */) {
// find out if there is an error
error = getErrorMessage();
map.addAttribute("error", error);
return "someHTMLfile";
}
This also doesn't work.
Actually I don't think your issue is related to Thymeleaf, just SpringMVC :-)
In your first snippet, you don't add anything to the request model but try to get an object called "error" back from the form.
In your second snippet, you do add an object to the model, that's why your view is well rendered.
Take a look at the SpringMVC doc here (16.3.3.8) to have a better understanding of the #ModelAttribute annotation on a method argument.
I feel stupid but whatever, we all make mistakes.
Spring was creating a new String instance for me and injecting it into my method and into the model under the key error. String is an immutable object, so when I do error = getErrorMessage(), I assign another instance to my error object. Now there is my error and the error String in Spring's model with a value of "". That's why Thymeleaf rendering only finds the empty string.

Categories