Facing Exception of MessageBodyWriter while sending JSONObject to Rest web service - jersey-client

I am newbie to web service. Due to requirement I have to send a file[most probably in txt format] to server through REST web service.
I am getting the exception like below.
MessageBodyWriter not found for media type=application/json, type=class gvjava.org.json.JSONObject, genericType=class gvjava.org.json.JSONObject.
Here is my web service method.
#Path("{c}")
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String convert(#PathParam("c") JSONObject object) throws JSONException {
String result = "";
return "<ctofservice>" + "<ctofoutput>" + result + "</ctofoutput>" + "</ctofservice>";
}
Now client code is like below
JSONObject data_file = new JSONObject();
data_file.put("file_name", uploadFile.getName());
data_file.put("description", "Something about my file....");
data_file.put("file", uploadFile);
Client client = ClientBuilder.newClient();
webTarget = client.target(uploadURL).path("ctofservice").path("convert");
Response value = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(data_file,MediaType.APPLICATION_JSON_TYPE),
Response.class);
Please help me with this.
Thanks in advance.
------------------------------------------------------------------------
As suggested by peeskillet in the answer below, I tried to send file through multipart. Still I am facing exception of no octet stream found.
Below is my rest api
#Path("{c}")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response convert(#FormDataParam("file") FormDataContentDisposition file) {
String result = "";
Some operation with attached parameter ...
return Response.status(200).entity(result).build();
}
Here is my test client
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file",
uploadFile,MediaType.APPLICATION_OCTET_STREAM_TYPE);
multiPart.bodyPart(fileDataBodyPart);
Client client = Client.create();
WebResource webResource = client
.resource(uploadURL).path("ctofservice");
ClientResponse response = webResource.accept("application/json")
.post(ClientResponse.class,multiPart);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
And I am getting the exception below
I am not able to understand why I need to send data as MediaType.APPLICATION_OCTET_STREAM_TYPE ? As I have used multipart as media type before ...
I appreciate your help..

Without needing to configuring anything else, the easiest way to get around this is to just use a String instead of the actual JSONObject (i.e. just passing toString())
.post(Entity.json(data_file.toString()))
The problem with using JSONObject is that there is no provider that knows how to handle the conversion. You will have the same problem on the server side, where there is no provider to handle the conversion to JSONObject. So you will need to just do
#POST
public Response post(String json) {
JSONObject jsonObject = new JSONObject(json);
}
If you really want to be able to just use JSONObject without needing to use a String, then you should check out this post.
As an aside, this is not valid JSON (it's XML)
"<ctofservice>" + "<ctofoutput>" + result + "</ctofoutput>" + "</ctofservice>"
but you are saying that the endpoint returns JSON

Related

Can I can return json list from HttpClientResponse

I am trying to connect with our server using dart and flutter. I get an error in certificate server, I get the code and I get response exactly, but the problem is the response keeps coming back as a string. I want it as a list to loop through it.
HttpClient client = new HttpClient();
client.badCertificateCallback =((X509Certificate cert, String host, int port) => true);
String url ='https://xxx';
//Map map = { "email" : "email" , "password" : "password"};
HttpClientRequest request = await client.getUrl(Uri.parse(url));
//request.headers.set('content-type', 'application/json');
//request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply);
I have simple code to get a JSON response as a list. The problem is our server is using https and nginx to take all request to the correct port. Previous code worked but I need to respond with a list.
simple code is :
String apiURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(apiURL);
return json.decode(response.body);
You won't get a list. You would get flat json which you would need to process. Processing can be done using simple script using powershell.

MVC accessing external Web API using login credentials

In need of some help accessing an external Web API passing along credentials in order to access the methods available. I have included the code below that i use in order to attempt to access the Web API. However, i receive the following error every time i attempt to access it:
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
What am i missing or what am i doing wrong? I have been circling around this for a couple days and have tried a couple different techniques but continue to get the same error. Here is one technique that i used.
private static async Task<string> GetAPIToken(string userName, string password, string apiBaseUri)
{
try
{
using (var client = new HttpClient())
{
//setup client
client.BaseAddress = new Uri(apiBaseUri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//setup login data
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("username",userName),
new KeyValuePair<string,string>("password",password),
});
//send request
HttpResponseMessage responseMessage = await client.PostAsync("Token", formContent);
//get access token from response body
var responseJson = await responseMessage.Content.ReadAsStringAsync();
var jobject = JObject.Parse(responseJson);
return jobject.GetValue("access_token").ToString();
}
}
catch (Exception ex)
{
return null;
}
}
Any help would be greatly appreciated.
Thanks
There is a little bit of a difference when using HTTPS vs HTTP. This question should give you the information you need to fix your problem.
Make Https call using HttpClient

Google Machine Learning API Issue

I'm trying to use the Google Machine Learning API and I'm facing two problems.
In the API explorer I put the correct information and I get a response error:
Code 200
"error": "Missing \"instances\" field in request body: {\n \"httpBody\": \n
{\n \"data\": \"\\"instances\\" : \\"teste\\"\",\n
\"contentType\": \"application/json\"\n }\n}"
The request find my model (if I change the value in field name I get another error) but don't understand my json. That's the json:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
When I do the predict on the command line using gcloud, I get no errors and everything seems ok. The Json that I was create for gcloud is a little bit different:
{"key":"0", "image_bytes": {"b64": "mybase64"} }
I already tryied that one in the API explorer and no success.
So, I decided to use the .Net Api to try the predict and I get other situation: The Response is Empty (???).
Here is my code:
'get the service credential that I created
Dim credential = Await GetCredential()
Dim myService As New CloudMachineLearningEngineService(New BaseClientService.Initializer() With {
.ApplicationName = "my Project Name (Is That It???)",
.ApiKey = "my API Key",
.HttpClientInitializer = credential
})
Dim myBase64 As String = GetBase64("my image path to convert into a base64 String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
'If I change the model name I get error
Dim myPredictRequest = myService.Projects.Predict(myRequest, "projects/myProject/models/myModel/versions/v1")
myPredictRequest.AccessToken = credential.Token.AccessToken
myPredictRequest.OauthToken = credential.Token.AccessToken
myPredictRequest.Key = "my API Key
'Execute the request
Dim myResponse = myPredictRequest.Execute()
'at this point, myResponse is Empty (myResponse.ContentType Is Nothing, myResponse.Data Is Nothing And myResponse.ETag Is Nothing)
If I change the model name I get a error informing that my model was not found, so my credentials are right.
I don't know what I'm doing wrong. Someboby can help with any of this issues?
Thanks!
UPDATE: --------------------------
I changed this Execute Command:
Dim myResponse = myPredictRequest.Execute()
To This One:
Dim s = StreamToString(myPredictRequest.ExecuteAsStream())
and Now I can get the same error with .Net API and google developers interface (Missing instances field...).
So If someboby just Know what is wrong with my Json request, It will help a lot.
The JSON you put in the API explorer is indeed correct (assuming, of course, your model has inputs key and image_bytes). This appears to be a bug with the explorer I will report.
The reason you are getting the error you are in the .NET code is because you are using an .HttpBody field. This code:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
Will produce a JSON request that looks like this:
{
"httpBody": {
"data": "{\"instances\" : [{\"key\":\"0\", \"image_bytes\": {\"b64\": \"mybase64\"} }]}",
"contentType": "application\/json"
}
}
When what you really need is:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
Hence the error message you see.
I don't know how to generate the correct response using the .NET library; based on the Python example in the docs, I would guess:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myPredictRequest = myService.Projects.Predict(myJsonRequest, "projects/myProject/models/myModel/versions/v1")
But I don't have a good way of testing that. For reference, the Python equivalent is:
response = service.projects().predict(
name=name,
body=myJsonRequest
).execute()
I solved the problem with .Net API.
I created two new classes Inherits the Google API's classes.
Something like that:
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleCloudMlV1PredictRequest
Inherits GoogleCloudMlV1PredictRequest
<JsonProperty("instances")>
Public Property MyHttpBody As List(Of myGoogleApiHttpBody)
End Class
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleApiHttpBody
Inherits GoogleApiHttpBody
<JsonProperty("image_bytes")>
Public Property MyData As image_byte
<JsonProperty("key")>
Public Property key As String
End Class
So, in my original code I change this part:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
For this one:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myRequest = New myGoogleCloudMlV1PredictRequest With {
.MyHttpBody = New List(Of myGoogleApiHttpBody)()
}
Dim item As myGoogleApiHttpBody = New myGoogleApiHttpBody With {
.key = "0",
.MyData = New image_byte With {
.b64 = myBase64
}
}
myRequest.MyHttpBody.Add(item)
And voilá, It's working!
Thanks for everyone!!
Github issue #1068 shows two work-arounds for this problem.
In summary, use service.ModifyRequest to insert the raw JSON content.
Or use service.HttpClient.PostAsync(...) directly.

How to multipart post form data to LinkedIn using OAuth 1 and DotNetOpenAuth?

I'm using the DotNetOpenAuth framework which has been great to get up to speed with consuming data.
I'm using it to talk to LinkedIn and am having trouble figuring out the correct approach to posting/sharing information to the site. Here is the reference I am using - http://developer.linkedin.com/documents/share-api
When I execute the below code I always get the below error responses;
Error occurred while sending a direct message or getting the response.
The remote server returned an error: (400) Bad Request.
I am using Oauth v1.0a.
Here is my code;
try
{
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><share><comment>83% of employers will use social media to hire: 78% LinkedIn, 55% Facebook, 45% Twitter [SF Biz Times] http://bit.ly/cCpeOD</comment>";
xml += "<content><title>Survey: Social networks top hiring tool - San Francisco Business Times</title>";
xml += "<submitted-url>http://sanfrancisco.bizjournals.com/sanfrancisco/stories/2010/06/28/daily34.html</submitted-url>";
xml += "<submitted-image-url>http://images.bizjournals.com/travel/cityscapes/thumbs/sm_sanfrancisco.jpg</submitted-image-url>";
xml += "</content><visibility><code>anyone</code></visibility></share>";
var multiparts = new List<MultipartPostPart>();
MultipartPostPart part = MultipartPostPart.CreateFormPart("body", xml);
part.PartHeaders[HttpRequestHeader.ContentType] = "application/xml";
multiparts.Add(part);
var resourceEndpoint = new MessageReceivingEndpoint("http://api.linkedin.com/v1/people/~/shares", resourceHttpMethod);
HttpWebRequest request = consumer.PrepareAuthorizedRequest(resourceEndpoint, accessToken, multiparts);
request.ServicePoint.Expect100Continue = false;
IncomingWebResponse response = consumer.Channel.WebRequestHandler.GetResponse(request);
this.resultsBox.Text = response.GetResponseReader().ReadToEnd();
}
catch (Exception ex)
{
}
Thanks
Forgot to write back on this, talking to someone from a vintage google newsgroup I got the direction I needed but wanted to verify the solution before posting.
The big thing I was screwing up on was adding the multipart data prior to sending the request data as opposed to constructing the request myself and writing the new content to the stream.
I'm new to using OAuth and REST so I don't know all the ins and outs, suffice to say I've validated this code against both the LinkedIn and Twitter REST APIs.
Here is the new CODE;
try
{
Encoding encoder = Encoding.ASCII;
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
byte[] bytes = encoder.GetBytes(xd.OuterXml.ToString());
var resourceEndpoint = new MessageReceivingEndpoint(ResourceURL, resourceHttpMethod);
HttpWebRequest request = _consumer.PrepareAuthorizedRequest(resourceEndpoint, _manager.AccessToken);
request.ServicePoint.Expect100Continue = false;
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "application/xml";
using (System.IO.Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
IncomingWebResponse response = _consumer.Channel.WebRequestHandler.GetResponse(request);
ret = true;
}
catch (Exception ex)
{
_Logger.Error(OpenLogger.FormatException(ex));
}

EntityClassGenerator : Not generating any output for NorthwindDataService

I am trying to generate the OData Proxy for the service : http://services.odata.org/Northwind/Northwind.svc/$metadata
I am using System.Data.Services.Design.EntityClassGenerator for generating the OData proxy.
When I instantiate the EntityClassGenerator and call GenerateCode the output has no errors. But there is no code in the generated proxy code.
The same code works for my own service. But when I point it to any external service the EntityClassGenerator is not working.
Here is the code :
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(metadataEndpoint);
webRequest.Method = "GET";
webRequest.ContentType = "text/xml;encoding='utf-8";
webRequest.Proxy = (proxy != null) ? proxy : WebRequest.DefaultWebProxy;
using (WebResponse response = webRequest.GetResponse())
{
string xml = string.Empty;
XmlReaderSettings settings = new XmlReaderSettings();
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
xml = reader.ReadToEnd();
using (XmlTextReader sourceReader = new XmlTextReader(reader))
{
using (StringWriter targetWriter = new StringWriter())
{
// Generate the OData End point proxy.
EntityClassGenerator entityGenerator = new EntityClassGenerator(LanguageOption.GenerateCSharpCode);
entityGenerator.OnPropertyGenerated += new EventHandler<PropertyGeneratedEventArgs>(entityGenerator_OnPropertyGenerated);
IList<System.Data.Metadata.Edm.EdmSchemaError> errors = entityGenerator.GenerateCode(sourceReader, targetWriter, namespacename);
entityGenerator.OnPropertyGenerated -= new EventHandler<PropertyGeneratedEventArgs>(entityGenerator_OnPropertyGenerated);
odataProxyCode = targetWriter.ToString();
}
}
}
}
I found the code in the question to be a useful starting point for doing exactly what the OP was asking. So even though the OP doesn't accept answers, I'll describe the changes I made to get it to work in case it is useful to someone else.
Removed the xml = reader.ReadToEnd(); call. I assume that was for debugging purposes to look at the response from the web request, but it had the result of "emptying" the reader object of the response. That meant that there was nothing left in the reader for the GenerateCode call.
The important one: Changed the use of EntityClassGenerator to System.Data.Services.Design.EntityClassGenerator. In the code below, I included the entire name space for clarity and specificity. Based on the code in the question, it appears the OP was probably using System.Data.Entity.Design.EntityClassGenerator. I used .NET Reflector to examine datasvcutil.exe, which is a command-line utility that can generate the proxy classes. I saw that it referenced the generator in that other name space.
For figuring out the problems, I dumped the errors from the GenerateCode call. One could examine them in the debugger, but some kind of automated checking of them would be needed regardless.
Here is what I ended up with:
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.
Create("http://services.odata.org/Northwind/Northwind.svc/$metadata");
webRequest.Method = "GET";
webRequest.ContentType = "text/xml;encoding='utf-8";
webRequest.Proxy = WebRequest.DefaultWebProxy;
using (WebResponse response = webRequest.GetResponse())
{
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
using (XmlTextReader sourceReader = new XmlTextReader(reader))
{
using (StringWriter targetWriter = new StringWriter())
{
// Generate the OData End point proxy.
System.Data.Services.Design.EntityClassGenerator entityGenerator =
new System.Data.Services.Design.EntityClassGenerator(
System.Data.Services.Design.LanguageOption.GenerateCSharpCode);
IList<System.Data.Metadata.Edm.EdmSchemaError> errors =
entityGenerator.GenerateCode(sourceReader, targetWriter,
"My.Model.Entities");
foreach (System.Data.Metadata.Edm.EdmSchemaError error in errors)
Console.WriteLine("{0}: {1}", error.Severity.ToString(), error.Message);
string odataProxyCode = targetWriter.ToString();
}
}
}
}

Resources