I have some requests in my struts 2 application.
When using json request, i can see them running more than twice, even 5 times. why!
Please help!
I Have my method declared like this :
#Actions({ #Action(value = "/getelements", results = { #Result(name = "success", type = "json") }) })
public String myelements() {
// getting elements here
}
it is the get tha make it running again and again ?
Just a guess, but if your action methods start with getXXX, then the json result type will invoke that method again when it is trying to serialize the action class to json.
Does that make sense?
Basically make sure that only your getter methods are prefixed with get and your action method is something else, like execXXX
Related
The following action:
def addMembers(){
Map result = [message:"successful"]
try {
def group = Group.get(params.id)
def json = request.JSON
def users = json.users.collect{Usr.get(it.id)}
result.members = groupService.addMembers(group,users)
}catch(Exception e){
message = "Exception $e"
result.message = message
response.setStatus(hsr.SC_METHOD_NOT_ALLOWED)
}
respond result, [model:[result:result]]
}//eo addMember
In conjunction with the following addMembers.gson file
model {
Map result
}
json{
message result.message
members g.render(template:"simpleMember", collection: result.members, var:'member')
}
Gets a null pointer exception:
java.lang.NullPointerException: Cannot get property 'message' on null object
I have things working well in other actions where I respond domain objects but the client side needs a message if I catch an exception and it really didn't seem worth it to create an arbitrary pogo when [message:"",members:[]] could do the same amount of work as an arbitrary extra file and an extra 5-10 lines of code.
Update 1
I tried replacing Map with an arbitrary ResultHolder class to placate any strict typing that might have been in play.
That didn't help
Update 2
In my .gson file I replaced
json{
with
json g.render(result){
And that gets me null output instead of null pointers.
Equally unacceptable.
Update 3
In order to try to assess how to interact with gson template without depending on ajax posts and database interaction I make the following arbitrary action:
def jsonDbug(){
def result = [message:"hi"]
respond result, [model:[jsonDbug:result]]
}
and an arbitrary gson file:
model{
Map jsonDebug
}
json{
says jsonDebug.message
}
This allows me to make changes faster to see what is going wrong.
I'm trying calling in other ways except respond now but nothing works.
It's as if JSON views are strictly for domain objects and nothing else.
It turns out that I wasn't that very far off when I started.
The problem was:
respond result, [model:[result:result]]
Which is the predominant example used at http://views.grails.org/latest/
When I changed to:
render(view:"addMembers", model:[result:result])
It worked exactly how I wanted it to.
This is a slightly messy questions. Although it appears I'm asking question about amCharts, I really just trying to figure how to extract an array from HTTP request and then turn it into a variable and place it in to 3-party javacript.
It all starts here, with this question, which was kindly answered by AmCharts support.
As one can see from the plnker. The chart is working. Data for the chart is hard coded:
`var chartData = [{date: new Date(2015,2,31,0,0,0, 0),value:372.10,volume:2506100},{date: new Date(2015,3,1,0, 0, 0, 0),value:370.26,volume:2458100},{date: new Date(2015,3,2,0, 0, 0, 0),value:372.25,volume:1875300},{date: new Date(2015,3,6,0, 0, 0, 0),value:377.04,volume:3050700}];`
So we know the amCharts part works. Know where the problem is changing hard coded data to a json request so it can be dynamic. I don't think this should be tremendously difficult, but for the life of me I can't seem figure it out.
The first issue is I can't find any documentation on .map, .subscribe, or .observable.
So here is a plunker that looks very similar to the first one, however it has an http providers and injectable. It's broken, because I can't figure out how to pull the data from the service an place it into the AmCharts function. I know how pull data from a http provider and display it in template using NgFor, but I don't need it in the template (view). As you can see, I'm successful in transferring the data from the service, with the getTitle() function.
this.chart_data =_dataService.getEntries();
console.log('Does this work? '+this.chart_data);
this.title = _dataService.getTitle();
console.log('This works '+this.title);
// Transfer the http request to chartData to it can go into Amcharts
// I think this should be string?
var chartData = this.chart_data;
So the ultimate question is why can't I use a service to get data, turn that data into a variable and place it into a chart. I suspect a few clues might be in options.json as the json might not be formatted correctly? Am I declaring the correct variables? Finally, it might have something to do with observable / map?
You have a few things here. First this is a class, keep it that way. By that I mean to move the functions you have inside your constructor out of it and make them methods of your class.
Second, you have this piece of code
this.chart_data =_dataService.getEntries().subscribe((data) => {
this.chart_data = data;
});
What happens inside subscribe runs asynchronously therefore this.chart_data won't exist out of it. What you're doing here is assigning the object itself, in this case what subscribe returns, not the http response. So you can simply put your library initialization inside of the subscribe and that'll work.
_dataService.getEntries().subscribe((data) => {
if (AmCharts.isReady) {
this.createStockChart(data);
} else {
AmCharts.ready(() => this.createStockChart(data));
}
});
Now, finally you have an interesting thing. In your JSON you have your date properties contain a string with new Date inside, that's nothing but a string and your library requires (for what I tested) a Date object, so you need to parse it. The problem here is that you can't parse nor stringify by default a Date object. We need to convert that string to a Date object.
Look at this snippet code, I used eval (PLEASE DON'T DO IT YOURSELF, IS JUST FOR SHOWING PURPOSES!)
let chartData = [];
for(let i = 0; i < data[0].chart_data.length; i++) {
chartData.push({
// FOR SHOWING PURPOSES ONLY, DON'T TRY IT AT HOME
// This will parse the string to an actual Date object
date : eval(data[0].chart_data[i].date);
value : data[0].chart_data[i].value;
volume : data[0].chart_data[i].volume;
});
}
Here what I'm doing is reconstructing the array so the values are as required.
For the latter case you'll have to construct your json using (new Date('YOUR DATE')).toJSON() and you can parse it to a Date object using new Date(yourJSON) (referece Date.prototype.toJSON() - MDN). This is something you should resolve in your server side. Assuming you already solved that, your code should look as follows
// The date property in your json file should be stringified using new Date(...).toJSON()
date : new Date(data[0].chart_data[i].date);
Here's a plnkr with the evil eval. Remember, you have to send the date as a JSON from the server to your client and in your client you have to parse it to a Date.
I hope this helps you a little bit.
If the getEntries method of DataService returns an observable, you need to subscribe on it to get data:
_dataService.getEntries().subscribe(
(data) => {
this.chart_data = data;
});
Don't forget that data are received asynchronously from an HTTP call. The http.get method returns an observable (something "similar" to promise) will receive the data in the future. But when the getEntries method returns the data aren't there yet...
The getTitle is a synchronous method so you can call it the way you did.
In a Grails 2.5.0 controller action method, it seems like the properties in the HTTP JSON body will not be used for command object binding if request.JSON has been accessed in a filter.
Why is that? It doesn't make any sense to me.
Is there any way to allow request.JSON to be used in a filter, and also for command object binding?
Yes, this is the default behavior of Grails while it comes to data binding with request body. When you read the request body via request.JSON in your filter then the corresponding input stream will be closed or gets empty. So, now Grails can't further access that request body to bind to the command object.
So, you can either access the request body on your own in the filter or can use it with the command object but can't both.
From Binding The Request Body To Command Objects heading http://grails.github.io/grails-doc/2.5.0/guide/theWebLayer.html#dataBinding:
Note that the body of the request is being parsed to make that work.
Any attempt to read the body of the request after that will fail since
the corresponding input stream will be empty. The controller action
can either use a command object or it can parse the body of the
request on its own (either directly, or by referring to something like
request.JSON), but cannot do both.
So, what are you trying to achieve is not possible directly. But, you can do something different. In your filter, read the incoming request body and store into the params or session (if filter passes the request to controller) and then manually bind the parameter in action:
MyFilters.groovy
class MyFilters {
def filters = {
foo(/* your filter */) {
before = {
// Your checks
Map requestData = request.JSON as Map
session.requestData = requestData
return true
}
}
}
}
Now, in your controller action, instead of doing:
class MyController {
def fooAction(MyCommandObject object) {
}
}
Do something like this:
class MyController {
def fooAction() {
MyCommandObject object = new MyCommandObject(session.requestData)
// Clear from session to clear up the memory
session.requestData = null
}
}
Update: The above solution, I've provided will work well but is not clean. #JoshuaMoore provided a link with a cleaner solution Http Servlet request lose params from POST body after read it once.
I have implemented a RESTful service using Jersey. I am able to return the desired output in JSON format. But, I also need to set Http Status Code and my customized status message. Status code and status message should not be part of the JSON output.
I tried following links:
JAX/Jersey Custom error code in Response
JAX-RS — How to return JSON and HTTP status code together?
Custom HTTP status response with JAX-RS (Jersey) and #RolesAllowed
but I am able to perform only one of the tasks, either returning JSON or setting HTTP status code and message.
I have code something like below:
import javax.ws.rs.core.Response;
public class MyClass(){
#GET
#Produces( { MediaType.APPLICATION_JSON })
public MyObject retrieveUserDetails()
{
MyObject obj = new MyObject();
//Code for retrieving user details.
obj.add(userDetails);
Response.status(Status.NO_CONTENT).entity("The User does not exist").build();
return obj;
}
}
Can anyone provide solution to this?
the mistakes are :
1. if status is set to NO_content (HTTP204) the norm is to have an entity empty. so entity will be returned as empty to your client. This is not what you want to do in all case, if found return details, if not found return 404.
2.Produces( { MediaType.APPLICATION_JSON }) tells that you will return a json content, and the content of entity is not a json. You will have to return a json. You will see I use jackson as it's part of Jersey.
set a #Path("/user") to set a endpoint path at least at Resource level.
Need to set a path in order to adress your resource (endpoint)
use a bean in order to pass multiple things. I've made an example bean for you.
as improvement caution with HTTP return, use the proper one
404 :not found resource
204 : empty....
take a look at the norm: http://www.wikiwand.com/en/List_of_HTTP_status_codes
Take a look the complete code in Gist: https://gist.github.com/jeorfevre/260067c5b265f65f93b3
Enjoy :)
Good evening everyone. I am currently using MVC 3 and I have a viewmodel that contains a property that is a List. I am currently using json2's JSON.stringify method to pass my viewmodel to my action method. While debugging I am noticing that all the simple properties are coming thru but the collection property is empty even though I know for sure that there is at least one object in the collection. I wanted to know if there is anyone that is running into the same issue. Below is the code that I am using to post to the action method:
$.post("/ReservationWizard/AddVehicleToReservation/",
JSON.stringify('#ViewData["modelAsJSON"]'),
function (data) {
if (data != null) {
$("#vehicle-selection-container").html(data);
$(".reservation-wizard-step").fadeIn();
}
});
The object #ViewData["modelAsJSON"] contains the following json and is passed to my action method
{"NumberOfVehicles":1,"VehiclesToService":[{"VehicleMakeId":0,"VehicleModelId":0}]}
As you can see the property "VehiclesToService" has one object but when it gets to my action method it is not translated to the corresponding object in the collection, but rather the collection is empty.
If anyone has any insight into this issue it would be greatly appreciated.
Thanks in advance.
UPDATE
OK after making the recommended changes and making the call to new JavaScriptSerializer().Serialize(#Model) this is the string that ultimately gets sent to my action method through the post
'{"NumberOfVehicles":1,"VehiclesToService":[{"VehicleMakeId":0,"VehicleModelId":0}]}'
I can debug and see the object that gets sent to my action method, but again the collection property is empty and I know that for sure there is at least one object in the collection.
The AddVehicleToReservation action method is declared as follows:
public ActionResult AddVehicleToReservation(VehicleSelection selections)
{
...
return PartialView("viewName", model);
}
Here's the problem:
JSON.stringify('#ViewData["modelAsJSON"]')
JSON.stringify is a client side function and you are passing as argument a list that's stored in the ViewData so I suppose that it ends up calling the .ToString() and you have
JSON.stringify('System.Collections.Generic.List<Foo>')
in your final HTML which obviously doesn't make much sense. Also don't forget that in order to pass parameters to the server using the $.post function the second parameter needs to be a javascript object which is not what JSON.stringify does (it generates a string). So you need to end up with HTML like this:
$.post(
'ReservationWizard/AddVehicleToReservation',
[ { id: 1, title: 'title 1' }, { id: 2, title: 'title 2' } ],
function (data) {
if (data != null) {
$('#vehicle-selection-container').html(data);
$('.reservation-wizard-step').fadeIn();
}
}
);
So to make this work you will first need to serialize this ViewData into JSON. You could use the JavaScriptSerializer class for this:
#{
var myList = new JavaScriptSerializer().Serialize(ViewData["modelAsJSON"]);
}
$.post(
'#Url.Action("AddVehicleToReservation", "ReservationWizard")',
// Don't use JSON.stringify: that makes JSON request and without
// proper content type header your sever won't be able to bind it
#myList,
function (data) {
if (data != null) {
$('#vehicle-selection-container').html(data);
$('.reservation-wizard-step').fadeIn();
}
}
);
And please don't use this ViewData. Make your views strongly typed and use view models.