AngularJS send data to spring mvc method - angularjs

Hi everyone i'm trying to send data as param to spring mvc method that should catch param using #RequestParam :
#ResourceMapping(value="send")
public void send(ResourceResponse response,#RequestParam("message") String message) throws JsonGenerationException, JsonMappingException, IOException{
System.out.println("send method invocked");
System.out.println("message === >" + message);
.........
and my angular JS script (not work) is as follow
var message = "message="+JSON.stringify({
"name" : $scope.message.name ,
"email" : $scope.message.email ,
"tel": $scope.message.tel,
"id_subject":$scope.message.selectedSubject ,
"content" : $scope.message.content
});
console.log("valid");
$http.post('${send}', message)
.success(function(data, status, headers, config) {
})
.error(function(data, status, headers, config) {
});
method from controller throw exception (Required String parameter 'message' is not present)
please help

Controller.java:
#RequestMapping(value = "/send",
method = {RequestMethod.POST},
consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
#ResponseStatus(value = HttpStatus.OK)
public void place(#RequestBody Message msg) {
//do something with msg
}
Message.java:
public class Message {
//All your fields
private String name;
private String email
//and so on...
/*
* Getters and setters for the fields.
* You can use #Data annotation from Lombok library
* to generate them automatically for you.
*/
public String getName() { return name; }
public String getEmail() { return email; }
}
Angular part:
var message = {name: $scope.message.name, email: $scope.message.email};
$http.post('/send', message)
.success(function() {
console.log("msg sent");
})
.error(function() {
console.log("msg failed");
});
You may also need to configure Spring to use Jackson for JSON conversion:
Is it possible to convert from JSON to domain object with #RequestParam

Related

Getting code 400 (Bad request) when sending post request with angularjs

I'm building an app which uses AngularJS on the client side and java on the server side. I'm trying to do a login, but when I send the data (username and password) via POST request using AngularJS, I keep getting this two errors:
POST http://localhost:8008/WebProjekat/rest/auth/login 400 (Bad Request)
and
Possibly unhandled rejection: {"data":"Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: org.glassfish.jersey.message.internal.EntityInputStream#542ca5bc; line: 1, column: 2] (through reference chain: MyResponsePackage.User[\"username\"])","status":400,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"/WebProjekat/rest/auth/login","data":{"username":{"ng339":8},"password":{"ng339":9}},"headers":{"Accept":"application/json, text/plain, /","Authorization":"Basic","Content-Type":"application/json;charset=utf-8"}},"statusText":"Bad Request"}
Here is my angularjs code which does the post rquest:
factory.Login = function(username, password, callback){
$http.post('/WebProjekat/rest/auth/login', {username: username,
password: password})
.then(function(response){
callback(response);
})
}
Here is my java code which checks if the credentials are valid
#POST
#Path("/login")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public MyResponse login(User u) {
String username = u.getUsername();
String password = u.getPassword();
MyResponse response = null;
if(password.equals("test") && username.equals("test")) {
response = new MyResponse(true, "Succes!");
}else {
response = new MyResponse(false, "Error");
}
return response;
}
And here is my User class
public class User {
private String username;
private String password;
public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
I apologize if there is somewhere similar question with the answer. I've tried looking for it but could not resolve my problem. I hope the question is clear, if any further explanation is needed i'll provide it. If anyone could help me i'd be extremely greatful.

MVC 6 API Multiple Parameters

I have the following API, which takes care of updating items in the database:
[Route("update")]
[HttpPost("")]
public JsonResult UpdateRecords([FromBody]ICollection<ShoppingItemViewModel> vm)
{
if (ModelState.IsValid)
{
try
{
var items = Mapper.Map<IEnumerable<ShoppingItem>>(vm);
//update database
_repository.UpdateValues(items, User.Identity.Name);
return Json(null);
}
catch (Exception Ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(null);
}
}
else
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(null);
}
}
Then under my Angular code I am executing this POST method like following:
$scope.SaveChanges = function () {
$http.post("/api/items/update", $scope.items)
.then(function (response) {
}, function (err) {
$scope.errorMessage = "Error occured: " + err;
}).finally(function () {
});
};
What I would like to do, is to introduce new parameters to my initial UpdateRecords function, where some of them are optional. Then depending on the inserted parameters my procedure would do different things.
What I have tried to do is to change my function like following (example):
public JsonResult UpdateRecords([FromBody]ICollection<ShoppingItemViewModel> vm, [FromBody]bool EraseOldItems)
and under my Angular App:
$http.post("/api/items/update", {vm:$scope.items, EraseOldItems: true})
or even
$http.post("/api/items/update", {'vm':$scope.items, 'EraseOldItems': true})
but I could not get the code to work (my parameters were all the time null).
What am I doing wrong here?
From Parameter Binding in ASP.NET Web API:
At most one parameter is allowed to read from the message body.
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
The reason for this rule is that the request body might be stored in a
non-buffered stream that can only be read once.
You can pass a request object that contains other objects:
public class Request
{
public ICollection<ShoppingItemViewModel> vm { get; set; }
public bool eraseOldItems { get; set; }
}
And then your action:
[Route("update")]
[HttpPost("")]
public JsonResult UpdateRecords([FromBody]Request request){ ... }

I am not able to post data with $http.post to springMVC controller(RESTfull service), both angular and controller working on different ports

My angular code:
var user={id:null,username:'data',address:'',email:''};
$http.post("localhost:8080/Myservice/adduser",user).success(function(data) {
alert("data gaya");
alert(data);
}).error(function(data1, status, headers, config) {
alert( "nahi gaya"+headers+"config"+config);
});
Here is my Spring service mapping
#RequestMapping(value = "/adduser", method = RequestMethod.POST)
#ResponseBody
public String createUser1(HttpServletResponse response,#RequestBody User user) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
System.out.println("Created a User " + user.getUsername());
String sss ="{\"employeeID\":\"101\"}";
return sss;
}
Here is my pojo class
public class User {
private long id;
private String username;
private String address;
private String email;
public User(){
}
public User(long id, String username, String address, String email){
this.id = id;
this.username = username;
this.address = address;
this.email = email;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
when ,I am making a post call without sending any data it is working fine but when i post data it is giving this error
XMLHttpRequest cannot load localhost:8080/Spring4MVCAngularJSExample/adduser. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
findings
when I called my service using mozilla's RESTclient it gives the error
Any help would be very appreciable.
Thanks in advance.
You have to enable CORS on your controller method. Annotate the createUser1 method with #CrossOrigin(origins = "http://domain.com") where we only allow http://domain.com to send cross-origin requests.
Or simply you can annotate with #CrossOrigin on your controller method or the class to enable CORS from all domains.
Some helpful links and documentation -
https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html
https://spring.io/guides/gs/rest-service-cors/

java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type

I am getting the following validation error when I try to submit my form. The dropdown box populated with values from Sites.java gives this error:
org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'model.TypeSites'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [model.TypeSites]: no matching editors or conversion strategy found
at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:58)
Is there something wrong with my mapping?
Sites.java mapping
public class Sites implements java.io.Serializable {
private int id;
#ManyToOne
#JoinColumn(name = "idTypeSite")
private TypeSites siteesTypeSite;
}
TypeSites.java mapping :
public class TypeSites implements java.io.Serializable {
private int idTypeSite;
private String typeSite;
#OneToMany(mappedBy = "siteesTypeSite",fetch = FetchType.LAZY)
private Set<Sites> sitees= new HashSet<Sites>(0);
}
controller class :
#Controller
#RequestMapping(value = "/protected/sites")
public class SitesController {
------
#RequestMapping(method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<?> create(#ModelAttribute("site") Sites site,
#RequestParam(required = false) String searchFor,
#RequestParam(required = false,
defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
Locale locale) {
siteService.save(site);
}
Angularjs code :
$scope.createObject = function (newObjectForm) {
if (!newObjectForm.$valid) {
$scope.displayValidationError = true;
return;
}
$scope.lastAction = 'create';
var url = $scope.url;
var config = {headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}};
$scope.addSearchParametersIfNeeded(config, false);
$scope.startDialogAjaxRequest();
$http.post(url, $.param($scope.sites), config)
.success(function (data) {
$scope.finishAjaxCallOnSuccess(data, "#addObjectsModal", false);
})
.error(function(data, status, headers, config) {
$scope.handleErrorInDialogs(status);
});
};
JSP :
<select required
ng-model="sites.siteesTypeSite"
name="siteesTypeSite"
ng-change="getSelectedValue()"
value="{{sites.siteesTypeSite}}"
>
<option ng-repeat="typesites in page.source" value="{{typesites.idTypeSite}}" >{{typesites.typeSite}}</option>
</select>
Iwas solve this error like that :
i have edite my angular function to :
$scope.createObject = function (newObjectForm) {
if (!newObjectForm.$valid) {
$scope.displayValidationError = true;
return;
}
$scope.lastAction = 'create';
var url = $scope.url;
console.debug(url);
var config = {headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}};
$scope.addSearchParametersIfNeeded(config, false);
$scope.startDialogAjaxRequest();
$scope.sites.siteesTypeSite =JSON.parse($scope.sites.siteesTypeSite);
$http.post(url, $.param($scope.sites), config)
.success(function (data) {
console.debug(data);
$scope.finishAjaxCallOnSuccess(data, "#addObjectsModal", false);
})
.error(function(data, status, headers, config) {
$scope.handleErrorInDialogs(status);
});
};

RequestBody POJO always empty

I want to store some data from an HTML form (working with AngularJS) into my database, using Spring.
For this, I'm using the #RequestBody annotation with a POJO, but I can't make it work: my POJO is instancied, but it looks like the POJO attributes are not mapped with my form values (they are all null).
Controller :
#RequestMapping(value = "/createEntities", method = RequestMethod.POST)
#ResponseBody
public List<Entity> createEntities(#RequestBody final EntityList resource, #RequestParam final String kind) {
System.out.println("Creating entity for: " + kind);
Preconditions.checkNotNull(resource);
List<Entity> newEntities = new ArrayList<Entity>();
System.out.println("Entity test = " + resource.getTest()); // Prints "Entity test = null"
// Code below returns NullException
//System.out.println("Entity list nb = " + resource.getEntity().size());
if (resource.getEntities() != null && !resource.getEntities().isEmpty()) {
System.out.println("Entity list is OK");
for (EntityForm eForm : resource.getEntities()) {
if (eForm.getGrant() != null) {
Entity ent = new Entity();
if ("RTS".equals(kind)) {
ent.setDept(deptService.findByAbr(DeptEnum.RTS.name()));
} else {
ent.setDept(deptService.findByAbr(DeptEnum.RTB.name()));
}
ent.setGrant(eForm.getGrant());
ent.setCountry(eForm.getCountry());
ent.setName(eForm.getName());
ent = service.create(ent);
newEntities.add(ent);
}
}
}
return newEntities;
}
EntityList is the POJO for my form. This POJO contains a list of EntityForm (+ a string for test purpose), which is a DTO for my database entity Entity.
EntityList POJO :
public class EntityList implements Serializable {
private static final long serialVersionUID = 6335318686899794229L;
private List<EntityForm> entities;
private String test;
public EntityList() {
super();
}
public EntityList(List<EntityForm> entities, String test) {
super();
this.entities = entities;
this.test = test;
}
public List<EntityForm> getEntities() {
return entities;
}
public void setEntities(List<EntityForm> entities) {
this.entities = entities;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
I thought the problem came from a bad mapping between my list of entities in my form and my List<EntityForm> in my POJO, that's why I added a simple String to my POJO.
AngularJS side
Service :
app.factory("Entities", function($resource) {
return $resource("api/auth/entities", null,
{
createEntities: {method:'POST', url: "api/auth/entities/createEntities", params: { kind: '#kind' }, isArray:true}
});
})
Controller :
$scope.EntForm = {};
$scope.EntForm.entities = [];
$scope.EntForm.test = "myTest";
/* ... */
$scope.saveEnt= function() {
console.log($scope.EntForm);
Entities.createEntities($scope.EntForm,{kind:"RTS"},function(res) {
var msg = 'Entities created...';
ngToast.create(msg);
$location.path("/entities");
});
}
In my firefox console, I see that $scope.EntForm is correctly set (I have all my entity objects with the fields set, as well as the test string defined in the controller).
Result
All this code will display :
Creating entity for: RTS
Entity test = null
What am I doing wrong ?
Have you checked out the POST payload with Firefox developer tools, is your custom createEntities method working correctly?
(Would have added this as a comment, but unfortunately I don't yet have enough reputation for that.)
I had to remove the #RequestParam final String kind part from my Spring controller, and the param in AngularJS code.
To get the kind, I just added $scope.EntForm.kind = "theValueIWant" in my AngularJS controller.
I don't know if it's a good way to make it work in terms of good practice, but I get the #RequestBody content now.

Resources