Angular $resource and webApi - angularjs

I am using webApi and have generated the model using entityframework the overload method of the GET(int id) I am trying to call that using the query of the $resource
I am trying to pass an optional parameter to a call using the $resource but get the error [$resource:badcfg] I have had a google and people say add
{
'get': {method: 'GET'},
'query': {method: 'GET', isArray: true}
}
into the function, so I have tried this: but still have no luck.
function minorResource($resource, appSettings) {
return $resource(appSettings.serverPath + "/api/minorworks/:id",
{
'get': {method: 'GET'},
'query': {method: 'GET', isArray: true}
});
}
Would you use 2 separate methods or can the above function be made to work?
For completness here is my Controller call
minorResource.query({id: vm.seachCriteria}, function (data) {
//console.log(data);
vm.minorWork = data;
});

Note that query is used to retrieve an array of objects and get is used to retrieve a single object. That means that with a get you usually sent the id of the object to the API.
So in your case:
var minorWorksResource = $resource(appSettings.serverPath + "/api/minorworks/:id");
// Note that query returns an array.
var works = minorWorksResource.query(function() {
var firstWork = works[0];
});
// Note that we pass an ID that will be fetched in the query string.
var singleWork = minorWorksResource.get({id: 123}, function() {
});
And the WebAPI part:
[RoutePrefix("api/minorworks")]
public class MinorWorksController : ApiController {
public IHttpActionResult Get(int id) {
var singleWork = null;
// Retrieve a single item;
return Ok(singleWork);
}
public IHttpActionResult Get() {
var workList = null;
// Retrieve the whole list.
return Ok(workList );
}
}

Related

POST request not getting mapped to Spring MVC Controller

I am sending a POST request from Angularjs $http service . It is working fine when my promise is like below and is getting properly mapped to Spring Controller ,
service.js
reassignKsaPendingLeads : function(data,username)
{
var promise = $http({
url : "reassignPendingLeads.htm",
method : "POST",
data : mydata
})
.success(function(data, status, header, config, statusText)
{
}
}
Spring Controller
#RequestMapping({ "reassignPendingLeads.htm" })
public #ResponseBody String updateAccessStatus(#RequestBody List<KsaLead> ksaLeads)
{
log.info("Inside updateAccessStatus");
return "true";
}
The json object i pass from service.js is getting mapped properly to #RequestBody List ksaLeads.
Since the json object contains same keys as bean properties of KsaLead.
But Now i want to pass another parameter username apart from json body (data).
Then i get Request method 'POST' not supported in Spring Controller .
new service.js
reassignKsaPendingLeads : function(data,username)
{
var mydata = JSON.stringify(data) + '&username=' + username;
var promise = $http({
url : "reassignPendingLeads.htm",
method : "POST",
data : mydata
})
.success(function(data, status, header, config, statusText)
{
}
new Spring Controller
#RequestMapping({ "reassignPendingLeads.htm" })
public #ResponseBody String updateAccessStatus(#RequestBody List<KsaLead> ksaLeads,#RequestParam String username)
{
log.info("Inside updateAccessStatus");
return "true";
}
Can anyone guide me as to how should i pass data from angularJs so that it gets mapped correctly to Spring Controller
I would assume that you want to pass the username as a request parameter. In order to do this, the $http can have a params input field:
function(data,username) {
var promise = $http({
url: "reassignPendingLeads.html",
method: "POST",
data: data,
params: { username: username }
})
// continue with your promise here
}
If you want to pass it inside the request body we have to do the following steps:
We have to add the username to the mydata object.
// we assume that data is not a primitive type
function(data,username) {
var mydata;
// check if data is defined
if (data) {
// make a deep copy first, since we don't want to modify the input
mydata = angular.copy(data);
} else {
// if the data is undefined, create e new object
mydata = {};
}
// add the username to mydata
mydata.username = username;
var promise = $http({
url: "reassignPendingLeads.html",
method: "POST",
data: mydata
})
// continue with your promise here
}
On the back-end we have to make sure that we can accept this kind of data. For this it is advised to create a data class which holds the username and any other fields which may appear on your data object from the front-end.
Probably something like this:
public class MyDataClass {
private String username;
// other fields
// no args constructor
public MyDataClass() {}
// all args constructor
public MyDataClass(String username) {
this.username = username;
}
// getter and setters
}
Now we modify the controller to accept it:
#RequestMapping(value = "reassignPendingLeads.htm", method = RequestMethod.POST)
public #ResponseBody String updateAccessStatus(#RequestBody MyDataClass data)
{
log.info(data.getUsername());
return "true";
}

Not hitting with Web API two different GET methods

Implemented webapi routing and having two different route methods for for retrieving values but it is differentiated by supplying parameter type.
Api methods are getting hit for the corresponding action methods if we simply specify "apiurl/api/contact/search/sri" and "apiurl/api/contact/get/2" in direct browser url.
But when comes to communicate with angular to webapi, api is not getting hit.
//angular service
contact.search = function (inputName) {
return $http({
method: 'GET',
url: url + 'api/contact/search',
//params: { name: inputName }
data: { name: inputName }
});
//return $http.get(url + 'api/contact/search', name);
}
//WebAPI
[HttpGet]
[Route("search/{name:alpha}")]
public IHttpActionResult GetContacts([FromBody]string name)
{
repository = new ContactRepository();
if (string.IsNullOrEmpty(name))
{
var message = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Search Name can not be empty")
};
throw new HttpResponseException(message);
}
return Ok(repository.GetContact(name));
}
// GET api/contact/5
[HttpGet]
[Route("get/{id:int}")]
public IHttpActionResult Get(int id)
{
repository = new ContactRepository();
if (id == 0)
{
var message = new HttpResponseMessage(HttpStatusCode.NotFound) { Content = new StringContent("Issue with Passed Id Parameter.") };
throw new HttpResponseException(message);
}
return Ok(repository.GetContact(id));
}
When you use data: { name: inputName }, it is appended to the url in the following way:
...api/contact/search?name=inputName
but what you want is this:
...api/contact/search/inputName
So, you have two options.
Either change your angular code:
return $http({
method: 'GET',
url: url + 'api/contact/search/' + inputName,
});
or change your API to accept QUERY params.
Hope it helps

400 Bad Request when accessing a Sprint Rest method with AngularJs

I am trying to access an update rest method with AngularJs, but it is giving me 400 bad request error.
Here is my code.
#RestController
#RequestMapping("/api/loggedInUser")
public class UserController {
#RequestMapping(value = "/{id}",method = RequestMethod.PUT)
public AppUser updateLoggedInUser(#RequestBody AppUser user){
return userService.updateAppUser(user);
}
}
Here is the code for accessing the service from AngularJs:
App.factory('LoggedInUserService', ['$resource', function($resource) {
console.log('service injected');
return {
getLoggedInUser: $resource('api/loggedInUser', {}, {
query: {method: 'GET'}
}),
updateLoggedInUser: $resource('api/loggedInUser/:id', {}, {
update: {method: 'PUT', params: {id: '#id'}}
})
};
}]);
Here is the code for accessing the service in my app.js file.
.run(function($location, $rootScope, LoggedInUserService) {
LoggedInUserService.getLoggedInUser.query(function(loggedInUser) {
$rootScope.loggedInUser = loggedInUser;
console.log($rootScope.loggedInUser.username);
if (loggedInUser.role[0].authority === 'ADMIN_ROLE' && loggedInUser.pristineAccess) {
$rootScope.loggedInUser.isAdmin = true;
$rootScope.pristineAccess = false;
LoggedInUserService.updateLoggedInUser.update($rootScope.loggedInUser);
$location.path('/admin');
} else {
$rootScope.loggedInUser.isAdmin = false;
$location.path('/dashboard');
}
});
});
When I remove the #RequestBody annotation I don't get a 400 error but the parameter doesn't get populated.
What am I doing wrong here? I used the same kind of code in another place in the same application and it worked fine. The only difference here is that the rest method argument parameter is an entity object and not a pojo.
add consumes = MediaType.APPLICATION_JSON_VALUE to your controller method and check your POST content with web developers tool or firebug or simmilar tool
#RequestMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.PUT)
public AppUser updateLoggedInUser(#RequestBody AppUser user){
return userService.updateAppUser(user);
}

How do I get data from a Java REST service with angular.js

I'm using the default JEE7 REST application on Netbeans. The REST method that I'm trying to call is:
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public Customer find(#PathParam("id") Integer id) {
return super.find(id);
}
I can successfully get a list of all customers. However, when I get the customer ID on the client side with angular, it generates this URL:
http://localhost:8080/mavenproject2/customers?0=1
(when I passed the ID of 1)
The addition of "?" and the index added "0=" makes the call fail.
http://localhost:8080/mavenproject2/customers/1 works
My service looks like this:
customerServices.factory('customerById', function ($resource) {
return $resource('http://localhost:8080/mavenproject2/customers/:id', {id: "#id"}, {
query: {method: 'GET', isArray: true}
});
})
and my controller looks like this:
.controller('customerDetailsController', function ($scope, $routeParams, customerById) {
$scope.customer = customerById.query($routeParams.customerId);
});
Assistance will be greatly appreciated.
You should pass the argument as object, having the field(s) specified with the #. For your case:
$scope.customer = customerById.query({ id: $routeParams.customerId });
You could try something like this in your controller:
$scope.fetchData = function() {
$http({
method : 'GET',
url : 'http://localhost:8080/mavenproject2/customers/',
params : {id : theIdFromYourCode}
}).success(function(data) {
// do something
}).error(function(data, status) {
// do something if error
});
};
Note that you will have to include the $http module.

Can someone give me an example on how I can call $resource directly?

In my code I have:
var EntityResource = $resource('/api/:entityType', {}, {
postEntity: { url: '/api/:entityType/', method: 'POST' },
getEntity: { url: '/api/:entityType/:entityId', method: 'GET' },
putEntity: { url: '/api/:entityType/:entityId', method: 'PUT' },
deleteEntity: { url: '/api/:entityType/:entityId', method: "DELETE" },
getEntities: { url: '/api/:entityType/:action/:id', method: 'GET', isArray: true },
});
Then I am using the following to get data:
getProjects: function (
entityType,
deptId) {
var deferred = $q.defer();
EntityResource.getEntities({
action: "GetProjects",
entityType: entityType,
deptId: deptId
},
function (resp) {
deferred.resolve(resp);
}
);
return deferred.promise;
},
and the following to call getProjects:
entityService.getProjects(
'Project',
$scope.option.selectedDept)
.then(function (result) {
$scope.grid.data = result;
}, function (result) {
$scope.grid.data = null;
});
I think the intermediate function getProjects is not needed and I would like to directly use $resource.
Can someone give me some advice on how I could do this? I looked at the AngularJS documentation for $resource and it's not very clear for me.
$resource calls by default return empty arrays and then fill them up when the response is received. As mentioned in documentation
It is important to realize that invoking a $resource object method
immediately returns an empty reference (object or array depending on
isArray). Once the data is returned from the server the existing
reference is populated with the actual data.
There are default 5 methods already defined on resource, get,save,query,remove,delete. You can directly call these rather than defining your own as you have done like postEntity, but the url template remains the same.
So once you define resource like this
var entityResource = $resource('/api/:entityType');
you can make calls like
var entity=entityResource.get({entityType:1},function(data) {
//The entity would be filled now
});
See the User example in documentation
If you want to return promise then you have to wrap the calls into your your service calls like you did for getProjects.
Update: Based on your comment, the definition could be
var entityResource = $resource('/api/:entityType/:action/:id')
Now if you do
entityResource.get({},function(){}) // The query is to /api
entityResource.get({entityType:'et'},function(){}) // The query is to /api/et
entityResource.get({entityType:'et',:action:'a'},function(){}) // The query is to /api/et/a
entityResource.get({entityType:'et',:action:'a',id:1},function(){}) // The query is to /api/et/a/1
Hope it helps.
$resource does expose $promise but it is on return values and subsequent calls.

Resources