I need some help please...
I am working with a GWT enabled web application. I am using the gwt-2.3.0 SDK.
I have a method that extends the DataSource class and uses the transformResponse method:
public class DeathRecordXmlDS extends DataSource {
protected void transformResponse(DSResponse response, DSRequest request, Object data){
super.transformResponse(response, request, data);
}
}
As I understand, the transformResponse() method should get control and at this point, I will have access to the data that is being provided to the Client side of my application. I am trying to work with the Object data parameter (the third parameter) that is passed in.
I am expecting an XML formatted string to be passed in. The XML will contain data (a count field) that I need to access and use.
I don't seem to be getting an XML string. Here's what I know...
I do see the XML data being passed to my webapp (the client). I can see this because I inspect the webpage that I am working with and I see the Response data. Here's an example of something that I expect to receive:
XML data from Query:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Collection numRecords="0">
<DeathRecords/>
</Collection>
The above XML is valid (I checked it in a Validator). This is a case where there was no data (No Death Records) being returned to my application. The numRecords XML attribute is set to "0". Of course, If I do have records returned the numRecords will contain the number of records and I'll get that same number of DeathRecord nodes.
I am not getting the above data (or, I don't know how to work with it) in the transformResponse() method.
Here's what I've done to try to figure this out...
The Object data parameter... it is a JavaScriptObject. I know this because I did a .getClass().getName() on it:
DeathRecordXmlDS::transformResponse() data.getClass().getName(): com.google.gwt.core.client.JavaScriptObject$
Then, to try to work with it, I converted it to a String:
com.google.gwt.core.client.JavaScriptObject dataJS = (com.google.gwt.core.client.JavaScriptObject)data;
System.out.println("DeathRecordXmlDS::transformResponse() data as a JavaScriptObject: "+dataJS.toString());
The contents of 'data' formatted as a String look like:
DeathRecordXmlDS::transformResponse() data as a JavaScriptObject: [XMLDoc <Collection>]
So, it looks like I have something that has to do with my 'Collection' node, but not a String of XML data that I can parse and get to my numRecords attribute.
What do I need to do to gain access to the XML in the transformResponse() method?
Thanks!
I think your data object is already translated to a javascript collection.
Maybe you could use the utility class XMLTools to retrieve your numRecords information:
Integer numRecords = Integer.parseInt(XMLTools.selectString(data, "Collection/#numRecords"));
After working on this for an additional period of time I was able to read the XML data that I am working with. I used the following piece of code:
try{
JsArray<JavaScriptObject> nodes = ((JavaScriptObject) XMLTools.selectNodes(data, "/Collection/#numRecords")).cast();
for (int i = 0; i < nodes.length(); i++) {
com.google.gwt.dom.client.Element element = (com.google.gwt.dom.client.Element) nodes.get(i);
numRecords = element.getNodeValue();
}
} catch(Exception e){
// If Parsing fails, capture the exception
System.out.println("DeathRecordXmlDS::transformResponse() Not able to parse the XML");
}
I think the first step to solving this was understanding that the parameter 'data' of type Object was really a JavaScriptObject. I learned this after looking at the .getClass() and .getName(). This helped me understand what I was working with:
System.out.println("DeathRecordXmlDS::transformResponse() data.getClass().getName(): "+data.getClass().getName());
Once I knew it was a JavaScriptObject, I was able to do a little more focused of a Google search for what I was trying to accomplish. I was a little surprised that the XMLTools.selectNodes() function worked the way it did, but the end result is that I was able to read the numRecords attribute.
Thanks for the suggestion!
Related
Grails 2.5. I need to log the request and the response to log file.
This is to log REST/JSON api calls. I need to log both the request JSON (which is easy with a filter), and the response JSON (Which is looking impossible)
an api call looks like this:
class myController {
def myMethod() {
def json = request.JSON
:
render(status:200, contentType:'application/json' {
['something': "something",'sometingElse' : 42]
}
Tried creating a filter, e.g:
class LoggingFilters {
def filters = {
after = { Map model ->
log.debug "${response.???"
}
The question is, how do you get a handle on the output? Tried respose.outputStream.toString() etc, but it says something has already got the output stream.
I saw one suggestion which said don't use render, return a model with a map with a single item: data, and render this outside against some dummy jsp. Then you can get the model in the filter. The problem with this is that we have many hundreds of render statements, and we dont really want to retest everything (we have no automated testing).
Another other work around is to use tomcat request dumper filter, but this would not meet our requirements (e.g. we need to scrub certain output, such as passwords, want to be able to log to db, only want to log very specific things etc).
We tried this plugin: https://grails.org/plugin/httplogger , but it doesnt work with grails 2.5.
I am building a REST API and facing this issue: How can REST API pass very large JSON?
Basically, I want to connect to Database and return the training data. The problem is in Database I have 400,000 data. If I wrap them into a JSON file and pass through GET method, the server would throw Heap overflow exception.
What methods we can use to solve this problem?
DBTraining trainingdata = new DBTraining();
#GET
#Produces("application/json")
#Path("/{cat_id}")
public Response getAllDataById(#PathParam("cat_id") String cat_id) {
List<TrainingData> list = new ArrayList<TrainingData>();
try {
list = trainingdata.getAllDataById(cat_id);
Gson gson = new Gson();
Type dataListType = new TypeToken<List<TrainingData>>() {
}.getType();
String jsonString = gson.toJson(list, dataListType);
return Response.ok().entity(jsonString).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET").build();
} catch (SQLException e) {
logger.warn(e.getMessage());
}
return null;
}
The RESTful way of doing this is to create a paginated API. First, add query parameters to set page size, page number, and maximum number of items per page. Use sensible defaults if any of these are not provided or unrealistic values are provided. Second, modify the database query to retrieve only a subset of the data. Convert that to JSON and use that as the payload of your response. Finally, in following HATEOAS principles, provide links to the next page (provided you're not on the last page) and previous page (provided you're not on the first page). For bonus points, provide links to the first page and last page as well.
By designing your endpoint this way, you get very consistent performance characteristics and can handle data sets that continue to grow.
The GitHub API provides a good example of this.
My suggestion is no to pass the data as a JSON but as a file using multipart/form-data. In your file, each line could be a JSON representing a data record. Then, it would be easy to use a FileOutputStream to receive te file. Then, you can process the file line by line to avoid memory problems.
A Grails example:
if(params.myFile){
if(params.myFile instanceof org.springframework.web.multipart.commons.CommonsMultipartFile){
def fileName = "/tmp/myReceivedFile.txt"
new FileOutputStream(fileName).leftShift(params.myFile.getInputStream())
}
else
//print or signal error
}
You can use curl to pass your file:
curl -F "myFile=#/mySendigFile.txt" http://acme.com/my-service
More details on a similar solution on https://stackoverflow.com/a/13076550/2476435
HTTP has the notion of chunked encoding that allows you send a HTTP response body in smaller pieces to prevent the server from having to hold the entire response in memory. You need to find out how your server framework supports chunked encoding.
I have a JAX-RS web service which looks like so:
#Path("/status")
#Produces("application/xml")
#GET
public PrecisionStatus getPrecisionValue(){
PrecisionStatus status = ...
return status;
}
Initially, the result was:
<PrecisionStatus sensorID="TemperatureSensor5"><condition>OK</condition><fieldValue>60.0</fieldValue></PrecisionStatus>
It looks fine, but I want to declare the xsd file which describes this document. By using JAXB marshalling features, I was able to produce (in logger/console) the desired output:
<PrecisionStatus sensorID="TemperatureSensor5" xsi:noNamespaceSchemaLocation="http://mysite.com/myapp/xsd0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<condition>OK</condition>
<fieldValue>60.0</fieldValue>
</PrecisionStatus>
(this is confirmed by unmarshalling the object).
However, if i return this object return status;, the browser receives the former xml document, namely the one without the reference to xsd.
I am pretty sure that the object has the right form, but somewhat the reference to xsd is stripped in the final result. Any clue?
You could create a JAX-RS MessageBodyWriter to have access to the Marshaller in order to set the JAXB_NO_NAMESPACE_SCHEMA_LOCATION property. For a complete example see:
Formatted XML output in CXF?
We have a number of forms on our site that are shown with jquery .dialog and we submit them using an ajax post request.
I've done a fair bit of research and from what I can tell there isn't any definite patterns on how to return validation errors from the server side as a result of an ajax request.
Pretty much the only pattern I could find was to post the form and then do validation server side and in either case return a json object that encapsulated a result and if the result was incorrect the form html
ie.
{result: true}
{success: false, html = "<form>....</form>"}
So in the case the result was false you would need to rewire up any events attached to items on the form as you would be replacing the old form with the new form that has the validation errors.
This seems like an ok approach but you also end up potentially returning a lot more data to the client that you need to when they only really need to validation messages and you are also forced to rewire the form up which is a bit annoying.
I did find one other mention of somehow getting the validation errors and returning them in a json object from the action and somehow telling the client to display them against the correct fields.
Is there any frameworks out there that make this easier or should I write my own or just stick to returning the entire partial for the form and rewiring it when validation is incorrect?
I don't know of any frameworks that handle this particular case–and I don't know that there's a clear best practice–but it's easy enough to serialize validation errors and return them as a JSON object. You could try this extension method on ModelStateDictionary:
public static IEnumerable<ValidationResult> GetValidationResults(this ModelStateDictionary dictionary)
{
foreach (var key in dictionary.Keys)
foreach (var error in dictionary[key].Errors)
if (error != null)
yield return new ValidationResult(error.ErrorMessage, new string[] { key });
}
And in the controller:
if (!ModelState.IsValid)
{
return new JsonResult(ModelState.GetValidationResults());
}
But you're right, you would then have to loop through the object and append the errors to the correct fields. If you have ClientValidationEnabled and UnobtrusiveJavaScriptEnabled set to true, the loop would look something like this:
$.each(errors, function(i, item) {
$('span[data-valmsg-for=' + item.MemberNames[0] + ']').html(item.ErrorMessage);
})
If not, it wouldn't be that difficult to match up the error messages to their respective fields as the object contains the field name. This would definitely save you some data across the wire, but it moves a larger share of the validation responsibility into Javascript. Like I said, I don't know that there's a clear best practice, but I have used this method in the past with success.
I have an ASP.NET MVC 2 application which in part allows a user to filter data and view that data in a JQGrid.
Currently this consists of a controller which initialises my filter model and configures how I wish my grid to be displayed. This information is used by a view and a partial view to display the filter and the grid shell. I use an editor template to display my filter. The JQGrid makes use of a JsonResult controller action (GET) to retrieve the results of the filter (with the addition of the paging offered by the grid - only a single page of data is returned by the GET request. The Uri used by the grid to request data contains the filter model as a RouteValue - and currently contains a string representation of the current state of the filter. A custom IModelBinder is used to convert this representation back into an instance of the filter model class.
The user can change the filter and press a submit button to get different results - this is then picked up by an (HttpPost) ViewResult action which takes the filter model - reconstituted by a further model binder and causes the grid shell to be updated.
So I have:
FilterModel
Represents the user's desired filtering characteristics
FilterModelEditorTemplateSubmissionBinder : DefaultModelBinder - used to convert the request information supplied from a user changing their filtering characteristics into the appropriate FilterModel instance.
FilterModelStringRepresentationBinder : IModelBinder - used to convert the encoded filter from the JQGrid GET request for data so the correct request is made of the service which is ultimately performing the query and returning the relevant data.
ViewResult Index() - constructs a default filter, configures the grid specification and returns the view to render the filter's editor template, and the grid shell.
[HttpPost]ViewResult Filter(FilterModel filter) - takes the new filter characteristics and returns the same view as Index(). Uses FilterModelEditorTemplateSubmissionBinder to bind the filter model.
JsonResult GetData(FilterModel filter, string sidx, string sord, int page, int rows) - called from the JQGrid in order to retrieve the data. Uses FilterModelStringRepresentationBinder to bind the filter model.
As a complication, my filter model contains a option to select a single value from a collection of items. This collection is retrieved from a service request and I don't want to keep querying for this data everytime I show the filter, currently I get it if the property is null, and then include the options hidden in the editor template and encoding in the string representation. These options are then reconstituted by the relevant model binder.
Although this approach works I can't help but feel that I am having to basically reinvent viewstate in order to maintain my filter and the included options. As I am new to ASP.NET MVC but am very happy with classic ASP and ASP.NET Web Forms I thought I'd throw this out there for comment and guidance as to find a way which more closely fits with the MVC pattern.
It seems to me that the best way in to divide some actions which provide pure data for the jqGrid from other controller action. Such jqGrid-oriented actions can have prototype like:
JsonResult GetData(string filter, string sidx, string sord, int page, int rows)
I personally prefer to implement this part as WCF service and to have this WCF service as a part of the same ASP.NET site. In general it's much more the matter of taste and depends on your other project requirements.
This part of you ASP.NET site could implement users authentication which you need and can be tested with unit tests exactly like other actions of your controllers.
The views of the ASP.NET MVC site can have empty data for jqGrids, and have only correct URLs and probably generate the HTML code depends on the users permission in the site. Every page will fill the data of jqGrids with respect of the corresponds requests to the server (request to the corresponding GetData action).
You can use HTTP GET for the data for the best data caching. The caching of data is the subject of a separate discussion. If you do this, you should use prmNames: { nd:null } in the definition of jqGrid to remove unique nd parameter with the timestamp added per default to every GET request. To have full control of the data caching on the server side you can for example add in HTTP headers of the server responses both "Cache-Control" set to "max-age=0" and "ETag" header with the value calculated based of the data returned in the response. You should test whether the request from the client has "If-None-Match" HTTP header with the value of "ETag" coresponds the data cached on the client. Then you should verify whether the current data on the server (in the database) are changed and, if there are not changed, generate a response with an empty body (set SuppressEntityBody to true) and return "304 Not Modified" status code (HttpStatusCode.NotModified) instead of default "200 OK". A more detail explanation is much more longer.
If you don't want optimize you site for caching of HTTP GET data for jqGrids you can either use HTTP POST or don't use prmNames: { nd:null } parameter.
The code inside of JsonResult GetData(string filter, string sidx, string sord, int page, int rows) is not very short of cause. You should deserialise JSON data from the filter string and then construct the request to the data model depends on the method of the data access which you use (LINQ to SQL, Entity Model or SqlCommand with SqlDataReader). Because you have this part already implemented it has no sense to discuss this part.
Probably the main part of my suggestion is the usage of clear separation of controller actions which provide the data for all your jqGrids and the usage of MVC views with empty data (having only <table id="list"></table><div id="pager"></div>). You should also has no doubt with having a relative long code for analyzing of filters which come from the Advance Searching feature of the jqGrid and generating or the corresponding requests to your data model. Just implement it one time. In my implementation the code in also relatively complex, but it is already written one time, it works and it can be used for all new jqGrids.
I made this once, very simple.
pseudo code:
Controller
[HttpGet]
public ActionResult getList(int? id){
return PartialView("Index", new ListViewModel(id??0))
}
ViewModel
public class ListViewModel{
//ObjectAmountPerPage is the amount of object you want per page, you can modify this as //parameter so the user
//can choose the amount
public int ObjectAmountPerPage = 20 //you can make this into a variable of any sort, db/configfile/parameter
public List<YourObjectName> ObjectList;
public int CurrentPage;
public ListViewModel(id){
Currentpage = id;
using (MyDataContext db = new MyDataContext()){
ObjectList = db.YourObjectName.OrderBy(object=>object.somefield).getListFromStartIndexToEndIndex(id*ObjectAmountPerPage ,(id*ObjectAmountPerPage) +20).toList();
}
}
}
Now Create A RenderPartial:
PartialView
<#page inherit="IEnumerable<ListViewMode>">
<%foreach(YourObjectName object in Model.ObjectList){%>
Create a table with your fields
<%}%>
And create a view that implements your Jquery, other components+your partialView
View
<javascript>
$(function(){
$("#nextpage").click(function(){
(/controller/getlist/$("#nextpage").val(),function(data){$("#yourlist").html = data});
});
});
</javascript>
<div id="yourlist">
<%=Html.RenderPartial("YourPartialView", new ListViewModel())%>
</div>
<something id="nextpage" value"<%=Model.CurentPage+1%>">next page</something>
I hope this helps, this is according to the MVC- mv-mv-c principle ;)
Model-View -(modelview) - control