Xpage read JSON context - http POST request - json

I'm trying to read java generated JSON stream created by out.writeBytes with my Xpage. I can get data like getServerPort and others (listed in code below) but when I'm trying to read context with BufferedReader or ServletInputStream I'm reciving errors.
Any one knows simple way to read stream content like that on Xpage ? readLine method returned null.
var exCon = facesContext.getExternalContext()
var httpRequest:javax.faces.contex.ExternalContext =exCon.getRequest();
print("CallCenter getContext "+String(exCon.getContext()))
print("CallCenter ContentType "+String(httpRequest.getContentType()))
print("CallCenter ContentLength"+String(httpRequest.getContentLength()))
print("CallCenter RemoteAddr "+String(httpRequest.getRemoteAddr() ))
print("CallCenter ServerPort "+String(httpRequest.getServerPort()))
facesContext.responseComplete();
// ONE OF METHODS I've TRIED =============
var stringBuffer:java.lang.StringBuffer = new java.lang.StringBuffer(80);
var line = null;
var reader:java.io.BufferedReader = httpRequest.getReader();
while ((line = reader.readLine()) != null)
{
stringBuffer.append(line);
stringBuffer.append("\n");
}
print("Buffer "+stringBuffer.toString());
// ============================
} catch(e) {
_dump(e);
fdf

There can only be one: the stream or the reader. Instead of getReader() use new InputStreamReader(in); point in to the inputstream of the context

Related

best overloaded method match for `RestSharp.Deserialize<RootObject>(RestSharp.IRestResponse)' has some invalid arguments

So i am working this project on Xamarin forms, and get the error as in title on
var rootObject = deserial.Deserialize<RootObject>(gameJson);
I am supposed to return the list of games to my app.How can i remove the error?
public async Task<Game[]> GetGamesAsync(){
var client = new RestClient("http://mystore/");
var request = new RestRequest ("api/Games", Method.GET);
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
var apiKey = session ["ApiKey"];
var userId = session ["UserId"];
try
{
request.AddHeader ("authenticationkey",apiKey.ToString ());
request.AddHeader ("authenticationid",userId.ToString ());
}
catch{}
IRestResponse response = client.Execute (request);
statusCodeCheck (response);
var gameJson = response.Content;
if (response.StatusCode == HttpStatusCode.OK) {
RestSharp.Deserializers.JsonDeserializer deserial = new RestSharp.Deserializers.JsonDeserializer ();
var rootObject = deserial.Deserialize<RootObject>(gameJson);
return rootObject.games;
}
else if(response.StatusCode == HttpStatusCode.Forbidden){
return null;
}
}
Not sure you are looking for this but I also using Restsharp in portable library and I'm deserializing datacontracts with Json.NET's JsonConvert.DeserializeObject<T>
method. I have not encountered any problem with it yet.
Also another possible solution is that the returned data is wrapped and the main object is not the RootObject.

Facing Issue with Timespan in rest service serialization

I am using REST service to get the data from the Db.
In my class, I am having the property "UploadTime" of datatype TimeSpan?.
The time span is calculated based on the difference between dates and in the response,I ma getting response as :
ArrayOfUploadUI xmlns="http://schemas.datacontract.org/2004/07/NMS.ApplicationService.HIM.Objects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<UploadUI>
<UID>1</UID>
<DateCompleted>2015-01-08T10:46:25.25</DateCompleted>
<DateNotified>2015-01-07T10:46:25.25</DateNotified>
<DateDictationStartTime i:nil="true" />
<DateDictationEndTime i:nil="true" />
<UploadTime>P1D</UploadTime>
<ExistsOnBackend>false</ExistsOnBackend>
</UploadUI>
</ArrayOfUploadUI>
.
I am getting the following exception while trying to get the data:
using (HttpResponseMessage response = await _HttpClient(session).GetAsync(apiUrl))
{
if (response.IsSuccessStatusCode)
result = await response.Content.ReadAsAsync<T>();
else
await _HandleInvalidResponseAsync(response);
}
I am getting issue at the "response.Content.ReadAsAsync();".
Error is:
Error converting value "P1D" to type 'System.Nullable`1[System.TimeSpan]'. Path '[0].UploadTime', line 1, position 518.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType).
I googled and I came to know that WCF serilaizing the "timeSpan"datatype from "1:0:0:00" to "P1D".
My issue is how to deserialize this on the response level.
I have done formatting for the date at the source level and the issue got resolved.
JsonSerializerSettings dateFormatSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
};
string jsonNMSPlatformObject = JsonConvert.SerializeObject(nmsPlatformObject,dateFormatSettings);
using (HttpContent httpContent = new StringContent(jsonNMSPlatformObject))
{
httpContent.Headers.ContentType = new MediaTypeHeaderValue(JsonMedaType);
var request = new HttpRequestMessage(HttpMethod.Delete, apiUrl);
request.Content = httpContent;
using (HttpResponseMessage response = await _HttpClient(session).SendAsync(request))
{
if (response.IsSuccessStatusCode)
return;
else
await _HandleInvalidResponseAsync(response, jsonNMSPlatformObject);
}
}

Antlr4 StringTemplate not compatible with Json.net dynamic items

I would like to read a dynamic object from a json file and then use this in a stringTemplate.
The following code works.
dynamic data = new { bcName = "Lixam B.V", periodName = "July 2013" };
var engine = new Template("<m.bcName> <m.periodName>");
engine.Add("m", data);
engine.Render().Should().Be("Lixam B.V July 2013");
The following code fails
var json = "{bcName : 'Lixam B.V', periodName : 'July 2013'}";
dynamic data = JsonConvert.DeserializeObject(json);
string name = (data.bcName);
name.Should().Be("Lixam B.V"); // this passes
var engine = new Template("<m.bcName> <m.periodName>");
engine.Add("m", data);
engine.Render().Should().Be("Lixam B.V July 2013"); //fails
Is there another way to configure JsonConverter to be compatible with StringTemplate
You need to create an IModelAdaptor for whatever the compiled type representing dynamic is, and register it using TemplateGroup.RegisterModelAdaptor.
Inspired on Mr. Harwell's answer, I've implemented an IModelAdaptor that enable the usage of Newtonsoft.Json parsed objects.
Here it goes:
internal class JTokenModelAdaptor : Antlr4.StringTemplate.IModelAdaptor
{
public object GetProperty(
Antlr4.StringTemplate.Interpreter interpreter,
Antlr4.StringTemplate.TemplateFrame frame,
object obj,
object property,
string propertyName)
{
var token = (obj as JToken)?.SelectToken(propertyName);
if (token == null)
return null;
if (token is JValue)
{
var jval = token as JValue;
return jval.Value;
}
return token;
}
}
You just need to register the adaptor in your template group, like this:
template.Group.RegisterModelAdaptor(typeof(JToken), new JTokenModelAdaptor());

APEX, Unit Test, Callout No Response with Static Resource

Bit stuck on another one i'm afraid, i am trying to write a unit test for a bulk APEX class.
The class has a calllout to the google api, so i have created a static resource which i am feeding in via a mock, so i can complete testing of processing the JSON that is returned. However for some reason the response is always empty.
Now the very odd thing is that if i use exactly the same callout/JSON code, and the same mock code on a previous #future call, then it does return fine.
Here is the class:
global class mileage_bulk implements Database.Batchable<sObject>,
Database.AllowsCallouts
{
global Database.QueryLocator start(Database.BatchableContext BC)
{
String query = 'SELECT Id,Name,Amount,R2_Job_Ref__c,R2_Shipping_Post_Code__c,Shipping_Postcode_2__c FROM Opportunity WHERE R2_Shipping_Post_Code__c != null';
return Database.getQueryLocator(query);
//system.debug('Executing'+query);
}
global void execute(Database.BatchableContext BC, List<Opportunity> scope)
{
system.debug(scope);
for(Opportunity a : scope)
{
String startPostcode = null;
startPostcode = EncodingUtil.urlEncode('HP27DU', 'UTF-8');
String endPostcode = null;
String endPostcodeEncoded = null;
if (a.R2_Shipping_Post_Code__c != null){
endPostcode = a.R2_Shipping_Post_Code__c;
Pattern nonWordChar = Pattern.compile('[^\\w]');
endPostcode = nonWordChar.matcher(endPostcode).replaceAll('');
endPostcodeEncoded = EncodingUtil.urlEncode(endPostcode, 'UTF-8');
}
Double totalDistanceMeter = null;
Integer totalDistanceMile = null;
String responseBody = null;
Boolean firstRecord = false;
String ukPrefix = 'UKH';
if (a.R2_Job_Ref__c != null){
if ((a.R2_Job_Ref__c).toLowerCase().contains(ukPrefix.toLowerCase())){
system.debug('Is Hemel Job');
startPostcode = EncodingUtil.urlEncode('HP27DU', 'UTF-8');
} else {
system.debug('Is Bromsgrove Job');
startPostcode = EncodingUtil.urlEncode('B604AD', 'UTF-8');
}
}
// build callout
Http h = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('http://maps.googleapis.com/maps/api/directions/json?origin='+startPostcode+'&destination='+endPostcodeEncoded+'&units=imperial&sensor=false');
req.setMethod('GET');
req.setTimeout(60000);
system.debug('request follows');
system.debug(req);
try{
// callout
HttpResponse res = h.send(req);
// parse coordinates from response
JSONParser parser = JSON.createParser(res.getBody());
responseBody = res.getBody();
system.debug(responseBody);
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'distance')){
parser.nextToken(); // object start
while (parser.nextToken() != JSONToken.END_OBJECT){
String txt = parser.getText();
parser.nextToken();
//system.debug(parser.nextToken());
//system.debug(txt);
if (firstRecord == false){
//if (txt == 'text'){
//totalDistanceMile = parser.getText();
system.debug(parser.getText());
//}
if (txt == 'value'){
totalDistanceMeter = parser.getDoubleValue();
double inches = totalDistanceMeter*39.3701;
totalDistanceMile = (integer)inches/63360;
system.debug(parser.getText());
firstRecord = true;
}
}
}
}
}
} catch (Exception e) {
}
//system.debug(accountId);
system.debug(a);
system.debug(endPostcodeEncoded);
system.debug(totalDistanceMeter);
system.debug(totalDistanceMile);
// update coordinates if we get back
if (totalDistanceMile != null){
system.debug('Entering Function to Update Object');
a.DistanceM__c = totalDistanceMile;
a.Shipping_Postcode_2__c = a.R2_Shipping_Post_Code__c;
//update a;
}
}
update scope;
}
global void finish(Database.BatchableContext BC)
{
}
}
and here is the test class;
#isTest
private class mileage_bulk_tests{
static testMethod void myUnitTest() {
Opportunity opp1 = new Opportunity(name = 'Google Test Opportunity',R2_Job_Ref__c = 'UKH12345',R2_Shipping_Post_Code__c = 'AL35QW',StageName = 'qualified',CloseDate = Date.today());
insert opp1;
Opportunity opp2 = new Opportunity(name = 'Google Test Opportunity 2',StageName = 'qualified',CloseDate = Date.today());
insert opp2;
Opportunity opp3 = new Opportunity(name = 'Google Test Opportunity 3',R2_Job_Ref__c = 'UKB56789',R2_Shipping_Post_Code__c = 'AL35QW',StageName = 'qualified',CloseDate = Date.today());
insert opp3;
StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
mock.setStaticResource('googleMapsJSON');
mock.setStatusCode(200); // Or other appropriate HTTP status code
mock.setHeader('Content-Type', 'application/json'); // Or other appropriate MIME type like application/xml
//Set the mock callout mode
Test.setMock(HttpCalloutMock.class, mock);
system.debug(opp1);
system.debug(opp1.id);
//Call the method that performs the callout
Test.startTest();
mileage_bulk b = new mileage_bulk();
database.executeBatch((b), 10);
Test.stopTest();
}
}
Help greatly appreciated!
Thanks
Gareth
Not certain what 'googleMapsJSON' looks like, perhaps you could post for us.
Assuming your mock resource is well formatted, make sure the file extension is ".json" and was saved with UTF-8 encoding.
If #2 does not work, you should try saving your resource as .txt - I've run in to this before where it needed a plain text resource but expected application/json content type
Be certain that the resource name string you are providing has the same casing as the name of the resource. It is case sensitive.
Are you developing on a namespaced package environment? Try adding the namespace to the resource name if so.
Otherwise, your code looks pretty good at first glance.

How to return the Json value using WCF WebApi

I have create a one sample WCF rest template WebApi in this i have use Entity Framework to getting the data when i run the service for it return the string value it showing the result but at end of the json value add XML code like below how can i solve this.
[{"AccountId":1,
"AccountNumber":"AC001",
"AccountType":"Restaurant",
"BusinessName"‌​:"Red SpiceInc",
"PrimaryContactFirstName":"Varma",
"PrimaryContactLastName":"Bhupatiraju",
"P‌​rimaryContactPhone":"(949) 374 2114",
"PrimaryContactEmail":"redspice#mybusinessapp.com",
"AccountGuid":"918D3E66-CEFE-11E0-8C2F-0C0B4824019B",
"EntityState":1,"EntityKey":null}]
<?xml version="1.0" encoding="utf-8"?><Stream p1:nil="true" xmlns:p1="w3.org/2001/XMLSchema-instance"; />
My code
[WebGet(UriTemplate = "GetSetting({LocationGuid},{settingName})", ResponseFormat = WebMessageFormat.Json)]
public Stream GetSetting(string LocationGuid, string settingName)
{
string str = string.Empty;
string strJSON = string.Empty;
dynamic contactResponse = new JsonObject();
List<setting> Result;
Result = new List<setting>();
var Location = from acc in objEntity.locations where acc.LocationGuid == LocationGuid select acc;
if (Location.Count() > 0)
{
var LocationId = (from acc in objEntity.locations where acc.LocationGuid == LocationGuid select acc).First();
var objSetting = from cat in objEntity.settings where cat.SettingName == settingName & cat.LocationId == LocationId.LocationId select cat;
setting SettingList = new setting();
foreach (setting setting in objSetting)
{
setting Settinglist = new setting();
Settinglist.SettingId = setting.SettingId;
Settinglist.AccountId = setting.AccountId;
Settinglist.LocationId = setting.LocationId;
Settinglist.SettingName = setting.SettingName;
Settinglist.SettingValue = setting.SettingValue;
Settinglist.FieldType = setting.FieldType;
Result.Add(Settinglist);
}
JavaScriptSerializer js = new JavaScriptSerializer();
strJSON = js.Serialize(Result);
WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
return new MemoryStream(Encoding.UTF8.GetBytes(strJSON));
}
else
{
return null;
}
}
Please help me solve this problem.
I believe return the POCO is enough
the method signature is
public List<setting> GetSetting(string, string)
WCF Web API will serialize the object into json or xml for you as per your request header (accept: application/json, or application/xml)
As was mentioned in misaxi's response, the WebApi WebGet operations generally do not need to concern themselves with how the response is returned. The responsibility of the web operation is to simply return the data. E.g....
[WebGet(UriTemplate = "GetSetting({LocationGuid},{settingName})"]
public List<setting> GetSetting(string LocationGuid, string settingName)
{
List<setting> Result = null;
var Location = from acc in objEntity.locations where acc.LocationGuid == LocationGuid select acc;
if (Location.Count() > 0)
{
Result = new List<setting>();
....
foreach (setting setting in objSetting)
{
....
Result.Add(Settinglist);
}
}
return Result;
}
The fact that the client receives XML, JSON, JSONP, HTML, etc is up to the client (in conjunction with server-side support). The client's request header will include something that looks like Accept: application/json or Accept: application/xml or whatever representation that the client is after. WebApi comes pre-loaded with a few standard formats, XML (the default) and Json. You can introduce more formats as needed to accept a more diverse set of Accept: .... headers, but the conversion from your data to these requested formats are generally out-of-scope for your web operation and rely on the formatters you set up (or were set up by default) when your service is initialized.
Likewise, WebPost operations generally do not care if the body of the request was XML or JSON, by the time the operation is invoked, formatters have already translated that payload into your method's parameters.