Good morning all,
I am following this json post to server tutorial, , which is so far working very well, until I hit an issue saving the post to a c# service stack web service.
When I debug the json = jsonObject.toString(); it returns the following valid json.
{"name":"Test Name","country":"Test Country","twitter":"Test Twitter"}
As a general test, my web service looks like the following.
public object Any(String jsonString)
{
return jsonString;
}
But the response that I get back strips the " out of the string.
{name:Test Name,country:Test Country,twitter:Test Twitter}
With my limited understand of JAVA currently, I am guessing that the tutorial is correct and works fine, but the c# method just will not accept the json string correctly?
Thank you
You should only use Request DTO's as the argument for ServiceStack Services (i.e. never Strings), e.g:
public class MyRequest
{
public string Name { get; set ;}
public string Country { get; set ;}
public string Twitter { get; set ;}
}
public object Any(MyRequest request)
{
return request;
}
Returning a POCO enables ServiceStack to provide automatic Content Negotiation for your Response DTO's.
But returning a raw string in a ServiceStack Service gets written as-is, i.e. ServiceStack doesn't apply any further processing to string responses.
Java Add ServiceStack Reference for Android
If you're looking to invoke ServiceStack Services from Android you should consider Java Add ServiceStack Reference which enables a typed end-to-end API for consuming ServiceStack Services from Java/Android.
Related
My goal is to build a set of REST apis using aws api gateway, back with java Lambda functions and DynamoDB. The payload of the requests and responses is json. I want to avoid tedious field level mapping code between json and java and between java and dynamodb so am trying to use gson to map json to java objects the enhance dynamodb client so I can use java pojos as inputs and outputs of dynamodb queries. This all works fine when testing the functions stand alone.
The issue I am having is passing json between the Gateway and Lambda when trying to integrate gateway apis to the functions. I've tried the two interfaces of Lambda functions, RequestHandler and RequestStreamHandler. I can each of these to do half of what I need, but with RequestHander I have an get runtime errors when returning the response body as json, with RequestStreamHandler I can successfully set the response body as json, but I have problems receiving the request body as json.
It seems that something in the aws gateway framework is converting the body json into an escaped string and then another part of the framework is trying to convert the escaped string into json and failing.
What I am trying to do would seem the most basic REST api use case for aws gateway and Lambda, but I can't find any code examples in aws documentation beyond the trivial "hello world" type. Aws documentation seems pretty thin too, so has anyone out there been successfully in building REST apis with json payloads using aws gateway and Lambda who could share the secret of success?
Here's a bit of background as to what I've tried:
API Gateway:
I've created gateway apis using Lambda proxy integration to my Lambda functions. I've not specified any models to validate the input. I've just taken the default settings. I am passing a json object as the body of my HTTP requests to test the apis.
Lambda Functions
Coded in java using V2 of the SDK.
RequestHandler function - I have created a class the implements the RequestHandler interface specifying the input parameter as a HashMap and output as String. I have successfully got the body of the HTTP request from the hashmap and used Gson to convert the body to my Java pojo. All good.
However I fail trying to include json as the body of the response. I've used both Gson and org.json to construct my http response and include json as the body. I can unit test the function successfully, but when integrated with my gateway api I get an error in the gateway (not that the response has been escaped):
Tue Jan 12 11:12:23 UTC 2021 : Endpoint response body before transformations: "{"body":{"message":"hello world"},"isBase64encoded":false,"statusCode":200}"
Tue Jan 12 11:06:59 UTC 2021 : Execution failed due to configuration error: Malformed Lambda proxy response
RequestStreamHandler
The signature of the handleRequest method is:
public void handleRequest(InputStream input, OutputStream output, Context context)
In this case, I can successfully create a json response using gson and write it to the output stream and the api gateway is fine with it.
However I have a problem with the input. I have tried to use gson to parse the input stream and extract the body. This is fine, but the body is not json, it is an escaped json string, for example:
"{\r\n "id": "10",\r\n "title": "Ski trips",\r\n "owner": "captain",\r\n "locations": \r\n [\r\n {"latitude": 55, "longitude":-2 }\r\n ]\r\n}"
I can't use Gson to parse this nor use Gson to convert it to a pojo. If I try then I get runtime exceptions. To get round this I have used org.apache.commons.text.StringEscapeUtils to remove the escape characters and then removed the leading and trailing quotes round the string. I can then use Gson to convert the resultant string to my pojo class. This is tedious in the extreme.
I've tried changing the classes used for the inputs and outputs of the handleRequest methods, for example to return a JsonObject to see if that changed what I receive but to no avail. If the body contains just a string rather than json, then there is no problem. So just returning "hello world" as the body is fine as per the examples I've found.
I must be missing something, possible in the definition of the gateway api or in the types of the input and output parameters of the Lambda functions but without documentation it really is just wandering around in the dark. Hey all I want to do is to take a json object from the body of a rest request and write it as a json document to a nosql database, getting tripped up by conversion and mapping is really frustrating.
Thanks to anyone who can help me.
Lets say this is our Hander class with ApiGatewayRequest and ApiGatewayProxyResponse are request and response class names.
public class MyHandler implements RequestHandler<ApiGatewayRequest, ApiGatewayProxyResponse> {
#Override
public ApiGatewayProxyResponse handleRequest(ApiGatewayRequest request, Context context) {
}
}
Request Class
public class ApiGatewayRequest {
private String body;
private Map<String, String> headers;
private Map<String, String> queryStringParameters;
private Map<String, String> pathParameters;
private boolean isBase64Encoded;
}
Response Class
public class ApiGatewayProxyResponse {
private int statusCode;
private Map<String, String> headers;
private String body;
}
Json string should be sent in body with com.fasterxml.jackson.databind.ObjectMapper something like
String body = new ObjectMapper().writeValueAsString(ouputObject)
necessary headers ex: Access-Control-Allow-Credentials, Access-Control-Allow-Origin or Content-Type
I have solved my own problem. In aws gateway I had chosen my api to be of type Rest, which seemed the obvious choice for creating Rest services accessed over HTTP. I created a new api of type Http to integrate with the same Lambda function and to cut a long story short that solved the problem. The body of my post request as passed to the Lambda function is not escaped and can be process as json, and likewise the body in my response is not escaped or rejected before being returned to an http client. However I found this out through trial and error rather than by following clear documentation or working examples. My next step is to implement examples of get, post, put and delete HTTP methods to understand how parameters are passed in the case of path variables and query strings, as well as completing the integration with dynamodb. I'll post my working code once done.
i am trying to get json data and store data in db and send json object about status of operation i am able to store data in db but my return json object is not working fine i am not getting json object
my java code:
#RequestMapping(value = "/a",headers="Content-Type=application/json",method = RequestMethod.POST)
#ResponseBody
public JSONObject data(#RequestBody String load)
{
org.json.JSONObject obj = new org.json.JSONObject();
obj.put("Status", "Success");
obj.put("Details","DB updated");
return obj;
}
In your #RequestMapping annotation define produces = MediaTyp.APPLICATION_JSON_VALUE. Your method should then just return a simple Map.
What is returned is actually controlled by the accepts Header in the request. So as an alternativ you could always ensure that your request asks for the right typ. But setting produces in the annotation is in my opinion a good idea as Spring does some auto conversions based on libraries available on the classpath. This might cause security issues if you do not control the type by hand.
edit:
Instead of a simple Map you could also just return any Java Object as long as it can be serialized by Jackson. You can control serialization using annotation in the Object class in this case.
Also you need the Jaclson library on the classpath for this to work (should be the case if you use a basic Spring Boot Web App).
Here is the offical Spring guide on how to build sutch a service: http://spring.io/guides/gs/rest-service/
I am learning Spring Rest services, I have question regarding Spring rest services
Is it possible to call Spring Rest service from other language like c++ or Ruby, where c++ or Ruby will act as Client and Spring Rest service as service or resource provider.
If it's possible can some one explain simple, detailed manner with example.
The reason of asking the question, if we develop a web service using Jax-ws, the interoperability will happen across the technologies like calling Java based web service calling from C++ or and vice versa, can same thing happen using Rest service which is developed in Spring Rest or using Jersey api framework.
A REST call is just an http call. The service doesn't care what language the client is coded in - could be a browser, a mobile phone, written in c++, java, c, objective-c, it doesn't matter.
Typically if you have object data to pass from the client to the service, you would encode it in JSON or XML.
Yes, it is possible. The key of course is Serializing/Deserializing Data. As long as your Rest service accepts serialized data as input, and returns serialized data as output.
For Example, lets say you have an endpoint http://www.example.com/public-api/foo, with acceptable method GET (it provides data).
In Spring, you have a resource named Foo.java, that takes the following form
class Foo implements Serializable {
private static long serialVersionUID = -1L;
private String someProperty;
public Foo() {
...
}
public String getSomeProperty() {
return this.someProperty;
}
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
}
With the following Controller
#Controller
#RequestMapping(value={"/"})
class FooController {
#RequestMapping(value={"/foo"}, method={RequestMethod.GET})
public HttpEntity<Foo> foo() {
...
Foo foo = new Foo();
...
return new ResponseEntity<ResourceSupport>(foo, HttpStatus.OK);
}
}
When you access this in your browser, it will return the following text
{
"_self": "http://www.example.com/public-api/foo",
"someProperty": ...
}
This output (in JSON), can be parsed in Ruby and C++ (or any language really) quite simply.
Inputting is the same way. Instead of parsing JSON, you would just POST or PUT JSON data that conforms to whatever resource you're trying to input. To POST or PUT a new Foo object, you just POST or PUT JSON data with the appropriate Properties.
DISCLAIMER: I did search exhaustively for an answer to this question, and yes, I did find this other question: https://stackoverflow.com/questions/10315728/how-to-send-parameters-as-formparam-to-webservice . But firstly, that question is asking about Javascript, while I am asking about Java, and secondly, it has no answers anyway. So on to the question...
With RESTful services, passing #QueryParams into an #GET service is fairly easy, as you can simply append variables name/value pairs to a URL and use it to hit the server from within the program. Is there a way to do this with #FormParams as well?
For example, let's say I have the following RESTful service:
#POST
#Produces("application/xml")
#Path("/processInfo")
public String processInfo(#FormParam("userId") String userId,
#FormParam("deviceId") String deviceId,
#FormParam("comments") String comments) {
/*
* Process stuff and return
*/
}
... and let's say I also have another method somewhere else in my program like this:
public void updateValues(String comments) {
String userId = getUserId();
String deviceId = getDeviceId();
/*
* Send the information to the /processInfo service
*/
}
How can I perform the commented out action in the second method?
NOTE: Assume these methods are not in the same class or package. Also assume that the RESTful service is hosted on a different server than the machine you are running your method from. As such, you must access the method and pass the values in in a RESTful way.
Thank you for your help!
Using #FormParam you can bind form parameters to a variable.You can find a sample here.
Secondly ,In order to call rest service internally form your java method code you will have to use jersey client.Example code can be found here.
You can pass form parameters using jersey client form as follows.
Create form
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(UriBuilder.fromUri("http://localhost:8080/api").build());
Form f = new Form();
f.add("userId", "foo");
f.add("deviceId", "bar");
f.add("comments", "Device");
pass it to Restful method.
service.path("processInfo").accept(MediaType.APPLICATION_XML).post(String.class,f);
reference
Currently I have a web service running in a tomcat (http://localhost:8080/myApp/getUsers). My web service will accept a json string and then process accordingly. My webservice code is as follows:
#Path("/getUsers")
public class UsersWS
{
#POST
public Response post(String theRequestJSON)
{
try
{
JSONObject aJsonObj = new JSONObject(theRequestJSON);
String userID = aJsonObj.getString("userID");
System.out.println(userID);
}
}
}
So, my Web service is processing a json string. So now, I need to call the above web service from another JAVA class (with a jsonObject having the userID in request parameter).
How to do it? Shortly, I need to make a web service call from a JAVA class with a JSON object as a request parameter. How to send a json as a request parameter in a request call.
Take a look at Jersey: http://jersey.java.net
Here's a good write up on how to use the client:
http://blogs.oracle.com/enterprisetechtips/entry/consuming_restful_web_services_with
Use native URLConnection or Apache HttpClient to send a HTTP request to the server.And the parameters must passed in key=value&key2=value2... format. So you may need to reconstruct the JSON object in that format or using another special parameter name like data=jsonstring then parse the json string using some library.
#George has basically already answered your question, but in terms of JSON processing you may want to also look at Jackson http://jackson.codehaus.org/
This allows you to quickly convert Java objects to JSON equivalents.