java spring MVC, REST Delete method after clicked a link - java

I am creating a web page that allows the user to add new addresses, delete, and update the address list. My "add new address" is working, however "delete address" is not working.
Please check below my interface design for better understanding, help would be appreciated.
This is my working code for "add new address", and also the non working "Delete address" code.
In Controller:
#RequestMapping(value = "/addressBook", method = RequestMethod.GET)
public Object AddressBook(HttpSession session) throws Exception {
try{
String memberId= (String) session.getAttribute("memberId");
String addressId = (String) session.getAttribute("addressId");
List<Address> addresses = memberService.detail(memberId).getAddresses();
return new ModelAndView("account/addressBook").addObject("addressList", addresses);
} catch (Exception e) {
return new ModelAndView("account/addressBook")
.addObject("error", "No address book found");
}
}
#RequestMapping(value = "/addNewAddress", method = RequestMethod.GET)
public Object AddNewAddress() {
return "account/addNewAddress";
}
#RequestMapping(value = "/addNewAddress", method = RequestMethod.POST)
public Object AddNewAddress(#ModelAttribute AddAddress addAddress, HttpSession session, RedirectAttributes redirectAttributes) {
try {
String memberId = (String )session.getAttribute("memberId");
AddressDetail address1 = memberService.add(addAddress, memberId);
session.setAttribute("addressId", address1.getId());
return "redirect:/addressBook";
} catch (Exception e) {
return new ModelAndView("member/addNewAddress")
.addObject("addressList", addAddress)
.addObject("error", e.getMessage());
}
}
#RequestMapping(value="/deleteAddress" , method =RequestMethod.DELETE )
public Object DeleteAddress(HttpSession session) throws Exception {
String addressId = (String) session.getAttribute("addressId");
String memberId = (String) session.getAttribute("memberId");
AddressDetail addressDetail = memberService.deleteAddress(memberId, addressId);
return new ModelAndView("account/addressBook")
.addObject("success", "Address Deleted")
;
// "redirect:/addressBook";
}`
HTML Page:
<div class="8u 12u(5)">
<div class="table-wrapper">
<h4>Address Book</h4>
{{#addressList}}
<address>
{{street1}}, {{street2}}<br>
{{district}},{{cityTown}}<br>
{{postCode}}, {{provinceState}},<br>
{{countryCode}}<br>
<br>
Edit &nbsp <a class="confirm" href="/deleteAddress">Delete</a>
<hr>
</address>
{{/addressList}}
</div>
<b>Add New Address</b>
</div>
Member Service:
public AddressDetail add(AddAddress addAddress, String memberId) throws Exception {
Address address = new Address.Builder()
.setStreet1(addAddress.getStreet1())
.setStreet2(addAddress.getStreet2())
.setCityTown(addAddress.getCityTown())
.setDistrict(addAddress.getDistrict())
.setProvinceState(addAddress.getProvinceState())
.setPostCode(addAddress.getPostCode())
.setCountryCode(addAddress.getCountryCode())
.build();
RestRequest request = RestRequest.newBuilder()
.url("/member/" + memberId + "/address")
.post(address);
Address response = restClient.execute(configuration.serviceMemberName(), request, Address.class).body();
AddressDetail addressDetail = new AddressDetail();
addressDetail.setId(response.getId());
addressDetail.setDistrict(response.getDistrict());
addressDetail.setStreet1(response.getStreet1());
addressDetail.setStreet2(response.getStreet2());
addressDetail.setCityTown(response.getCityTown());
addressDetail.setProvinceState(response.getProvinceState());
addressDetail.setPostCode(response.getPostCode());
return addressDetail;
}
public AddressDetail addressDetail(String memberId, String addressId) throws Exception {
RestRequest request = RestRequest.newBuilder()
.url("/member/" + memberId + "/address/" + addressId)
.get();
Address response = restClient.execute(configuration.serviceMemberName(), request, Address.class).body();
AddressDetail addressDetail = new AddressDetail();
addressDetail.setId(response.getId());
addressDetail.setStreet1(response.getStreet1());
addressDetail.setStreet2(response.getStreet2());
addressDetail.setDistrict(response.getDistrict());
addressDetail.setCityTown(response.getCityTown());
addressDetail.setCountryCode(response.getCountryCode());
addressDetail.setPostCode(response.getPostCode());
addressDetail.setProvinceState(response.getProvinceState());
return addressDetail;
}
public AddressDetail deleteAddress(String memberId, String addressId) throws Exception {
RestRequest request = RestRequest.newBuilder()
.url("/member/" + memberId + "/address/" + addressId)
.delete();
Address response = restClient.execute(configuration.serviceMemberName(), request, Address.class).body();
AddressDetail addressDetail = new AddressDetail();
addressDetail.setId("");
addressDetail.setStreet1("");
addressDetail.setStreet2("");
addressDetail.setDistrict("");
addressDetail.setCityTown("");
addressDetail.setCountryCode("");
addressDetail.setPostCode("");
addressDetail.setProvinceState("");
return addressDetail;
}

From what I can see, you don't use any AJAX call to delete your record. You just created an anchor pointing to some "/deleteAddress" URL expecting that the browser will infer which HTTP verb to use from the URL semantics. You are far too optimistic. What's going to happen is that you'll fire an HTTP GET to the above "/deleteAddress" URL. But at the same time you instruct your Container to register the "/deleteAddress" URL for HTTP DELETE verb and so... nothing happens. Probably you'll get a 404 error.
If you want to use DELETE you will have to write a little javascript code to attach the "delete button" click to an AJAX call.
Something similar to the following:
$('.btn-delete').click(function () {
var id = //get the id somehow
doAjaxDelete(id);
});
function doAjaxDelete(id){
$.ajax({
type: "DELETE",
url: "your/path/to/record/" + id,
success: function(response){
// we have the response, do something to notify success
error: function(e){
//do something to notify failure
});
}
this code will work for all the elements having a ".btn-delete" class, so you should add it to your button (or use a different selctor, it's up to you). And you should also find a way to include in your DELETE URL an id to properly identify your record. LAst but not least, I used JQuery, so you should include it in your HTML page.
An easier way to proceed is to switch your method annotation from #RequestMapping(value="/deleteAddress" , method =RequestMethod.DELETE ) to #RequestMapping(value="/deleteAddress" , method =RequestMethod.GET). Honestly, I prefer to use the GET verb to retrieve stuff instead of deleting it.

Related

Redirect from Spring REST controller with parameters

I have two different Spring applications (app-one, app-two), app-one should receive a response and then redirect to app-two with some parameters. So, I have the following REST controller in app-one:
#RestController
public class RedirectController
{
#GetMapping(value = "/redirect")
public ResponseEntity<Void> redirectEndpoint(HttpServletRequest request,
RedirectAttributes redirectAttributes)
{
// Do some business logic
// Set parameters
redirectAttributes.addAttribute("attribute", "Value 1");
redirectAttributes.addFlashAttribute("flashAttribute", "Value 2");
// Redirect to success URL
String redirectURL = "http://app-two/success";
HttpHeaders headers = new HttpHeaders();
headers.setLocation(URI.create(redirectURL));
return ResponseEntity.status(HttpStatus.FOUND).headers(headers).build();
}
}
And the following REST controller in app-two:
#RestController
public class SuccessController
{
#GetMapping(value = "/success")
public ResponseEntity<Void> successEndpoint(HttpServletRequest request, Model model,
#RequestParam(value = "attribute", required = false) String attribute,
#ModelAttribute(value = "flashAttribute") String flashAttribute)
{
// Get parameters
System.out.println("attribute: " + attribute);
System.out.println("flashAttribute: " + flashAttribute);
String flashAttributeFromModelMap = (String) model.asMap().get("flashAttribute");
System.out.println("flashAttributeFromModelMap: " + flashAttributeFromModelMap);
Map<String, ?> flashMap = RequestContextUtils.getInputFlashMap(request);
if (flashMap != null)
{
String flashAttributeFromFlashMap = (String) flashMap.get("flashAttribute");
System.out.println("flashAttributeFromFlashMap: " + flashAttributeFromFlashMap);
}
// Do some business logic
return ResponseEntity.status(HttpStatus.OK).build();
}
}
I was able to redirect successfully by returning FOUND (302). But when adding attributes to RedirectAttributes (in this case attribute and flashAttribute), these attributes are not found after the redirection done (attribute gets null and flashAttribute gets empty).
I tried to get the attributes values by different ways (#RequestParam, #ModelAttribute, model.asMap().get(), and RequestContextUtils.getInputFlashMap(request).get()) but none of them gets the correct value.
What I need is to get the correct attributes' values in successEndpoint. Any suggestions on how to accomplish that?
Thanks in advance.

Pass an ID to frontend from the server

I am building a web app and I need to pass the user's id to my front-end(angular) so I can do some ajax calls.
My question is, how can I give(store) the user's id to my front end? For example, a user can create a group by specifying a group name, but I need to be able to pass the users Id aswell in my ajax request(My backend endpoint needs both an Id and a name).
Angular:
$scope.createGroup = function() {
$http.post(BASE_URL + "/group", $scope.groupRequest).
success(function (data, status, headers, config) {
console.log("Success");
}).error(function(data, status, headers, config) {
$log.info("Error: status =" + status + ", body =" + JSON.stringify(data));
});
}
Front-end controller
#RequestMapping(value = "/group", method = RequestMethod.POST)
public ResponseEntity createGroup(#RequestBody Map body) {
try {
return restTemplate.postForEntity(URI.create(BASE_URL + "/group"), body, Map.class);
} catch (HttpClientErrorException e) {
LOG.warn("Error when trying to fetch groups", e);
return ResponseEntity.badRequest().body(e.getResponseBodyAsString());
}
}
Java Back end controller
#RequestMapping(value = "/group", method = RequestMethod.POST)
public ResponseEntity createGroup(#RequestBody #Valid GroupRequest groupRequest, BindingResult validation) {
if (validation.hasErrors()) {
throw new ValidationException(validation.getFieldErrors());
}
Long groupId = groupService.createGroup(groupRequest);
URI groupLocationURI = URI.create("/group/" + groupId);
return ResponseEntity.created(groupLocationURI).build();
}
Thanks

Ajax returns status code 200, success function not triggering

There are quite a few topics about this, but none of them were any help.
Everything is working fine, the data gets inserted into the db, and (i'm using spring mvc as back-end) my controller handles everything correctly as well.
Ajax-code;
$.ajax({
type: "POST",
url: "http://localhost:8080/NotePath/register",
data: "email=" + email + "&password=" + password + "&name=" + name,
succes: function(response){
$("#formMail, #formPass, #formUsername").val("");
$("#loginRegister, #whiteBg").fadeOut();
},
error: function(xhr,err){
alert("readyState: "+xhr.readyState+"\nstatus: "+xhr.status);
alert("responseText: "+xhr.responseText);
}
});
Controller code;
#RequestMapping(value = "/register")
public #ResponseBody String registerUser(#RequestParam(value = "email") String email, #RequestParam(value ="password") String password,
#RequestParam(value = "name") String name, Model model){
String status = "";
Boolean isEmailTaken = registerServiceImpl.isEmailTaken(email);
Boolean isNameTaken = registerServiceImpl.isNameTaken(name);
if(isEmailTaken == false && isNameTaken == false){
try {
registerServiceImpl.registerUser(email, password, name);
status = "Succes";
} catch (Exception e) {
status = "Error";
e.printStackTrace();
}
}else if(isEmailTaken == true){
status = "mail taken";
}else if(isNameTaken == true){
status = "name taken";
}
return status;
}
I even tried returning a responseEntity;
return new ResponseEntity<String>(status, respHeader, HttpStatus.OK);
When I look at my response header (using google chrome) it even says "mail taken" or "name taken" or whatever message that should appear. But for some reason the ajax success function is not getting triggered...
Weird thing is that I have other ajax calls that do work without any problem.
I thought getting a status code of 200 meant that everything was...well....OK :p
You're not registering the callback correctly.
succes: function(response){ should be success: function(response) {

How to response a proper server execution to Ajax Post method?

I have a very simple task in my application, wich retrieves data from a combobox in after its selection event.
When select event is raised, data is passed to a jQuery function which requests opperation from server side.
All these stuffs are ok, but on processing server's response, Ajax receives a fail condition to the request. As I'm a rookie in jQuery and Ajax, I didn't know what I should be missing or doing wrong.
Jsp piece:
<input id="updStatus"
class="easyui-combobox"
name="updStatus"
data-options="
valueField:'id',
textField:'Name',
url:'StatusListCombo',
onSelect:function updStatusTask(row) {
$.fn.updStatusTask(row.id, ${task.id});
}">
jQuery function:
$.fn.updStatusTask = function (idStatus, idTask) {
var result = $.post("TaskUpdateStatus", {
idTask : idTask,
idStatus : idStatus
});
result.done(function( data ) {
alert("data: " + data); //<--NOT REACHED!!
});
result.fail(function(jqXHR, textStatus) {
alert("fail data: " + textStatus); //FIRED
});
result.always(alert("always"));//FIRED
};
Serverside method:
#RequestMapping(value = "/TaskUpdateStatus")
public String TaskUpdateStatus(Long idTask, Long idStatus, HttpSession httpSession, HttpServletResponse resp) throws IOException {
String result = new String();
try {
//... do DAO opperations to persist, everything Ok...
resp.setStatus(200);
result = "Task successfully updated.";
}
catch(Exception e) {
result = "Error: " + e.getMessage();
}
return result;
}
I would start by annotating
public String TaskUpdateStatus(#RequestParam("idTask") Long idTask, #RequestParam("idStatus") Long idStatus, ...
otherwise Spring doesn't know where to get those fields and inject them.
The only problem was the String parameter returned by Controller. It was enough change controller type TaskUpdateStatus from String to void, and, obviously, supress the return statement.
Rather, the right way to return a text to the jQuery event handler, to be processed and showed, is using response.getWritter().write("something").
#RequestMapping(value = "/TaskUpdateStatus")
public void TaskUpdateStatus(Long idTask, Long idStatus, HttpSession httpSession, HttpServletResponse resp) throws IOException {
String result = new String();
try {
//... do DAO opperations to persist, everything Ok...
resp.getWriter().write("Status changed from "
+ oldStatusName + " to " + newStatusName);
resp.setStatus(200);
}
catch(Exception e) {
//... take care of exceptions
}
}
No errors is thrown and datum is correctly exhibited in Ajax post .done event handler.

Can't display response returned from Spring MVC controller using JSON and JQuery

I have a simple JQuery function which calls my Spring MVC controller:
function createDatabaseRecord() {
if (isFormValid()) {
$.getJSON(
"${pageContext.servletContext.contextPath}${databaseConfigUrl}",
{name:$('#idName').val(),
databaseName:$('#idDatabaseName').val(),
hostName:$('#idHostName').val(),
username:$('#idUsername').val(),
password:$('#idPassword').val()},
function (data) {
var html = '<span>' + data + '</span>';
$('#idMessage').html(html);
}
);
}
}
The function is invoked when I click the button, everything is fine. The problem is that this line: $('#idMessage').html(html); does not work as expected. I have a <div> element inside the same JSP page.
<div id="idMessage">
</div>
My Spring controller method which is invoked by that function:
#RequestMapping(value = DATABASE_CONFIG_RECORD_MAPPING, method = RequestMethod.GET)
public
#ResponseBody
String createDatabaseConfiguration(#RequestParam(value = "name", required = true) String name,
#RequestParam(value = "databaseName", required = true) String databaseName,
#RequestParam(value = "hostName", required = true) String hostName,
#RequestParam(value = "username", required = true) String username,
#RequestParam(value = "password", required = true) String password) {
try {
DatabaseConfig config = new DatabaseConfig();
config.setName(name);
config.setDatabaseName(databaseName);
config.setHostName(hostName);
config.setUsername(username);
config.setPassword(password);
configService.save(config);
} catch (Exception ex) {
LOGGER.error("Exception while create database configuration record.", ex);
return "Error occurred while creating database configuration record: " + ex.getMessage();
}
return "Database configuration record successfully created.";
}
I can see in the FireBug that response came to me:
. This is the message: Database configuration record successfully created. I expect to be show in that <div> element, but it is not displayed. Does someone know where might be the problem? If you need some more code, please ask.
Your response is not in JSON format.
Try this snippet in your controller:
return Collections.singletonMap("result", "Database configuration record successfully created");
And use it in javascript like this:
var html = '<span>' + data.result + '</span>';
I'm definitely not an expert in Java (though it looks ok) but think your problem comes from the fact that you're using jQuery's getJSON method but your view is just returning plain text.
You'll need to either convert your response to JSON or switch to a more manual AJAX request using $.get or $.ajax instead.

Categories

Resources