Can Jackson/Jax-rs have an optional data? - java

I am making a curl request to endpoint with following option curl --data {"foo" : "bar"} for POST request
However I want to implement a default behavior for missing data, ie curl without --data should also work for POST request.
Currently if data is missing it returns: "error":400,"errorCode":"INVALID_JSON". I do not want that.
Is it possible ?
Does it have any annotation to support optional data.?

Related

get a pagingobject in http response requested over curl

Hello people i have a question about how to get JSON pagingObject in my response with a http curl get (curl running on jokto-linux-system).
i wanted to get a special page over the parameter $offset=0 and $limit=0.
But i dont know where to put the parameter to get on the right page of the serviceressource. I get all the ressources back but i need to see how much pages are used also i didnt see this too.
So my basic problem is the visibility and changing of the parameter $offset and $limit of the pagingObject of an Service/Ressource with amount of Ressourceelements.
Thank you very much for evry answer
This my basic "GET" i try: curl -i http://127.0.0.1:80/service/ressource/Elementuri
Tried to get an the object over header: curl -X GET -H "$offset" -H "$limit" http://127.0.0.1:80/service/ressource/elementuri
I tried it to set after the uri: curl -X GET http://127.0.0.1:80/service/ressource/elementuri?$offset=0&$limit=1
Dollar sign is probably not necessary.
curl http://127.0.0.1:80/service/ressource/elementuri?limit=2&offset=2

Hyperledger Composer + loopback-datasource-juggler + Java: Encoding Problems

I developed a Business Network Definition with Hyperledger Composer, deployed it on a Hyperledger Fabric example-chain (running locally on a VirtualBox-installation of Ubuntu with Docker-containers) and started Composer's REST-server with composer-rest-server (and options -c [cardname] -n always -w true). Then I played a bit in the browser and all is working fine.
Now comes the problematic bit: I want to write a Java-program interacting with this REST API and somehow the API seems unable to parse my Java-sent requests. I copied the JSON-string that Java produces to the browser, ran it there and it worked fine. But if I send it programmatically I get the error (see at the end).
This is what I send through the browser
{"cId":"C_ID7","cDomain":"example.com"}
The browser tells me with CURL it should look like this
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{"cId":"C_ID7","cDomain":"example.com"}' 'http://localhost:3000/api/com.example.Company'
Now I want to send the same message through Java+JSOUP with the following code:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}").execute();
The same (without the requestBody and Method.GET) works for GET-requests. ignoreContentType(true) is necessary, because JSOUP will not handle 'application/json', see here. ignoreHttpErrors(true) is necessary, to get through the Http 500 error, which conceals the true error, which I need for trouble-shooting.
So then finally what I see, when I execute the above code, is the following error:
{"error":{"statusCode":500,"name":"Error","message":"Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}","stack":"Error: Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}\n at com_example_Company.ModelBaseClass._initProperties
(/home/[user]
]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:249:17)\n
at com_example_Company.ModelBaseClass (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:60:8)\n
at com_example_Company.Model (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at com_example_Company.PersistedModel (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at new com_example_Company (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at Function.DataAccessObject.create (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:359:13)\n
at SharedMethod.invoke
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/shared-method.js:270:25)\n
at HttpContext.invoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/http-context.js:297:12)\n
at phaseInvoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/remote-objects.js:676:9)\n at runHandler
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:135:5)\n
at iterate (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at Object.async.eachSeries
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:162:9)\n
at runHandlers (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:144:13)\n
at iterate
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:157:25\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:154:25"}}
where obviously [user] is my username. So I had a look at the loopback-datasource-juggler sources and found that in model-builder.js (source on Github) instead of parsing the different properties of the string, it is given the complete string ("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"). In line 269 the builder checks whether there are dot-characters in the property-name. Since in our case the property name is the complete JSON-string, there are dots and the program fails.
Unfortunately XML does not seem to be supported at this point.
Now: How can this happen? My only guess is an encoding thing done by Java, because the same JSON works in the browser. Any ideas what could have caused this?
And one smaller issue: The error message in the code is ''Property names containing dot(s) are not supported. ' + 'Model: %s, property: %s'', but in the error I receive it says something about "dynamic property". Am I at the wrong point for searching what causes the error?
Since you have already specified 'Content-Type: application/json', you needn't have double quotes in the requestBody. The following should work:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody({\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}).execute();
the curl example is what the REST APIs (rather than merely the browser) know about the business network REST API endpoints.
for your requestBody, you will need the fully qualified class (ie meaning asset/participant/transaction class with leading namespace) - an example is :
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
"$class": "org.example.biznet.SampleAsset", \
"assetId": "1", \
"value": "103300" \
}' 'http://localhost:3000/api/SampleAsset'
So yours will be something like
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"\$class\": \"org.example.biznet.SampleAsset\", \"cId\":\"C_ID7\", \"cDomain\":\"example.com\"}").execute();
I believe you also needed at least one other double-quotes (total above now : 14) and a closing curly bracket in addition.

how to Curl comment to jersey client

How to add bellow curl comment to the jersey client.
curl -X POST --user 'gigy:secret' -d 'grant_type=password&username=peter#example.com&password=password' http://localhost:8000/gigy/oauth/token
I tried to like bellow. but I don't know how to add other things.
Client client = Client.create();
WebResource webResource = client.resource("http://localhost:8000/gigy/oauth/token");
--user 'gigy:secret'
You need Basic Authentication. Basically You need to set the Authorization header with the value Basic base64("gigy:secret"), where base64 is whatever you use to convert the string "user:password" to its Base 64 counterpart. You can set headers on the WebResource calling one it's header method.
-d 'grant_type=password&username=peter#example.com&password=password'
These are application/x-www-form-urlencoded parameters. This is what you will need to send as the entity body of the request. With Jersey you can use the com.sun.jersey.api.representation.Form class. Once you create it, just add key value/pairs to it like key=grant_type and value=password. All the pairs split by &.
Implicit Media type.
When you don't set the Content-Type header in your cURL request, a POST will default to application/x-www-form-urlencoded. You need to set this using the type(MediaType) function after you call header. Use MediaType.APPLICATION_FORM_URLENCODED_TYPE.
-X POST
Now you need to send the request. Just call post after you call type, with the following arguments .post(ClientResponse.class, yourForm). This will return a ClientResponse.

RESTful web service in Java - 400 Bad request - Wrong method invocation? [duplicate]

This question already has answers here:
HTTP GET with request body
(23 answers)
Closed 7 years ago.
I don't understand why this curl invocation gives me a 400 bad request.
curl -v -XGET -H "Content-Type:application/json" -d '{"match":{"first":"james"}}' http://localhost:8080/geocon/search/
Considered that this is the code part who should handle everything
#Path(Paths.SEARCH)
public class SearchService {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String search(#DefaultValue(NO_TYPE) #QueryParam("type") String type, String query) {
// do interesting stuff with the query
System.out.println(type);
System.out.println(query);
return //the result of the query
}
Obviously, I don't see in the console the two print lines and the answer from the web service is 400 Bad request
If I change the verb in curl and in the code (POST instead of GET), the results are OK and everything works as it should.
Why?
Can't I use GET passing data? If you think about it, I am not modifying stuff, I'd just receive data so GET should be the most RESTful translation for it.
You are allowed to send a body with a GET request, but it must not have any semantics; it should essentially be ignored. Not doing so violates the HTTP/1.1 specification. I suggest avoiding this practice because no one expects a request body with a GET request.
Now I'm not sure if the MVC framework you're using is stricter in the sense that it automatically rejects any GET request sent with a body, because in general a server can accept a GET request with a body, but is just supposed to ignore it.
Hence, what you're doing is not RESTful. The only way you can pass in data through a GET is through query parameters.
UPDATE
This is in response to your comment.
You could expose an explicit resource called searchResult or search. To create a searchResult or search resource instance, you pass in a body that is essentially a query. If you are using semantic media types (as you should for proper RESTfulness), your search-result resource could have the media type application/vnd.myservice.search-result+json and the query can have the media type application/vnd.myservice.search-query+json. Then, you can POST a request to /searchResults that has a request body that contains the complex query. The media-type of the response would be application/vnd.myservice.search-result+json and it can contain the search results.
So how does this play out? A search query comes in and you parse out the body and run the query. Then you should persist the results (not for ever; give it some sane TTL value). Once you have done that, you return a 303 See Other with a Location header that has a link to the search results (maybe something like /searchResults/4334, where 4334 is the id of this particular result). The client can then access this URI to retrieve the search results. If the client requests a search result that has expired (i.e., the server cleaned it up because the TTL expired), then the server should respond with a 410 Gone.
Also read this for more pointers.
It seems that syntax you are using has a typo.Try using the below ones for json and xml format. -XGET is wrong. it should be -X GET.
For xml
curl -H "Accept: application/xml" -H "Content-Type: application/xml" -X GET http://hostname/resource
For JSON
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://hostname/resource

Spring REST controller post request

I have this controller in spring
#RestController
public class GreetingController {
#RequestMapping(value = "/greeting", method = RequestMethod.POST)
public String greeting(#RequestParam("uouo") String uouo) {
return uouo;
}
}
and when I testing it
curl -k -i -X POST -H "Content-Type:application/json" -d uouo=test http://192.168.1.104:8080/api/greeting
the result of the testing
HTTP Status 400 - Required String parameter 'uouo' is not present
I tried may thing, but I think #RequestParam can't use for POST it always passed the parameter in URL using GET, I use post only if I had object JSON as parameter using #RequestBody, is there any way to make string parameter send using POST?
The Servlet container will only provide parameters from the body for POST requests if the content type is application/x-www-form-urlencoded. It will ignore the body if the content type is anything else. This is specified in the Servlet Specification Chapter 3.1.1 When Parameters Are Available
The following are the conditions that must be met before post form
data will be populated to the parameter set:
The request is an HTTP or HTTPS request.
The HTTP method is POST.
The content type is application/x-www-form-urlencoded.
The servlet has made an initial call of any of the getParameter family of methods on the request object.
If the conditions are not met and the post form data is not included
in the parameter set, the post data must still be available to the
servlet via the request object’s input stream. If the conditions are
met, post form data will no longer be available for reading directly
from the request object’s input stream.
Since you aren't sending any JSON, just set the appropriate content type
curl -k -i -X POST -H "Content-Type:application/x-www-form-urlencoded" -d uouo=test http://192.168.1.104:8080/api/greeting
or let curl infer it
curl -k -i -X POST -d uouo=test http://192.168.1.104:8080/api/greeting?uouo=test
Note that you can still pass query parameters in the URL
curl -k -i -X POST -H "Content-Type:application/json" http://192.168.1.104:8080/api/greeting?uouo=test

Categories

Resources