Rest DELETE Bad Request - java

Can u explain me why DELETE method (store.remove() in Edit.js) throws 400 Bad request. Other method works well. In header request url seems to be ok "http://localhost:8080/Diary/rest/notes/22?_dc=1461837327580".
I know that problem is in payload of DELETE method, store.remove() includes ID as payload. How can i disable that and send DELETE method without body, because ID is already in URL
Rest Service
#Path("/notes")
public class NoteRestService {
#Context
private UriInfo uriInfo;
#Context
private HttpServletRequest request;
private NoteDaoImpl noteDao = new NoteDaoImpl();
#GET
#Produces("application/json")
public String getNotes(){
String login = request.getSession(true).getAttribute("login").toString();
List<Note> notes = noteDao.getUserNotes(login);
return new Gson().toJson(notes);
}
#POST
#Consumes("application/json")
public Response postNote(Note note){
String login = request.getSession(true).getAttribute("login").toString();
note.setUser(login);
noteDao.persist(note);
URI noteUri = uriInfo.getAbsolutePathBuilder().path(Long.toString(note.getId())).build();
return Response.created(noteUri).build();
}
#PUT
#Path("{id}")
#Consumes("application/json")
public Response updateNote(#PathParam("id") String id,Note note){
String login = request.getSession(true).getAttribute("login").toString();
Note editNote = noteDao.getNote(Long.parseLong(id));
note.setCreated(editNote.getCreated());
note.setUser(login);
noteDao.update(note);
return Response.ok().build();
}
#DELETE
#Path("{id}")
public Response deleteNote(#PathParam("id") String id){
Note note = noteDao.getNote(Long.valueOf(id));
if (note==null){
throw new NotFoundException();
}
noteDao.delete(Long.parseLong(id));
return Response.noContent().build();
}
}
EditController.js
Ext.define('MVC.controller.Edit', {
extend: 'Ext.app.Controller',
init: function () {
this.control({
'editForm > button#SaveRecord': {
click: this.onSaveButtonClick
},
'editForm > button#DeleteButton': {
click: this.onDeleteButtonClick
}
});
},
onSaveButtonClick: function (btn) {
//get reference to the form
var detailView = btn.up('editForm');
//get the form inputs
var data = detailView.getValues();
//see if the record exists
var store = Ext.getStore('TestStore');
console.log(data.id);
var record = store.getById(data.id);
if (!record) {
record = Ext.create('MVC.model.Note', {
title: data.title,
created: new Date(),
updated: new Date(),
text: data.text
});
Ext.MessageBox.alert('Created', data.title);
store.insert(0, record);
store.sync();
return;
}
record.set(data);
store.sync();
//manually update the record
detailView.updateRecord();
},
onDeleteButtonClick: function (btn) {
//get reference to the form
var detailView = btn.up('editForm');
//get the form inputs
var data = detailView.getValues();
var store = Ext.getStore('TestStore');
var record = store.getById(data.id);
store.remove(record);
store.sync();
}
});
UPD: Store
Ext.define('MVC.store.TestStore', {
extend: 'Ext.data.Store',
requires: [
'MVC.model.Note'
],
storeId: 'TestStore',
model: 'MVC.model.Note',
autoLoad: false,
proxy: {
type: 'rest',
url: 'rest/notes',
actionMethods: {
create: 'POST',
read: 'GET',
update: 'PUT',
destroy:' DELETE'
},
reader: {
type: 'json',
rootProperty: 'data'
},
writer: {
type: 'json',
writeAllFields: true
}
}
});

You can't have a HttpMethod.DELETE with a body.
This is not explicitly stated in the RFC, but some Proxy servers will reject the body if you have one in a delete method. Spring lowers the standard and will reject your query with a Bad Request.
Remove the body as well as the answer to fix your issue.
Check this for more information:
Is an entity body allowed for an HTTP DELETE request?

If TestStore is the store you're using, I'd guess that your problem is here:
actionMethods: {
create: 'POST',
read: 'GET',
update: 'PUT',
destroy: 'GET'
},
I don't recognize the #DELETE annotation, so I'm not 100% sure but if your controller is expecting DELETE, and you're sending GET, that could explain the 400 error.

Related

Ajax don't see Post Controller

I made ajax request, but it don't see Post Controller, which need to handle request. But if i change POST to GET - Get Controller handle ajax request.
My Post Controller:
#RestController
public class AddProductController extends AbstractController {
private static final long serialVersionUID = 5023867691534917359L;
private static final Logger LOGGER = LoggerFactory.getLogger(AddProductController.class);
#PostMapping("/ajax/json/product/add")
public ShoppingCart addProductToCart(HttpServletRequest req,
#RequestParam(name = "idProduct") String idProduct,
#RequestParam(name = "count") String count) {
ProductForm productForm = createProductForm(idProduct, count);
ShoppingCart shoppingCart = SessionUtil.getCurrentShoppingCart(req); // Get ShoppingCart
orderService.addProductToShoppingCart(productForm, shoppingCart); // Add product in Cart
return shoppingCart;
}
Ajax request:
var addProductToCart = function (){
var idProduct = $('#addProductPopup').attr('data-id-product');
var count = $('#addProductPopup .count').val();
var btn = $('#addToCart');
convertButtonToLoader(btn, 'btn-primary');
$.ajax({
url : '/ajax/json/product/add',
method : 'POST',
data: {
idProduct : idProduct,
count : count
},
success : function(data) {
$('#currentShoppingCart .total-count').text(data.totalCount);
$('#currentShoppingCart .total-cost').text(data.totalCost);
$('#currentShoppingCart').removeClass('hidden');
convertLoaderToButton(btn, 'btn-primary', addProductToCart);
$('#addProductPopup').modal('hide');
},
error : function(xhr) {
convertLoaderToButton(btn, 'btn-primary', addProductToCart);
if (xhr.status == 400) {
alert(xhr.responseJSON.message);
} else {
alert('Не сработала JS функция добавления в коризну');
}
}
});
};
Whats wrong with my PostController?
Jquery.ajax does not encode POST data for you automatically the way that it does for GET data. Jquery expects your data to be pre-formatted to append to the request body to be sent directly across the wire.
A solution is to use jQuery.param function to build a query string that process POST requests expect.
Change data object in you method to the format below, and hopefully, it will work.
data: jQuery.param({ idProduct : idProduct, count : count }),
contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
Change your ajax like below. You do not need to send data because you are not expecting data in body in your post controller.
$.ajax({
url : '/ajax/json/product/add?idProduct='+idProduct+'&count='+count,
method : 'POST',
success : function(data) {
$('#currentShoppingCart .total-count').text(data.totalCount);
$('#currentShoppingCart .total-cost').text(data.totalCost);
$('#currentShoppingCart').removeClass('hidden');
convertLoaderToButton(btn, 'btn-primary', addProductToCart);
$('#addProductPopup').modal('hide');
},
error : function(xhr) {
convertLoaderToButton(btn, 'btn-primary', addProductToCart);
if (xhr.status == 400) {
alert(xhr.responseJSON.message);
} else {
alert('Не сработала JS функция добавления в коризну');
}
}
});

Server responded with 404 - POST request

I wish to create a web application where user input is saved to database.
I am using Java and React for the UI but I keep getting 404 error.
I have the following scripts:
React:
addCreditCard(event) {
var that = this;
event.preventDefault();
let card_data = {
cardholder : this.refs.cardholder.value,
cardnumber : this.refs.cardnumber.value,
card_identifier : (this.refs.cardnumber.value).substr(15),
expiration : this.refs.expiration.value,
cvc : this.refs.cvc.value
};
console.log('Ez itt: ' + JSON.stringify(card_data))
const request = {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify(card_data)
}
let creditcards = that.state.creditcards;
creditcards.push(card_data);
that.setState({
creditcards : creditcards
})
console.log(creditcards)
fetch('/api/new-card', request)
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error('Something went wrong ...');
}
})
.then(data => this.setState({ creditcards: data.creditcards }))
.catch(error => this.setState({ error }))
}
Java
#Path("")
#Produces(ExtendedMediaType.APPLICATION_JSON_UTF8)
#Consumes(ExtendedMediaType.APPLICATION_JSON_UTF8)
public class CreditCardRest {
/**
* Injected configurationDao.
*/
#Inject
#Named(SessionFactoryProducer.SQL_SESSION_FACTORY)
private CardDAO cardDAO;
#RequestMapping(value = "/new-card", method = RequestMethod.POST)
#Transactional
public Response.ResponseBuilder saveCreditCardData(#PathParam("cardholder") final String cardholder,
#PathParam("cardnumber") final Integer cardnumber,
#PathParam("expiration") final String expiration,
#PathParam("cvc") final Integer cvc,
#PathParam("card_identifier") final Integer card_identifier,
#Context HttpServletResponse servletResponse) throws Exception {
Reader reader = Resources.getResourceAsReader("mybatis-card-service.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
//Create a credit card object
cardDAO.saveCreditCardData(cardholder, cardnumber, expiration, cvc, card_identifier);
System.out.println("record inserted successfully");
session.commit();
session.close();
return Response.status(200);
}
}
The JS code works, the problem is somewhere at the connection between the Java class and Ract...
Sorry, but I cannot figure it out... Of cource, this is just an installment of the whole code, but I hope it is might obvious for someone already at the first sight... Thanks a lot!
Thanks...
There is no /api path. Your path to the /new-card endpoint is /new-card because there is no root path at the class level.
#Path("/api")
#Produces(ExtendedMediaType.APPLICATION_JSON_UTF8)
#Consumes(ExtendedMediaType.APPLICATION_JSON_UTF8)
public class CreditCardRest {
}

Taking two HeaderParam in GET, a strange mistake for int #HeaderParam

I post two Headers from a js file in a GET REST Call:
allstaffworking: function(_getstaff){
var currentToken = _GetToken();
var Headers = {
token: currentToken.tokenStaff,
};
var HeaderId = {
idtoken: currentToken.idtokenStaff,
};
console.log("idtoken"+Headers);
if (currentToken !== null) {
$http({
method : 'GET',
headers: Headers, HeaderId,
url : REST_URL+'staff/working'
}).then(function successCallback(response) {
_getstaff(response)
}, function errorCallback(response) {
console.log(response.statusText);
});
} else {
console.log("NON SEI LOGGATO!!!");
}
},
The Headers are:
var Headers = {
token: currentToken.tokenStaff,
};
var HeaderId = {
idtoken: currentToken.idtokenStaff,
};
This is the java page called by REST_URL+'staff/working':
public List<Staff> getStaff()
{
List<Staff> listOfStaff=sDao.getAll(Staff.class);
return listOfStaff;
}
#GET
#Path("/working")
#Produces(MediaType.APPLICATION_JSON)
#Consumes("application/json")
public List<Staff> getWStaff(#HeaderParam("token") String token, #HeaderParam("idtoken") int tokenid)
{
s = (Staff) sDao.getById(tokenid, Staff.class);
st = (StaffType) sDao.getById(s.getStaffType().getIdstaffType(), StaffType.class);
if (ex && st.getIdstaffType()==2){
List<Staff> listOfWStaff=stfDao.getAllW();
return listOfWStaff;
}
else
return null;
}
taking the two Header with: #HeaderParam("token") String token, #HeaderParam("idtoken") int tokenid
The first Header Param works, the second doesn't works, look this debug's image
How you can see from the image, the idtoken's header value is 11.
Therefore my java class should work taking this second #HeaderParman such int. But it doesn't work, error 500. I try to manually insert "11" , in this way:
s = (Staff) sDao.getById(11, Staff.class);
And in this way it works!! Then, the mistake is when I take the second #HeaderParam, I've also tried with take tokenid as String, an convert it using Integer.parseint(tokenid)
but it does not change.
I hope that somebody can help me
$http config object's header property takes an object as param, as you are passing 2 objects its picking the first one. Ideally you should pass something like this:
$http({
...
headers: {
token: currentToken.tokenStaff,
idtoken: currentToken.idtokenStaff
}
...
});
Also I am curious as to why you are not getting error in line where you are providing Headers and HeaderId as comma separated.

I got 404 error after sending POST method from ajax (#ResponseStatus & ResponseEntity)

I ma using Spring MVC and trying to use jQuery. I have this on my web page:
$(document).ready(function () {
var entity = {mag: "status_key", paper: "View10"};
$("#btn").click(function () {
$.ajax({
url: "ajaxJsonPost",
type: 'post',
dataType: 'json',
data: JSON.stringify(entity),
contentType: 'application/json',
});
});
});
Spring server has this:
#RequestMapping(value = "ajaxJsonPost", method = RequestMethod.POST)
public void postJson(#RequestBody Entity en) throws IOException {
System.out.println("writing entity: " + en.toString());
}
OK, Entity cames to server. BUT browser console prints 404 not found. I know that my POST request needs any response. In the Internet I've found solution which recommends me to return ResponseEntity object, OR use annotation #ResponseStatus. They both return HttpStatus well, but I don't know in which cases I should use them. What is the best way?
#Controller
#RequestMapping("/apipath")
public class SomeController {
#RequestMapping(value = "/ajaxJsonPost", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public String postJson(#RequestBody final Entity en) {
System.out.println(en.toString());
//assuming you have a class "EntityService" and
//it has a method postData
//which takes Entity object as parameter and pushes into database.
EntityService.postData(en);
System.out.println("added");
return "success";
}
}
Entity object on the Server side
#JsonAutoDetect
public class Entity {
private String mag;
private String paper;
public String getMag() {
return mag;
}
public void setMag(final String mag) {
this.mag = mag;
}
public String getPaper() {
return paper;
}
public void setPaper(final String paper)
this.paper = paper;
}
}
ajax
$(document).ready(function () {
var entity = {mag: "status_key", paper: "View10"};
$("#btn").click(function () {
$.ajax({
url: "/apipath/ajaxJsonPost",
type: 'post',
dataType: 'json',
data: JSON.stringify(entity),
contentType: 'application/json',
success : function(response) {
alert(response);
},
error : function() {
alert('error');
}
});
});
});
And as far as why and when to use #ResponseStatus and #ResponseEntity, there is already a short and simple answer here by #Sotirios Delimanolis. When use #ResponseEntity .
It says :
ResponseEntity is meant to represent the entire HTTP response. You can
control anything that goes into it: status code, headers, and body.
#ResponseBody is a marker for the HTTP response body and
#ResponseStatus declares the status code of the HTTP response.
#ResponseStatus isn't very flexible. It marks the entire method so you
have to be sure that your handler method will always behave the same
way. And you still can't set the headers. You'd need the
HttpServletResponse or a HttpHeaders parameter.
Basically, ResponseEntity lets you do more.

response status from server to client

In my app I want to respond from server to client the status of the operation, for example, from client sends data in format json to server and I want that this responds whit status of the operation, if these data have inserted correctly in database to send status 200,...
I now have this.
Client:
function sendAjax() {
//I build the params necessary to send to server in format json
$.ajax({
url: "/url",
type: 'POST',
dataType: 'json',
data: param,
contentType: 'application/json',
mimeType: 'application/json',
success: function(data) {
alert(data.id );
},
error: function(data,status,er) {
alert("error: "+data+" status: "+status+" er:"+er);
}
});
alert();
}
Server:
Controller.java
#RequestMapping(value = "/", method = RequestMethod.POST)
public #ResponseBody
ResponseJson post (#RequestBody String string){
//I have the operations necessary to insert in database
ResponseJson pruebaJson = new ResponseJson ();
pruebaJson.setId (id);
return pruebaJson;
}
ResponseJson.java
public class ResponseJson implements Serializable
{
private String id;
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
}
How will I process the status that server send to client? this is, if I get status 200 or other status.
My app is realized in spring-mvc and I use javascript with ajax to send data in format json from client to server.
Thanks
You can do it by :
$.ajax({
statusCode: {
404: function() {
alert( "page not found" );
},
200: function() {
alert("insert done..!!!");
},
}
});
This may help you.
See JQuery API for more option.
EDIT : on the basis of my understanding you want to check status code inside success or error function for that
success: function(data , textStatus, jqXHR) {
alert(data.id );
var statusCode = jqXHR.status
if(statusCode == 200 ){
//Your code execute if status is 200
}
}
like wise you can do it in error function also.
In your ajax call success function executes when server sends status 200 code. other than that your error function only executes.
If you want to handle error status separately you can handle in error function with return status.

Categories