Spring MVC and AngularJS #RequestMapping - java

I have built an application with Spring-boot and AngularJS with the REST End Point application. I got a little stuck with #RequesMapping in Spring Controller I've made. The problem is, I have the example url:
"localhost:8080/foo/bar/api/cardGenerated/0102".
'01' is first parameter and '02' is second parameter. How can I mapped into #RequestMapping Spring controller to get a url above.
Here's my controller :
#RestController
#RequestMapping("/api")
public class CardGeneratedResource {
#RequestMapping(value = "/cardGenerated/{branchCode}{cardType}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<CardGenerated> get(#PathVariable("branchCode") String branchCode,
#PathVariable("cardType") String cardType,
HttpServletResponse response) {
log.debug("REST request to get CardGenerated : " + branchCode + " and " + cardType);
CardGenerated cardGenerated = cardGeneratedRepository.
findTopByBranchCodeAndCardTypeOrderByCardNumberDesc(branchCode, cardType);
if (cardGenerated == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(cardGenerated, HttpStatus.OK);
}
}
so this is my AngularJS $resource:
'use strict';
angular.module('itmApp')
.factory('CardGenerated', function ($resource) {
return $resource('api/cardGenerated/:branchCode:cardType', {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
data = angular.fromJson(data);
return data;
}
}
});
});
I always got 'Failed to load resource: the server responded with a status of 404 (Not Found)'.

Here you are missing / .
You have two path variable here.so default url is
localhost:8080/foo/bar/api/cardGenerated/FIRST_PATH_VARIABLE/SECOND_PATH_VARIABLE
branchCode (First path variabel)
cardType (Second path variable)
#RequestMapping(value = "/cardGenerated/{branchCode}/{cardType}"
And in frontend side too the same mistake while registering factory definition.
api/cardGenerated/:branchCode/:cardType'
All method is like
#RestController
#RequestMapping("/api")
public class CardGeneratedResource {
#RequestMapping(value = "/cardGenerated/{branchCode}/{cardType}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<CardGenerated> get(#PathVariable("branchCode") String branchCode,
#PathVariable("cardType") String cardType,
HttpServletResponse response) {
log.debug("REST request to get CardGenerated : " + branchCode + " and " + cardType);
CardGenerated cardGenerated = cardGeneratedRepository.
findTopByBranchCodeAndCardTypeOrderByCardNumberDesc(branchCode, cardType);
if (cardGenerated == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(cardGenerated, HttpStatus.OK);
}
}
and angular factory is like
'use strict';
angular.module('itmApp')
.factory('CardGenerated', function ($resource) {
return $resource('api/cardGenerated/:branchCode/:cardType', {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
data = angular.fromJson(data);
return data;
}
}
});
});
NOTE: First try with any rest client or postman and make sure backend api is working properly also angular side check parameters are being passed correctly.

Related

File size is zero when passing multiple files to the Spring Controller

I am trying to post a file (single file or multiple files) along with some JSON data using AngularJS and Spring MVC.
I tried as shown below:
JS:
(function () {
'use strict';
var myApp = angular.module('app');
myApp.controller('filesWithJSONController', function ($scope, fileUploadService) {
$scope.uploadFile = function () {
var file = $scope.myFile;
var uploadUrl = myApplnURL + '/showInfo/getInformationTest';", //Url of web service
var fd=new FormData();
angular.forEach($scope.files,function(file){
fd.append('file',file);
});
fd.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
promise = fileWithJSONService.sendInformation(fd,uploadUrl);
promise.then(function (response) {
$scope.serverResponse = response;
}, function () {
$scope.serverResponse = 'An error has occurred';
})
};
});
})();
(function () {
'use strict';
var myApp = angular.module('app');
myApp.service('fileWithJSONService', function ($http, $q) {
this.sendInformation = function (fd, uploadUrl) {
var deffered = $q.defer();
var config = {
headers : {
'Content-Type': undefined
}
}
$http.post(uploadUrl, fd, config).then(function (response) {
console.log("response " + response);
}, function (errResponse) {
console.error('Error in request' + errResponse);
deferred.reject(errResponse);
});
...
Spring Controller:
#Controller
#RequestMapping("/showInfo")
public class InfoController{
#RequestMapping(value = "/getInformationTest", method = RequestMethod.POST, consumes = {"multipart/form-data"})
#ResponseBody
public String sendInformationTest(#RequestPart("properties") ConnectionProperties properties, #RequestPart("file") List<MultipartFile> multiPartFileList){
System.out.println("In spring controller");
//business logic
}
With the above code, it is showing the multiPartFileList size as zero in Spring Controller.
But if I change the code to take only one file instead of multiple files, it is showing the file information successfully. Any input?
try with:
var fd = new FormData();
fd.append('file', file);//replace with forEach
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,//overrides Angular's default serialization, leaving our data intact.
headers: {'Content-Type': undefined}//lets the browser detect the correct Content-Type as multipart/form-data, and fill in the correct boundary.
})
.success(function(){})
.error(function(){});
Backend - Spring:
#RequestMapping(value ="/upload", method = RequestMethod.POST)
public ResponseEntity handleFileUpload(#RequestParam("file") MultipartFile[] files){
//add the others params & logic
}

Pass model and a string using ajax to Spring MVC

Hi I need to pass the full model and one string from html to Spring controller using AJAX. I use the below code snippet but it doesn't work.
var str = $("#resourceManagement").serialize();
var agreementId = ${agreementId};
var tempCnltName=$modal.find("input[data-type='cnltName']").val();
$.ajax({
type:"POST",
data: {str, tempCnltName},
url: "${AGREEMENT_BASE_URL}/checkDuplicateConsultantOnline",
async: false,
dataType: "json",
success: function (data, status, xhr) {
message = data.errorMsg;
},
error: function () {
}
});
The problem is that if I pass model alone (str) or string alone (tempCnltName) I can get it in controller but I cannot get both together.
My controller is as below:
#RequestMapping(value = "/app/agreement/checkDuplicateConsultantOnline", method = RequestMethod.POST)
public #ResponseBody AjaxResponse checkDuplicateConsultantOnline(
#ModelAttribute("consultantBidModel") ConsultantBidModel model,
#RequestParam(value = "tempCnltName", required = false) String cnltName,
HttpServletRequest request,
HttpSession session) throws Exception {
final Set<String> allCnltNames = new HashSet<>();
String errMessage = "";
if (model.getLeadingCnltName() != null) {
allCnltNames.add(model.getLeadingCnltName().toLowerCase());
}
if (model.getJointVentureConsultants() != null) {
for (ConsultantBidListItem entry : model.getJointVentureConsultants()) {
if (!allCnltNames.add(entry.getCnltName().toLowerCase())) {
errMessage = "Each consultant can only appear once.";
}
}
}
if (model.getSubConsultants() != null) {
for (ConsultantBidListItem entry : model.getSubConsultants()) {
if (!allCnltNames.add(entry.getCnltName().toLowerCase())) {
errMessage = "Each consultant can only appear once.";
}
}
}
AjaxResponse response = new AjaxResponse();
if (errMessage != null) {
response.setSuccess(true);
response.setResponseObject(errMessage);
response.setErrorMsg(errMessage);
}
return response;
}
On the server side, you're already prepared to receive both the model (with #ModelAttribute) and an additional URL parameter (with #RequestParam)
On the client, append the URL parameter to the URL. Assuming that str is your model and tempCnltName is your string to submit to the server:
$.ajax({
type:"POST",
data: str,
url: "${AGREEMENT_BASE_URL}/checkDuplicateConsultantOnline?tempCnltName=" + tempCnltName,
...
try
var strVal = $("#resourceManagement").serialize();
var agreementId = ${agreementId};
var tempCnltNameVal=$modal.find("input[data-type='cnltName']").val();
$.ajax({
type:"POST",
data: {str: strVal, tempCnltName: tempCnltNameVal},
url: "${AGREEMENT_BASE_URL}/checkDuplicateConsultantOnline",
async: false,
dataType: "json",
success: function (data, status, xhr) {
message = data.errorMsg;
},
error: function () {
}
});
Probably the malformed json is causing trouble
Another way of doing the above, add the string to model:
var strVal = "consulName=" + tempCnltName + "&";strVal = strVal + $("#resourceManagement").serialize();
The model can then have a new parameter consulName and we can get the value in Controller.

How to attach request params in spring which is retrieved from front end?

I tried this code below...can anyone kindly help me how to pass the params to the spring method and is it a correct implementation in angularjs.
#GetMapping("/extended-registered-time")
public ResponseEntity<List<Registered_time>> getSubLeaves(#ApiParam Pageable pageable) {
log.debug("REST request to get registered time : {}", pageable);
LocalDate startDate = LocalDate.of(2018,01,15);
LocalDate endDate = LocalDate.of(2018,01,24);
List<Registered_time> result = ExtendedRegisteredTimeService.
getSelectedRegisteredTime(startDate,endDate);
return new ResponseEntity<>(result, HttpStatus.OK);
}
This is the frontend implementation(AngularJs)
.factory('RegisteredTimeService', RegisteredTimeService);
RegisteredTimeService.$inject = ['$resource'];
function RegisteredTimeService ($resource) {
var userName="HGajanayake";
var resourceUrl = '/api/extended-registered-time/{'+userName+'}';
return $resource(resourceUrl, {}, {
'query': {
method: 'GET',
isArray: true
},
'status':{
method:"POST",
isArray:true,
I couldnt get over with #requestParams so I choosed #pathVariable instead.I got the correct result.
This is my Service
function RegisteredTimeService ($resource) {
var userName="HGajanayake";
// var resourceUrl = '/api/extended-registered-time?employee='+userName;
var resourceUrl = "/api/extended-registered-time/:employee";
return $resource(resourceUrl, {}, {
'query': {
method: 'GET',
isArray: true
},
This is my api endpoint
#GetMapping("/extended-registered-time/{employee}")
#ResponseBody
public ResponseEntity<List<Registered_time>> getSubLeaves(#PathVariable String employee) {
List<Registered_time> result = ExtendedRegisteredTimeService.getSelectedRegisteredTime(employee);
return new ResponseEntity<>(result, HttpStatus.OK);
}
This is the controller where I call the service
function RegisteredTimeController ($rootScope, $scope, $state, Employee, RegisteredTimeService,Profile,$resource) {
var firstName="HGajanayake";
var c=RegisteredTimeService.query({employee:firstName},function(result) {
var v=result;
console.log(v);
});

Angularjs http no response from Spring Boot

I'm trying to develop a small application to create index on local elasticsearch engine. I use angularjs on the front-end, and spring-boot on the back-end. It can create index successfully, however, when I want to retrive the response in the front-end, it keeps throwing me errors.
Below is my AngularJS api call:
app.service('ESIndexService', function($http) {
this.createESIndex = function(esindexObj) {
var settings = {
method: 'POST',
url: BASE_URL + "/ESIndex/createESIndex",
data: esindexObj
};
return $http(settings).then(function(response) {
console.log("response:"+response);
return response;
}, function(error) {
console.log("error:"+error);
return error;
});
};
});
Then this is my controller:
#CrossOrigin
#RestController
#RequestMapping(value = "ESIndex")
public class ESIndexController {
#RequestMapping(value = "createESIndex", method = RequestMethod.POST)
public #ResponseBody String createIndex(#RequestBody ESIndex esIndex) {
try {
Settings settings = Settings.builder()
.put("xpack.security.user", String.format("%s:%s", Constants.ES_UNAME, Constants.ES_PWD)).build();
TransportClient client = new PreBuiltXPackTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(Constants.ES_HOST), Constants.ES_PORT));
CreateIndexResponse response = client.admin().indices().prepareCreate(esIndex.getName()).setSettings(Settings.builder()
.put("index.number_of_shards", esIndex.getNumberOfShards())
.put("index.number_of_replicas", esIndex.getNumberOfReplicas())).get();
client.close();
if(response.isAcknowledged() && response.isShardsAcked())
return Constants.SUCCESS;
else
return "Fail to create index!";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}
I want to get the response status and data in AngularJS response. However, it keeps throwing me errors:
error:SyntaxError: Unexpected token i in JSON at position 0
I'm not using JSON.parse function, why it gives me error like this?
After adding responseType: 'text', still throwing same error, the chrome nextwork
It turns out I need to add "transformResponse: undefined", however, in another of my project, I never did this. What's the difference?
AngularJS:
this.newBlog = function(blogObj) {
var settings = {
method: 'POST',
url: baseUrl + "/blog/newBlog.do",
data: blogObj
}
return $http(settings).then(function(response) {
return response;
}, function(error) {
return error;
});
};
Java Controller:
#RequestMapping(value="newBlog.do", method=RequestMethod.POST)
public #ResponseBody String newBlog(#RequestBody Blog blog, HttpServletRequest request) {
User createdBy = (User) request.getSession().getAttribute("user");
if(createdBy == null)
return NO_SESSION_MSG;
else {
createdBy.setPwd(null);
blog.setCreatedAt(TQBUtilities.getCurrentTime());
blog.setLastUpdatedAt(TQBUtilities.getCurrentTime());
blog.setCreatedBy(createdBy);
return blogService.newBlog(blog);
}
}
Angular is automatically trying to parse the server response as JSON. Try adding this to your settings object
responseType: 'text'
So
var settings = {
method: 'POST',
url: BASE_URL + "/ESIndex/createESIndex",
data: esindexObj,
responseType: 'text'
};
#jheimbouch add "transformResponse: undefined" to http call, like below, works fine:
var settings = {
method: 'POST',
url: BASE_URL + "/ESIndex/createESIndex",
data: esindexObj,
transformResponse: undefined
};
However, why it is required in angularjs 1.6.2? When I was using AngularJS 1.4.8, I don't need to add transformResponse attributes.

Spring Rest Controller POST request doesn't work

I have a rest controller:
#RestController
#RequestMapping("/query")
public class QueryController {
#Autowired
private QueryService queryService;
#RequestMapping(value = "/select", method = RequestMethod.POST)
public #ResponseBody QueryResultDTO executeQuery(#RequestBody QueryDTO queryDTO) {
try {
QueryResultDTO queryResultDTO = queryService.executeQuery("select * from employees");
queryResultDTO.setSuccessful(true);
return queryResultDTO;
} catch (SQLException e) {
QueryResultDTO queryResultDTO = new QueryResultDTO();
queryResultDTO.setSuccessful(false);
queryResultDTO.setErrorMessage(e.getMessage());
return queryResultDTO;
}
}
}
and I try to send POST request from AngularJS controller:
app.controller("AppCtrl",function($scope,$http) {
var app = this;
$scope.execute= function () {
$http({
url: '../query/select',
method: "POST",
data: { 'message' : $scope.queryText }
})
.then(function(response) {
$scope.queryResult = response.data;
console.log($scope.queryResult);
console.log($scope.queryText)
},
function(response) {
console.log(response);
});
}
});
but It doesn't work. My executeQuery function in Spring Controller isn't even called.
But when I change RequestMethod to GET it works correctly.
#RestController
#RequestMapping("/query")
public class QueryController {
#Autowired
private QueryService queryService;
#RequestMapping(value = "/select", method = RequestMethod.GET)
public #ResponseBody QueryResultDTO executeQuery() {
try {
QueryResultDTO queryResultDTO = queryService.executeQuery("INSERT INTO employee VALUES (7,'dupa')");
queryResultDTO.setSuccessful(true);
return queryResultDTO;
} catch (SQLException e) {
QueryResultDTO queryResultDTO = new QueryResultDTO();
queryResultDTO.setSuccessful(false);
queryResultDTO.setErrorMessage(e.getMessage());
return queryResultDTO;
}
}
}
and in Angular controller:
app.controller("AppCtrl",function($scope,$http) {
var app = this;
$scope.execute= function () {
$http({
url: '../query/select',
method: "GET",
data: { 'message' : $scope.queryText }
})
.then(function(response) {
$scope.queryResult = response.data;
console.log($scope.queryResult);
console.log($scope.queryText)
},
function(response) {
console.log(response);
});
}
});
My main problem is that I'd like to send some data to my Spring controller and then send JSON in response to my Angular controller. Whith GET method response works perfectly, but when I use POST the controller method isn't even called.
Edit:
My QueryDTO class is simple:
public class QueryDTO {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
And some logs with DEBUG level:
2016-06-06 09:28:23.697 DEBUG 7504 --- [nio-8090-exec-2] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2016-06-06 09:28:23.698 DEBUG 7504 --- [nio-8090-exec-2] o.s.web.servlet.DispatcherServlet : Successfully completed request
Try adding the consumes=MediaType.APPLICATION_JSON_VALUE in your method.
#Transactional
#RequestMapping(value = "/userlogincheck", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody void userLoginCheck(#RequestBody UserImpl user, HttpServletRequest request, HttpServletResponse response) throws JSONException, IOException {
JSONObject json = new JSONObject();
try {
String email=user.getEmail();
Long userId=user.getId();
User loginData = accountService.userLoginCheck(email,userId);
if(loginData==null)
{
json.put("status", "FAILURE");
json.put("message", "user does not exist");
json.put("nextPage", "signIn");
}
else
{
json.put("status", "SUCCESS");
json.put("nextPage", updateState);
}
}
catch(Exception e) {
logger.info(e.getMessage());
}
response.setContentType("application/json;charset=UTF-8");
logger.info("response======" + json.toString());
PrintWriter out = response.getWriter();
out.write(json.toString());
}
I had the same issue and was able to fix it by adding CSRF token to my request (this is only an issue if you are using the WebSecurity). https://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html
This link describe the following steps:
1) Add the token to your header, with thymeleaf you do as follows (I think you can fetch the token from cookie as well):
<head>
<meta name="_csrf" th:content="${_csrf.token}"/>
.....
</head>
2) Change your request to include the CSRF token as follows (I am not familiar with angular but I guess you can set the header the same way as I did with Jquery):
var token = $("meta[name='_csrf']").attr("content");
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify(newTodo),
headers: {
'X-CSRF-TOKEN': token
},
contentType: 'application/json',
dataType: 'json',
success: function(){
alert('callback ');
}
});

Categories

Resources