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

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.

Related

Handling fault events

Can't handle exceptions occurs on server side by flash (flex) application.
Server on java, spring-boot-web, for handling exceptions uses org.zalando library.
On server, for example:
#ExceptionHandler(value = SecurityException.class)
public ResponseEntity securityViolation(Throwable e, NativeWebRequest request) {
log.error(e.getMessage(), e);
HttpServletRequest httpServletRequest = ((ServletWebRequest) request).getRequest();
ThrowableProblem problem = createBaseProblemBuilder(Error.SECURITY_ERROR, httpServletRequest)
.withStatus(Status.FORBIDDEN)
.withTitle("Unauthorized")
.withDetail(e.getMessage())
.build();
return create(problem, request);
}
private ProblemBuilder createBaseProblemBuilder(Error error, HttpServletRequest httpServletRequest) {
return Problem.builder()
.withType(URI.create(Error.BASE_ERROR_URL + error.getCode()))
.with("httpMethod", httpServletRequest.getMethod())
.withInstance(URI.create(httpServletRequest.getRequestURI()))
.with("requestTraceId", Long.toString(Thread.currentThread().getId()))
.with("timestamp", LocalDateTime.now());
}
On client (flex):
public function invokeCommand(url: String, requestBody: String = null): IThenable {
return new Promise(function (fulfill: Function = null, reject: Function = null): * {
invokeService(requestBody, _serverInfo.serviceUrl + url,
function (event: ResultEvent): void {
fulfill(event.result);
}, function (event: FaultEvent): void {
var response: Object = event.fault.content;
handleFault(response);
reject(response);
});
});
}
private function handleFault(response: Object): void {
var faultResponseDto: FaultResponseDto = new FaultResponseDto(response ? JSON.parse(response.toString()) : null);
... some code, but response already is empty
}
Expects, that event.fault.content contains data from server, but it always empty.
In browser network console response has payload, and contains all data from server in json.
Main question - how i can read fault payload in flash?
In debug I browse all in FaultEvent, but can't find nothing about needed data.
P.S. sorry for bad english...

java spring MVC, REST Delete method after clicked a link

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.

Ajax status errors while trying to refresh data

I need to refresh my data at certain points in my application (after a pop up form is closed). The application in essence allows users to submit forms, save data, and reopen the forms and view/edit the data.
I'm calling an ajax request from a javascript function. The ajax then calls the java function, which in debugging appears to execute without issue, but right after that's performed, I got an ajax error with status 200. I read some things online, and instead of using a POST type, changed it to a GET, but now I get a 500 status, and can't access the data anymore; my belief is that I'm being logged out.
This is the javascript/ajax function:
function refreshData(){
$.ajax({
url: "./profileEntriesAction.do",
data: "toMethod=refreshData",
type: "GET",
success: function(data){
alert('success :: ' + data);
}
});
}
On the java side (profileEntriesAction), I have:
#SuppressWarnings("unchecked")
public ActionForward refreshProfile(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception{
HttpSession objSession = request.getSession();
User user = (User) objSession.getAttribute(Constants.USER_KEY);
ActionErrors errors = new ActionErrors();
ActionMessages messages = new ActionMessages();
ProfileBean pBean = (ProfileBean)objSession.getAttribute("pBean");
ProfileForm pForm = (ProfileForm)objSession.getAttribute("ProfileForm");
if (user == null)
return (mapping.findForward("logon"));
//get connection to db from the pool using a static method
Connection objConn = StartUpServlet.getPoolConnection();
try{
System.out.println("refreshProfile 2");
/////////////////////////////
/////////////////////////////
IntDAO iDAO = new IntDAO();
// get lists data
if (!pForm.isNoInts()) {
Object[] arr = iDAO.getLists(objConn, pBean.getProfileId());
pForm.setList((ArrayList<Ints>) arr[0]);
}
/////////////////////////////
/////////////////////////////
}catch(SQLException ex){
if(ex.getErrorCode() == Constants.SQL_ERROR_CODE_UNACCESSIBLE_RESOURCE && ex.getSQLState().equalsIgnoreCase(Constants.SQL_SQL_STATE_UNACCESSIBLE_RESOURCE)){
objLogger.error("DB maintenance :\n" + ex.getMessage());
errors.add(Globals.ERROR_KEY, new ActionMessage("error.db.maintenance"));
} else {
objLogger.error("Error while refreshing the profile - Profile Id "+ pBean.getProfileId()+" :\n" + ex.getMessage());
errors.add(Globals.ERROR_KEY, new ActionMessage("error.entry.refresh.profile", "Profile"));
}
if(objConn != null)
objConn.rollback();
}catch(Exception e){
objLogger.error("Error while refreshing the profile - Profile Id "+ pBean.getProfileId()+" :\n" + e.getMessage());
errors.add(Globals.ERROR_KEY, new ActionMessage("error.entry.refresh.profile", "Profile"));
if(objConn != null)
objConn.rollback();
}finally {
if(objConn!= null && !objConn.getAutoCommit())
objConn.setAutoCommit(true);
// return the connection to the pool using a static method
StartUpServlet.rtnPoolConnection(objConn);
}
if (!errors.isEmpty()) {
saveErrors(objSession, errors);
}
if(!messages.isEmpty()){
saveMessages(objSession, messages);
}
return mapping.findForward("success");
//return null;
}
I've tried commenting out the entire contents of the java function and just returning the mapping.findForward("success"); but I still get the same errors.

jquery ajax call returns error on successful call to a servlet

I have a servlet that adds a user to a file on the server side.
I invoke it with a jqueries ajax call.
I can see on the server that the method is being called correctly and my user is added, but the error callback is being invoked on the jquery call. All the status text says is error.
Using firebug the response seems to be empty. Why can I not get a success jquery callback?
//Servlet Code
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
String responseStr = "";
if(action.equals("addUser"))
{
responseStr = addUser(request);
}
System.out.println("Reponse:" + responseStr);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().println(responseStr);
}
private String addUser(HttpServletRequest request) throws IOException
{
Storage s;
s = Storage.load();
String name = request.getParameter("name");
String imageUrl = request.getParameter("imageUrl");
User u = new User();
u.setName(name);
u.setImageUrl(imageUrl);
s.addUser(u);
s.save();
return "success";
}
.
//javascript code
function addUser() {
var name = $('#name').val();
var imageUrl = $('#imageUrl').val();
var url = "http://ws06525:8080/QCHounds/QCHoundServlet?action=addUser&name=${name}&imageUrl=${imageUrl}";
url = url.replace("${name}", name);
url = url.replace("${imageUrl}", imageUrl);
$('#result').html(url);
$.ajax({
url: url,
success: function( data ) {
$('#result').html(data);
},
error: function(jqXHR, textStatus, errorThrown)
{
alert("error: " + textStatus);
alert("error: " + errorThrown);
}
});
}
Aaargh! Feel like an idiot. It's a cross site scripting issue.
I was testing the call to the server from the html file on disk so my browser address was
file://projects/myproject/content/Users.html <<< Fail
instead of:
http://myboxname:8080/appname/Users.html <<< Works
The actual code is fine...
use this for learn what is the problem, it will be better for get solution i think
error: function(e){
alert(JSON.stringify(e))
}
For one thing the string "success" isn't valid json. If your ajax query is expecting json, that would fail it.
What if you returned "{ \"success\": true }" ?
EDIT
It looks like from your ajax call that the response shouldn't be json, why is your return content type json?
If it is true that firebug shows no response, your problem must be in the java code that writes the response.

How to write a Controller variable value back to the HTML page that sent the Ajax request without a page refresh?

The following JavaScript
new Ajax.Request('/orders/check_first_last/A15Z2W2',
{asynchronous:true, evalScripts:true,
parameters:{first:$('input_initial').value,
last:$('input_final').value,
order_quantity:$('input_quantity').value}});
triggers an Ajax call to the checkFirstLast method in the OrderController:
#Controller
#RequestMapping("/orders")
public OrderController {
#RequestMapping("/check_first_last/{code}")
#ResponseBody
public String checkFirstLast(#PathVariable String code,
#RequestParam int first,
#RequestParam int last,
#RequestParam("order_quantity") int orderQuantity) {
Integer newResult = new Integer(last - first);
return newResult.toString();
}
}
If I want to write the newResult String from the checkFirstLast method into the result_text HTML element on the page that sends the Ajax request, replacing the value set by the initialResult JSTL variable:
<h2 id="result_text"><c:out value="${initialResult}"/></h2>
what change would I need to make to the controller method above (checkFirstLast), now that I have already included the Jackson JSON library in my project?
the flow in ajax is:
send request with javascript to server
process request on server
sent response back to client
process response with javascript and update the page
The 4th step is missing in the code you provide.
It seems to me you are using the prototype javascript framework, is this correct?
If you look at the documentation for ajax requests and the ajax options you will see you can specify callback function when the requests was handled with success, or when a failure occured.
Change your javascript to:
new Ajax.Request(
'/orders/check_first_last/A15Z2W2',
{
asynchronous:true,
evalScripts:true,
parameters:
{
first:$('input_initial').value,
last:$('input_final').value,
order_quantity:$('input_quantity').value
},
onSuccess: function(transport)
{
$('result_text').update(transport.responseText);
}
}
);
and let me know what it gives.
This is an abstract controller that I wrote to handle Ajax. This actually is from the Struts example on DispatchAction.
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub
AjaxResponse ajaxResponse = null;
String parameter = "command";
try {
String methodName = request.getParameter(parameter);
Method method = getMethod(methodName);
ajaxResponse = invokeMethod(request, response, method);
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error(e.getLocalizedMessage());
ajaxResponse = toXmlException(e);
}
if (ajaxResponse != null) {
//Finally
response.setContentType(ajaxResponse.getContentType());
response.setHeader("Cache-Control", "no-cache");
OutputStream out = response.getOutputStream();
out.write(ajaxResponse.getResponseText().getBytes());
out.flush();
}
return null;
}
As you can see, A javascript is sent to the server, which is then dispatched by the DispatcherServlet to the controller. The controller then invokes the correct method call and returns a response through response.getOutputStream().write(....).
The controller then must return a null so that the DispatcherServlet does nothing in return.
In my case, AjaxResponse is an interface and the response can be either XmlAjaxResponse or JsonAjaxResponse.
The java client then handles the response returned from the server (in this case, controller).
You need to add in a response to your side. Hope this helps.

Categories

Resources