XPages REST and date format - rest

I have an XPages page which contains the REST service component. I'm using the "documentJsonService".
Awesome component and everything else is working fine, but I'm having issues with the date formats and don't know what to do.
The Notes Document where I'm reading the data from, contains a DateTime item having a proper date e.g. 01.09.2014 (finnish format: dd.MM.yyyy). The REST component returns the date in "2014-09-01" (string). This is fine. However when I do a HTTP POST to the server with the same exact data, Domino changes the "2014-09-01" string date into 09.01.2014 Notes Date time item.
Don't know any more what to do. Why Domino gives date in format A and when I give it back in same format, something strange happens.
This same happens on Linux and Windows environments.
Domino version is 9.0.1.
Thanks already. I'm more or less lost with this "feature" :)

I would say: broken as designed. To my knowledge the JSON format returned is always in the form yyyy-mm-dd, while the format expected when posting depends on the browser locale. You would need to "hack around it".
I'm not a big fan of the ready baked JSON services, I'd rather roll my own, where I can be very specific with the formats and (more importantly) add validation before I write data back. You can find a sample on my blog
Basically you implement a bean like this:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ibm.domino.services.ServiceException;
import com.ibm.domino.services.rest.RestServiceEngine;
import com.ibm.xsp.extlib.component.rest.CustomService;
import com.ibm.xsp.extlib.component.rest.CustomServiceBean;
public class CustomSearchHelper extends CustomServiceBean {
#Override
public void renderService(CustomService service, RestServiceEngine engine) throws ServiceException {
HttpServletRequest request = engine.getHttpRequest();
HttpServletResponse response = engine.getHttpResponse();
response.setHeader("Content-Type", "application/json; charset=UTF-8");
// Your code goes here!
}
}
you need to check in the request what method GET or POST was used, but then it is easy to continue. While you are on it: the OpenNTF Domino API makes your life much easier.

Related

Why is this particular website auto-formatting dates when parsed programatically?

I am trying to get a list of certain links from a website using Jsoup 1.10.1. The following is a snippet which I've isolated from the rest of my code in an attempt to diagnose the problem:
public static void main(String[] args) throws IOException {
URL link = new URL("https://www.ncdc.noaa.gov/gibbs/availability/1979-01-01");
Document doc = Jsoup.parse(link, 600);
Elements links = doc.select(".availableChannels > a");
System.out.println(links.get(0));
}
In theory this should print out the contents of the first link under the .availableChannelsclass on the provided URL, which should be IR .
However, Jsoup instead auto-formats the yyyy-mm-dd date that appears within the a href, and as a result the code snippet prints out IR , which is undesired.
How do I stop Jsoup from automatically formatting dates?
UPDATE
I decided to write a similar program in Python 2.7 to see what would happen if I read from that particular page (https://www.ncdc.noaa.gov/gibbs/availability/1979-01-01). Turns out that the yyyy-mm-dd that appears in IR is still getting formatted into IR when I open and print the page's source using python.
import urllib
link = "https://www.ncdc.noaa.gov/gibbs/availability/1979-01-01";
f = urllib.urlopen(link);
myfile = f.read();
print myfile;
I guess the question becomes: Why is this particular website automatically formatting dates when accessed through non-standard web browser means? I've changed the question accordingly to reflect this.
It's because you need to set the Accept-Language header on the HTTP request.
The Accept-Language request HTTP header advertises which languages the
client is able to understand, and which locale variant is preferred.
Using content negotiation, the server then selects one of the
proposals, uses it and informs the client of its choice with the
Content-Language response header. (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language)
So it seems like if you don't set the header, the server hosting the website returns a variant that doesn't use your preferred local time settings that you see in your browser.
public static void main(String[] args) throws IOException {
URL link = new URL("https://www.ncdc.noaa.gov/gibbs/availability/1979-01-01");
Document doc = Jsoup.connect(link.toString())
.header("Accept-Language", "en-GB").get();
Elements links = doc.select(".availableChannels > a");
System.out.println(links.get(0));
}
Output:
IR

SmartGWT not able to parse data in the DataSource.transformResponse() method

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!

Why can't I get HAL support to work in grails 2.3.8?

I am following the directions in the docs, here:
http://grails.org/doc/2.3.8/guide/webServices.html#hypermedia
Why won't grails produce HAL-formatted output, as shown in the documentation?
I have a domain object which I have mapped with the #Resource annotation:
#Resource(uri='/documentCatalogs', formats = ['json', 'xml'], readOnly = true)
class DocumentCatalog {
String entityType
String actionCode
...
}
...and in my conf/spring/resources.groovy, I have configured the HAL JSON renderer beans:
import com.cscinfo.platform.api.formslibrary.DocumentCatalog
import grails.rest.render.hal.HalJsonCollectionRenderer
import grails.rest.render.hal.HalJsonRenderer
// Place your Spring DSL code here
beans = {
halDocumentCatalogRenderer(HalJsonRenderer, DocumentCatalog)
halDocumentCatalogCollectionRenderer(HalJsonCollectionRenderer, DocumentCatalog)
}
Using the debugger, I confirmed that the initialize() method on HalJsonRenderer is called and that it is constructed with the correct targetType.
I send a rest call using Postman:
http://localhost:8080/formslibrary/documentCatalogs/3
Accept application/hal+json
And I get back a response which is regular JSON and doesn't contain any links:
{
"class": "com.cscinfo.platform.api.formslibrary.DocumentCatalog",
"id": 3,
"actionCode": "WITH",
"entityType": "LLP",
...
}
What did I miss? Is there some plugin or configuration setting I have to enable for this behavior? Is there some additional mapping property somewhere that's not documented?
Figured it out! There are multiple aspects of the fix...
I had to add "hal" as one of the listed formats in the #Resource annotation:
#Resource(uri='/documentCatalogs', formats = ['json', 'xml', 'hal'])
Some hunting around in the debugger revealed that Grails will blithely ignore the Accept header, based on the UserAgent string that is sent from the client. (In my case, since I'm using Postman, it was the Google Chrome UA string.)
One workaround for the Accept header issue is to add ".hal" to the end of the URL:
http://localhost:8080/formslibrary/documentCatalogs/3.hal
This isn't a very good solution IMO, since the HAL URLs generated by the renderer don't end in ".hal" by default.
A better solution is to fix Grails' handling of the accept header by updating the config. In Config.groovy, you will see a line that says:
grails.mime.disable.accept.header.userAgents = ['Gecko', 'WebKit', 'Presto', 'Trident']
Change it to:
grails.mime.disable.accept.header.userAgents = ['None']
This forces Grails to honor the Accept header, regardless of the user agent.
Hope this helps somebody else who's hitting the same issue.
P.S. It's really helpful to put a breakpoint in the ResponseMimeTypesApi#getMimeTypesFormatAware(...) method.

JSF restful output non-english characters

I have a restful class to send JSON string to POST request. Data are store in DB with UTF-8 format. But the non-english characters always display as '??????', it all works fine if I get records form #Model.
Here is the code snap of rest (Using simple JSON to encoding JSON string):
#POST
#Path("/holidaylist")
#Produces(MediaType.APPLICATION_JSON)
public String getHoliday(){
List list = new LinkedList();
// Get list of holidays
List<Holiday> holidays = em.createQuery("SELECT holiday FROM Holiday holiday").getResultList();
Map event;
for(Holiday holiday : holidays){
System.out.println("======== Holiday nameļ¼š " + holiday.getHolidayName());
event = new HashMap();
event.put("id", holiday.getHolidayId());
event.put("title", holiday.getHolidayName());
event.put("start", holiday.getStartDate().toString());
list.add(event);
}
return JSONValue.toJSONString(list);
}
Thanks in advanced.
You need to make sure that you properly handle data encoding all along, starting from the DB and to the front-end. I'm not totally familiar with the SimpleJSON api, but are sure the toJSONString uses UTF-8 encoding? Also, make sure your page where you render t
Solved by using JAXB implementation. Seems simple JSON encoding issue.
Thanks everyone.

Play Framework 2.1 Scala - form binding for date

I want to create a form binding in Play Framework 2.1, for a form that has date/time fields. Is there any standard verifier for date/time input? I understand that the page form should also send the date/time in a particular format. Does anyone know of any prefab solution for that? Or can describe how to implement one by myself?
Play 2.1 has built-in support for Twitter Bootstrap; if you take that route then Bootstrap Date Picker is a good call for client-side (i.e. ensuring date is sent as yyyy-mm-dd or other valid date format).
With the client taken care of, server-side Play 2.1 supports JodaTime, so you can bind the post'd form date like so:
object FooForm {
import play.api.data.{Form, Forms}, Forms._
val mapper = mapping(
'fooDate-> jodaDate("yyyy-MM-dd")
)(Foo.apply)(Foo.unapply)
val form = Form( mapper )
}
Like #virtualeyes said, from the client side, DatePicker will generate the correct data format (dd/MM/yyyy by default).
However, Play Framework then needs to unmarshall the Date format correctly using bindFronRequest (client -> server).
Also Play needs to generate the correct Date string representation when generating the Form, which will be sent to the view (controller -> view). In java this can be done providing a DataBinder.
An example of this can be found in that issue opened on GitHub