Gson Syntax Exception causing Retrofit Error - json

I am in the process of connecting to a custom RESTful API using Retrofit. I have testing communicating with the device/API via Curl and with some test Java code running on a non-Android system (mac os x). The curl and java commands return the expected response.
However, using retrofit, I am unsure if I am using an inadequate configuration in my RestAdapter (i.e. RestAdapter.Builder()) to talk to this device.
The error I am getting appears to be that the entire json contents is not returned and only the first 47 bytes or so. I expect this is a behavior of the device I'm talking to, and am curious if this means I need to implement an Asynchronous callback as described in the Retrofit API docs. Before I do this I wanted to get feedback from some who have more experience with Retrofit.
The error is as follows (sanitized for public consumption):
12-06 08:50:52.962 28267-1735/com.mycompany.project D/Retrofit? [ 12-06 08:50:52.972 28267: 1735 D/Retrofit ]
{"OBJECT1":{"#Version":1,"OBJECTARRAY1":[
12-06 08:50:52.972 28267-1735/com.mycompany.project D/Retrofit? <--- END HTTP (46-byte body)
12-06 08:50:52.982 28267-1735/com.mycompany.project W/System.err retrofit.RetrofitError: retrofit.converter.ConversionException: com.google.gson.JsonSyntaxException: java.io.EOFException: End of input at line 1 column 47
I am setting up the RestAdapter as such:
RestAdapter restAdapter = new RestAdapter.Builder()
.setServer(serverUrl)
.setClient(new OkClient(RestUtils.getHttpClient(3000, 3000, username, password)))
.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade requestFacade) {
requestFacade.addHeader("Accept", "application/json");
requestFacade.addHeader("Client-Id", "12345");
}
})
.setLogLevel(RestAdapter.LogLevel.FULL)
.build();
service = restAdapter.create(OBJECT1.class);
Any insight into this problem would be greatly appreciated. I understand this error is related to the java.io.EOFException, but have been unable to verify the contents I am getting returned from the device, except for the output shown above in the error. I am heavily leaning towards the async vs. sync being the issue, but am open to any recommendations.
Cheers!

Related

API Response returns Mappable Object in iOS but Json on Android

I'm a newbie on mobile development and React-Native, this might come across as a very mundane thing to some of you, but I'm making an Api call and then mapping the results to create the same component but with different data.
This works fine on Iphone but on Android it does not.
The response from the req is an Object for both devices but on Android, it seems to be a json object that I simply cannot map with or use on a Flatlist.
I've tried JSON.parse to get the json object to a js object but it simply doesn't, like it. It throws out an unexpected token error.
I've attached a log for the Android object first and the same object for iPhone (Already mappable and a JS object).
Can someone tell me why this happens? I'd very much appreciate it!
enter image description here
____________________ After Changing to Fetch _______________________
Hey, I changed from Axios to fetch and now I get an unhandled promise warning saying 'Unhandled promise rejection: SyntaxError: JSON Parse error: Unrecognized token '' '.
Don't think I'm doing anything wrong here...
Well ... your response-object gets truncated due to memory issues on your real-device ... most likely your response object is kinda large ...
And that's just the way axios fetch response-data ... through chunks, you just get a slice of the response...
I came across this issue before ... and the solution was to switch to fetch
Edit
try {
const rawResponse = await fetch(...);
const text = await rawResponse.text();
console.log(text);
const parsedRes = JSON.parse(text);
console.log('parsedRes', parsedRes);
} catch(error) {
console.log('fetch error', error);
}

Handling exceptions in Spring 5 Reactive kotlin

I've been hitting the wall and haven't came up with any reasonable solution, so maybe someone will give it a try. I wrote simple service integrating with github, and having hard time to understand how should I work with exceptions in reactive word properly. Once I got expected 404 status error from Github I would like to throw my custom exception and present it to the client instead of valid response, I'm checking code statuses of response from github and the only thing I receive on my site is:
2018-06-26 21:45:08.286 WARN 8336 --- [ctor-http-nio-2]
.a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request
[GET http://localhost:8080/repositories/sh1nen/no-exist]: Response
status 404
Here is my simple method responsible for making requests and handling error codes appropriately.
fun findSpecificOwnerRepository(owner: String, repositoryName: String) = webClient
.get()
.uri("/repos/$owner/$repositoryName")
.retrieve()
.onStatus({ httpStatus -> HttpStatus.NOT_FOUND == httpStatus }, { Mono.error(RepositoryNotFoundException(reason = "Repository $repositoryName not found.")) })
.onStatus({ httpStatus -> HttpStatus.SERVICE_UNAVAILABLE == httpStatus }, { Mono.error(RepositoryNotFoundException(reason = "Service unavailable.")) })
.bodyToMono(GithubRepositoryResponse::class.java)
Here is my custom exception which basically represents no resources on my site to represent:
internal class RepositoryNotFoundException(
status: HttpStatus = HttpStatus.NOT_FOUND,
reason: String? = null,
throwable: Throwable? = null) : ResponseStatusException(status, reason, throwable)
And the endpoint itself which I'm hitting to get the response:
#GetMapping("{owner}/{repositoryName}")
fun findSpecificOwnerRepository(#PathVariable owner: String, #PathVariable repositoryName: String) = githubClient
.findSpecificOwnerRepository(owner, repositoryName)
I would like to get 404 with a message which is hardcoded. Do I need any special #ExceptionHandler in controller to handle my custom exception ?
Is there any chance of implementing situation when for example github is not able to keep up with requests I am serving and throw in that case also some exception? How could it be implemented?
I'm not sure if you are actually missing anything for point 1), as the exception you extend should naturally result in 404 to your clients, if I recall correctly.
About point 2, it all depends on how your source handles rate limiting. In the case of GitHub, it will return a 403 once you hit rate limits, but you can be extra careful and check the custom headers as well. See https://developer.github.com/v3/#rate-limiting
So the simplest way it would be implemented is with onStatus. Alternatively, you can inspect the whole response and act accordingly by using exchange instead of retrieve, and flatMaping on the resulting Mono (that emits the whole server response).

Setting Http Status Code and customized status message and returning JSON output using Jersey in RESTful Service

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 :)

Bitcoind JSON-RPC : Java Jersey Client : Unexpected end of file from server Error

I am very new to bitcoin and this is my first experiment with bitcoind.
We have been trying to develop an Java based application on BTC using bitcoind (using testnet). We are using simple HTTP Post using Jersey client with basic authentication like given below. We already have jersey client as part of project dependencies. We are running on Mac OS. The bitcoind and java client are hosted in the same system.
Client client = Client.create();
String url = "http://"+username+':'+password+"#localhost:18333";
//String url = "http://localhost:18333";
System.out.println("URL is : "+url);
WebResource webResource = client.resource(url);
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication (username, password.toCharArray());
}
});
String input = "{\"method\":\"getblockcount\",\"params\":[],\"id\":\"1\"}";
ClientResponse response = webResource.type("application/json").post(ClientResponse.class, input);
When we execute this, we are getting
Caused by: java.net.SocketException: Unexpected end of file from server
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:772)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:769)
From the exception what I understand is, there are some server side errors but i am not able to see errors in the log files. The degug.log does not give any details.
The entries in the bitcoin.conf file is as follows:
rpcuser=bitcoinrpc
rpcpassword=5UKQTzWTf7EEJnkShZhr9tbjpDVNmLMgQkFfWsnZhLey
testnet=1
server=1
Also I tried integrating with bitcoind using json-rpc client as well which resulted in the same error.
Really appreciate any help in resolving this error. Thank you in advance. Let me know if you need any further details.
Regards,
Manjunath
====== EDIT ======
When I inspect the request and response, its giving "Remote server closed the connection before sending response header" error as part of HTTP failure scenario. Following is the request data content :
URL : http://192.168.2.111:18333/
Request Data:
{
"method": "getblockcount",
"params": [],
"id": "1"
}
Please help me in understanding where the mistake is.
================ EDIT =================
Added below entries to bitcoin.conf to allow connections from client. But still facing the same error:
rpcallowip=192.168.2.111
rpcallowip=127.0.0.1
Regards,
Manjunath
After all tweaking, I am able to get it working properly. For the benefit of others, here is the Java Code for making JSON-RPC calls to bitcoind (Using Jersey Client):
bitcoin.conf entries :
rpcuser=bitcoinrpc
rpcpassword=5UKQTzWTf7EEJnkShZhr9tbjpDVNmLMgQkFfWsnZhLey
testnet=1
server=1
#txindex=1
rpcallowip=192.168.2.*
rpcallowip=127.0.0.1
rpcport=8999
#rpctimeout=60000
Make sure you change the port number and dont forget to provide rpcallowip entry pointing to respective IP address.
Client Code:
DefaultClientConfig config = new DefaultClientConfig();
config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
Boolean.TRUE);
Client client = Client.create(config);
client.addFilter(new HTTPBasicAuthFilter(username, password));
WebResource webResource = client.resource(url);
String input = "{\"id\":\"jsonrpc\",\"method\":\"listaccounts\",\"params\":[]}";
ClientResponse response = webResource.accept("application/json").type("application/json")
.post(ClientResponse.class, input);
Thats it. Your good to start with bitcoind integration.
Regards,
Manjunath

PUT requests with Custom Ember-Data REST Adapter

I'm using Ember-Data 1.0.0.Beta-9 and Ember 1.7 to consume a REST API via DreamFactory's REST Platform. (http://www.dreamfactory.com).
I've had to extend the RESTAdapter in order to use DF and I've been able to implement GET and POST requests with no problems. I am now trying to implement model.save() (PUT) requests and am having a serious hiccup.
Calling model.save() sends the PUT request with the correct data to my API endpoint and I get a 200 OK response with a JSON response of { "id": "1" } which is what is supposed to happen. However when I try to access the updated record all of the properties are empty except for ID and the record on the server is not updated. I can take the same JSON string passed in the request, paste it into the DreamFactory Swagger API Docs and it works no problem - response is good and the record is updated on the DB.
I've created a JSBin to show all of the code at http://emberjs.jsbin.com/nagoga/1/edit
Unfortunately I can't have a live example as the servers in question are locked down to only accept requests from our company's public IP range.
DreamFactory provides a live demo of the API in question at
https://dsp-sandman1.cloud.dreamfactory.com/swagger/#!/db/replaceRecordsByIds
OK in the end I discovered that you can customize the DreamFactory response by adding a ?fields=* param to the end of the PUT request. I monkey-patched that into my updateRecord method using the following:
updateRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record);
var adapter = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
// hack to make DSP send back the full object
adapter.ajax(adapter.buildURL(type.typeKey) + '?fields=*', "PUT", { data: data }).then(function(json){
// if the request is a success we'll return the same data we passed in
resolve(json);
}, function(reason){
reject(reason.responseJSON);
});
});
}
And poof we haz updates!
DreamFactory has support for tacking several params onto the end of the requests to fully customize the response - at some point I will look to implement this correctly but for the time being I can move forward with my project. Yay!
EmberData is interpreting the response from the server as an empty object with an id of "1" an no other properties in it. You need to return the entire new object back from the server with the changes reflected.