I'm trying my first Java RESTful web service and probably I don't have clear some mechanisms.
Here an example of my code:
@Path(Paths.USERS)
public class UserService {
private static final String OK_MESSAGE_USERSERVICE_PUT = Messages.OK_MESSAGE_USERSERVICE_PUT;
private Client esClient = ElasticSearch.getClient();
@GET
@Produces(MediaType.APPLICATION_JSON)
public String get(@QueryParam(QParams.ID) String id) {
// TODO Authentication
try {
GetResponse response = esClient
.prepareGet(PRIMARY_INDEX_NAME, USERS_TYPE_NAME, id)
.execute().actionGet();
if (response != null) {
return response.getSourceAsString();
}
}catch (ElasticsearchException e) {
e.printStackTrace();
return e.getMessage();
}
return Messages.RESOURCE_NOT_FOUND;
}
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public String update(@QueryParam(QParams.ID) String id,
@PathParam("metadata") String metadata) {
// TODO Authentication
boolean isMyself = true;
// precondition, the user exsists. If the check fails, you
// should put the isMyself flag at false.
if (isMyself){
esClient
.prepareIndex(PRIMARY_INDEX_NAME, USERS_TYPE_NAME, id)
.setSource(metadata).execute().actionGet();
}
return OK_MESSAGE_USERSERVICE_PUT;
}
My problem is:
How should I pass the metadata to the web service? I tried with
curl -g -X PUT 'http://localhost:8080/geocon/users?id=007&metadata={"name":{"first":"james","last":"bond"}}'
but I encounter an error like
Root Cause: java.net.URISyntaxException: Illegal character in query at index 33: /geocon/users?id=007&metadata=%7B"name":%7B"first":"james","last":"bond"%7D%7D
java.net.URI$Parser.fail(URI.java:2848)
Googling around, I've tried this different solution:
curl -X PUT -H "application/json" -d '{"name":{"first":"james","last":"bond"}}' http://localhost:8080/geocon/users/
but with this approach, I don't know how to pass to the web service my will of updating the user with ID 007 (since, AFAIK, I'm only communicating {"name":{"first":"james","last":"bond"}}).
How would you do? Thanks!
I would completely refactor this solution.
First: Change the url scheme to make the id part of the URI path. This is a more RESTful approach
Second: The request entity body should be the JSON. I don't see any reason for this to be "metadata". You can get rid of that altogether. You want to update the resource representation with the data you are sending, so this should be part of the body.
Third: If you're working with JSON, you should take advantage of Pojo Mapping with a provider like Jackson. This will automatically pars the JSON to a Pojo. You can do something like
Then just have the
Agent
argument in the method signature, signifying that it is the body of the request.You will need to add the Jackson provider to the project. Hopefully you are using Maven. You can add
Then in your application configuration, register the
JacksonJsonProvider
. If you need help with this, then show how you are configuration your application (whether web.xml or anApplication
subclass). If you want to skip the Pojo mapping and just get the raw JSON, the just set the method argument type toString
as you already are doing (just without the annotation)Fourth: Then your request would be (I'm on Windows, where we need to use double quotes and escape the interior quotes)
Fifth: I would change the
@GET
method also, to make the id part of the URL path, instead of a query param.It looks like you mix the way parameters are passed to a
GET
request (?foo=bar
) with aPUT
method, which is much more likePOST
.I'd expect that you send your JSON data to an URL like
/gecon/user/13
, of course after having your URL mapping edited properly.Try reading the wikipedia and this answer.