Server responded with 404 - POST request - java

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 {
}

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 функция добавления в коризну');
}
}
});

Parameters of POST request to Java server from Angular client

I've got Angular app and Java server.
I need to send POST request with JSON object consisting of string array and string field.
I'm using Angularjs $resource and Java javax.ws.rs.
My latest try as follows:
Client:
var messages = $resource('resources/messages/getmessages', {}, {
update: { method: 'POST', url: 'resources/messages/updatemessages' }
});
//...
var _args = { 'msgIdList': ['1', '2', '3'],
'action': 'makeSmth' };
return messages.update(_args).$promise.then(
function (data) {
//...
},
function (error) {
//...
}
)
Server:
#POST
#Path("updatemessages")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON +"; charset=UTF-8")
public Response updateMessages( #FormParam("msgIdList") List<String> msgIdList,
#DefaultValue("") #FormParam("action") String action,
#CookieParam("rgsid") String c_sid,
#Context HttpServletRequest httpservletreq) {
//...
}
The problem is that I've got 415 Unsupported Media Type error, and don't know what to do next. I've tried lots of things, but may be I was wrong from the start, and I can't pass parameters this way?
Any help would be appreciated, thanks!
you can try this in your angular, maybe it can help.
var sendPost = $http({
method: "post",
url:"JAVA_SERVER_SERVICE_URL",
data: {
msgIdList: 'your_value',
action: 'your_value'
},
headers: { 'Content-Type': 'application/json' }
});
So, eventually I made a wrapper class, so now it looks this way:
#XmlRootElement
private static class RequestWrapper {
#XmlElement
private ArrayList<String> msgIdList;
#XmlElement
private String action;
public ArrayList<String> getMsgIdList() {
return msgIdList;
}
public void setMsgIdList(ArrayList<String> msgIdList) {
this.msgIdList = msgIdList;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public RequestWrapper() {
}
}
#POST
#Path("updatemessages")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON +"; charset=UTF-8")
public Response updateMessages( RequestWrapper requestData,
#CookieParam("rgsid") String c_sid,
#Context HttpServletRequest httpservletreq) {
//...}
Angular part stays unchanged.
I'm not really sure, if this the right way to go (class description and so on), but it works.

Rest DELETE Bad Request

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.

500 Internal Server Error when calling ajax in spring

I am using Spring MVC and I have an AJAX which is used to delete selected user. It's working fine on my local system but when I tried to run the same code on development server I'm getting
500 Internal Server Error
I did google to figure out what is wrong with my code but I'm not able to figure out anything till now. Any help will be appreciated.
AJAX function in my JSP file:
$('.del-btn .userId').click(function(){
var userId = $(this).attr("alt");
var data = 'userId='+ userId;
$.ajax({
type: 'POST',
url: '${pageContext.servletContext.contextPath}/deleteUser',
data: data,
success: function(response) {
$('#submitkpi').submit();
}
});
});
deleteUser function in Controller:
#RequestMapping(value = "/deleteUser", method = RequestMethod.POST)
public #ResponseBody Map<String, ? extends Object> deleteKpi(#ModelAttribute(value = "userId") String userId, BindingResult result) {
if (!userId.isEmpty()) {
userService.deleteUser(userId);
return Collections.singletonMap("ok", true);
}
return Collections.singletonMap("errorMsg", "Unable to complete your request!");
}
Can you try this?!
$('.del-btn .userId').click(function(){
var userId = $(this).attr("alt");
$.ajax({
url: 'deleteUser',
data: ({
userId : userId,
}),
success: function(response) {
alert(response)
}
});
});
Controller
#RequestMapping("/deleteUser")
#ResponseBody
public String deleteKpi(#RequestParam(value = "userId") Long userId, HttpSession session) {
if (null != userId) {
userService.deleteUser(userId);
return "Ok";
}
return "NotOk";
}

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.

Categories