How do you fix a names mismatch problem, if the client-side names are keywords or reserved words in the server-side language you are using?
The DOJO JavaScript toolkit has a QueryReadStore class that you can subclass to submit REST patterned queries to the server. I'm using this in conjunction w/ the FilteringSelect Dijit.
I can subclass the QueryReadStore and specify the parameters and arguments getting passed to the server. But somewhere along the way, a "start" and "count" parameter are being passed from the client to the server. I went into the API and discovered that the QueryReadStore.js is sending those parameter names.
I'm using Fiddler to confirm what's actually being sent and brought back. The server response is telling me I have a parameter names mismatch, because of the "start" and "count" parameters. The problem is, I can't use "start" and "count" in PL/SQL.
Workaround or correct implementation advice would be appreciated...thx.
//I tried putting the code snippet in here, but since it's largely HTML, that didn't work so well.
While it feels like the wrong thing to do, because I'm hacking at a well tested, nicely written JavaScript toolkit, this is how I fixed the problem:
I went into the DOJOX QueryReadStore.js and replaced the "start" and "count" references with acceptable (to the server-side language) parameter names.
I would have like to handled the issue via my PL/SQL (but I don't know how to get around reserved words) or client-side code (subclassing did not do the trick)...without getting into the internals of the library. But it works, and I can move on.
As opposed to removing it from the API, as you mentioned, you can actually create a subclass with your own fetch, and remove start/count parameters (theoretically). Have a look at this URL for guidance:
http://www.sitepen.com/blog/2008/06/25/web-service-data-store/
Start and count are actually very useful because they allow you to pass params for the query that you can use to filter massive data sets, and it helps to manage client-side paging. I would try to subclass instead, intercept, and remove.
Is your pl/sql program accessed via a URL and mod_plsql? If so, then you can use "flexible parameter passing" and the variables get assigned to an array of name/value pairs.
Define your package spec like this...
create or replace package pkg_name
TYPE plsqltable
IS
TABLE OF VARCHAR2 (32000)
INDEX BY BINARY_INTEGER;
empty plsqltable;
PROCEDURE api (name_array IN plsqltable DEFAULT empty ,
value_array IN plsqltable DEFAULT empty
);
END pkg_name;
Then the body:
CREATE OR REPLACE PACKAGE BODY pkg_name AS
l_count_value number;
l_start_value number;
PROCEDURE proc_name (name_array IN plsqltable DEFAULT empty,
value_array IN plsqltable DEFAULT empty) is
------------
FUNCTION get_value (p_name IN VARCHAR) RETURN VARCHAR2 IS
BEGIN
FOR i IN 1..name_array.COUNT LOOP
IF UPPER(name_array(i)) = UPPER(p_name) THEN
RETURN value_array(i);
END IF;
END LOOP;
RETURN NULL;
END get_value;
----------------------
begin
l_count_value := get_value('count');
l_start_value := get_value('start');
end api;
end pkg_name;
Then you can call pkg_name.api using
http://server/dad/!pkg_name.api?start=3&count=3
Related
Given the following object
Friend Class GetLocationsResult
Public Property X1 As String
Public Property X2 As String
Public Property X3 As String
Public Property X4 As String
Public Property X5 As String
Public Property X6 As Double
Public Property X7 As Double
End Class
And it is declared and instantiated thusly:
Dim objList as List(of GetLocationsResults) = new List(of GetLocationsResults)
And objList is populated via an iterator that churns through a collection of objects/aggregate classes. The iterator just shoves values into a new GetLocationsResult object and then adds it to the list.
And given the NewtonSoft JSONConvert.SerializeObject(objList) results:
{"d":"[{\"X1\":\"Store Name\",\"X2\":\"Address\",\"X3\":\"City\",\"X4\":\"State\",\"X5\":\"Zip\",\"X6\":Coord1,\"X7\":Coord2}]"}
This point has been addressed and is no longer an issue
There are several issues with this result set. First, for whatever odd
reason, the object being named "d" is not acceptable.
How can I specify something other than "d" for the "name" of the json array?
When I attempt to JSON.parse the response, it needs to be in the following format in order to actually get to the data:
resultSet = JSON.parse(data.d);
console.warn(resultSet[0].X1);
Having to say resultSet[0] is, of course, not acceptable.
How do I cause the 'JSONConvert.Serialize' method to not wrap the response in such a way that I have to refer to the first index of the
resulting JSON data so that I can say resultSet.X1 instead of
resultSet[0].X1?
As requested, here is some more detailed information that may be relevant to the issue at hand.
The data is being returned from a WCF service. The exposed method is decorated thusly:
<WebInvoke(Method:="GET", ResponseFormat:=WebMessageFormat.Json)>
and returns type String. The service is being consumed by a desktop application and a mobile platform. The desktop website can have its own method and, in fact, does because we don't want to deal with X1, X2, etc while the mobile platform devs have declared that as necessary. As noted, the method returns a number of results in the form of a custom, aggregate class which is then shoved into a class object which is only a collection of properties. The return statement is thus:
Return JsonConvert.SerializeObject(retVal)
where retVal is a List(of GetLocationsResult)
So while having to access the data via index may be fine for the website, it is not acceptable for the mobile platform. Because each will run their own methods, it is possible to have a unique solution for both if needed.
Three things.
It sounds like you're returning that back through an ASP.NET ASMX
ScriptService or ASPX [WebMethod]. When using one of those
endpoints, you don't need to (and shouldn't) manually serialize the
object into JSON. ASP.NET will do that for you automatically. You don't need to use JSONConvert at all; just return your object as the result. That's why you're seeing all that escaped data after the .d. It's JSON serialized twice.
As WhiteHat mentioned, the .d is a good thing in some situations. It's introduced by default in these ASP.NET JSON services and can't easily be removed on the server-side, but is easy to account for when you parse the response on the client-side.
You are returning a List(of GetLocationResults), which maps to a JavaScript array. That's why you need to use resultSet[0].X1 to access a value in the result. If you want to access that value via resultSet.X1, you need to be sure to return only a single GetLocationResults object instead of a List of them.
Does that help? If you could update your question with a more complete example of your server-side and client-side code, I could give you an example of how to address the preceding three issues.
I have inherited some code that uses the Play! framework which has scala.html files that have javascript in them. Play! and scala are all new to me.
One of the javascript functions does a post and gets back a JSON object. It then loops through the JSON object and creates an array.
var myArray = [];
function createArray(){
$.post('/createArray', $('#arrayForm').serialize()).done(function( data ) {
var obj1 = JSON.parse(data);
$.each(obj1, function(idx, obj) {
myArray.push(obj.name);
});
});
return true;
}
It then uses this array (of strings) to create a text input field that does autocomplete using the data in the array.
I want/need to convert this text input to a select dropdown using the Play! #select but the options arg for #select wants a List object (or Map or Seq - just figured List would be easier since I already have an array of strings).
If I manually create the List object, it works fine.
#select(pForm("equipName"), options(scala.collection.immutable.List("Yes","No")))
The problem is I cannot figure out how to convert the myArray array to a List object which I can then pass to the #select options.
I have found a lot of posts that talk about converting a scala List to an array but can't find a way to go the other way. I am hoping it is an easy thing that I can't seem to figure out.
Thanks in advance for the help.
You can not do that. And more precisely - you do not want to do that.
So basically your play application run on server. In your Play application all those .scala html files are compiled to generate some functions.
Now, when a play application receives a request from a client browser, it gets mapped to some controller by by router. The controller does some processing and finally take one of these above functions ( lets say for index.scala.html we get views.html.index ) and call this function with some parameters.
These functions returns some text which is then sent to the client's browser as HTTP response with response header Content-Type:text/html; charset=utf-8 which tells the browser to treat this text as html.
Now, the browser renders the html which has embedded JavaScript and hence runs the JavaScript. So... basically your JavaScrpt code does not exist on server... for play all of it is just text.
Both of these Scala code and JavaScript code are executed at very different times, at different computers and in different environments hence you can not do whatever you are saying.
I was wondering how I would go about converting data when I call the set or save methods on a model. Specifically converting the inputted date string to epoch time.
I know I could just convert it in the view, but as far as I know, that wont work very well with my validations.
The model code is here if you are interested.
Thanks for any help!
What I can gather you have two options:
1 Convert them in your view
This means you can roll your own conversions for the view or use something like Backbone.modelbinder to make the conversions for you. Then you have to modify your validate method to accept an epoch date. Personally I would prefer this one, I think that it's suitable for the UI to handle verifying user input's well-formedness and conversion to the right unit and let the model handle validating if the values are within the accepted limits.
2 Convert them in your model
Backbone doesn't offer this out-of-the-box. If you set something to be something, there is no easy way to convert it to something else, especially between validate and set. Basically your best bet would be to roll your own set -function with something like
// Inside the set function
...
if (!this._validate(attrs, options)) return false; // real line in the set func
// insert something like this, after validate you know the values are eligible for conversion
attrs = this.convert(attrs); // a custom func that converts attributes to right units
...
// set continues as usual
Hope this helps!
You can overwrite the sync method in your model:
, sync: function(method, model) {
if(method === 'update'){
// change you model here
}
}
This will be invoke bevor data is send to the backend server. The "method" indecates 'create' or 'update'.
According to the sources, validate is the only callback that is called before set and save. You can to set the values in your validate method directly on the attributes object. Unfortunately you cannot make any changes to attributes at this point.
You can use a plugin like backbone.getters.setters to do this since it looks like it won't be a feature added to backbone.
Having some trouble getting BIRT to allow me to create a Data Set with Parameters that are set at run time.
The SQL that is giving me the error is:
...
FROM SPRIDEN, SPBPERS P, POSNCTL.NBRJOBS X, NHRDIST d1
where D1.NHRDIST_PAYNO between '#PAYNO_BEGIN' and '#PAYNO_BEGIN'
AND D1.NHRDIST_YEAR = '#YEAR'
...
I have my Report Parameters defined as PaynoBegin, PaynoEnd, Year
I also have a Data Set script set for beforeOpen as follows:
queryText = String (queryText).replace ("#PAYNO_END", Number(params["PaynoEnd"]));
queryText = String (queryText).replace ("#PAYNO_BEGIN", Number(params["PaynoBegin"]));
queryText = String (queryText).replace ("#YEAR", Number(params["Year"]));
The problem seems to be that the JDBC can't get the ResultSet from this, however I have 10 other reports that work the same way. I have commented out the where clause and it will generate the data set. I also tried breaking the where clause out into two and clauses with <= and >=, but it still throws a ORA-01722 invalid number error on the line.
Any thoughts on this?
Two quite separate thoughts:
1) You have single quotes around each of your parameters in the query, yet it appears as though each one is a numeric - try removing the single quotes, so that the where clause looks like this:
where D1.NHRDIST_PAYNO between #PAYNO_BEGIN and #PAYNO_BEGIN
AND D1.NHRDIST_YEAR = #YEAR
Don't forget that all three parameters should be required. If the query still returns an error, try replacing #PAYNO_BEGIN, #PAYNO_BEGIN and #YEAR with hardcoded numeric values in the query string, and see whether you still get an error.
2) You are currently using dynamic SQL - amending query strings to replace specified markers with the text of the entered parameters. This makes you vulnerable to SQL Injection attacks - if you are unfamiliar with the term, you can find a simple example here.
If you are familiar with the concept, you may be under the impression that SQL Injection attacks cannot be implemented with numeric parameters - Tom Kite has recently posted a few articles on his blog about SQL Injection, including one that deals with a SQL Injection flaw using NLS settings with numbers.
Instead, you should use bind parameters. To do so with your report, amend your query to include:
...
FROM SPRIDEN, SPBPERS P, POSNCTL.NBRJOBS X, NHRDIST d1
where D1.NHRDIST_PAYNO between ? and ?
AND D1.NHRDIST_YEAR = ?
...
instead of the existing code, remove the queryText replacement code from the beforeOpen script and map the three dataset parameters to the PaynoBegin, PaynoEnd and Year report parameters respectively in the Dataset Editor. (You should also change any other replaced text in your query text to bind parameter markers (?) and map dataset parameters to them as required.)
I need to call into a Win32 API to get a series of strings, and I would like to return an array of those strings to JavaScript. This is for script that runs on local machine for administration scripts, not for the web browser.
My IDL file for the COM object has the interface that I am calling into as:
HRESULT GetArrayOfStrings([out, retval] SAFEARRAY(BSTR) * rgBstrStringArray);
The function returns correctly, but the strings are getting 'lost' when they are being assigned to a variable in JavaScript.
The question is:
What is the proper way to get the array of strings returned to a JavaScript variable?
If i recall correctly, you'll need to wrap the SAFEARRAY in a VARIANT in order for it to get through, and then use a VBArray object to unpack it on the JS side of things:
HRESULT GetArrayOfStrings(/*[out, retval]*/ VARIANT* pvarBstrStringArray)
{
// ...
_variant_t ret;
ret.vt = VT_ARRAY|VT_VARIANT;
ret.parray = rgBstrStringArray;
*pvarBstrStringArray = ret.Detach();
return S_OK;
}
then
var jsFriendlyStrings = new VBArray( axOb.GetArrayOfStrings() ).toArray();
Shog9
is correct. COM scripting requires that all outputs be VARIANTS.
In fact, it also requires that all the INPUTs be VARIANTS as well -- see the nasty details of IDispatch in your favorite help file. It's only thought the magic of the Dual Interface implementation by ATL and similar layers (which most likely is what you are using) that you don't have to worry about that. The input VARIANTs passed by the calling code are converted to match your method signature before your actual method is called.