I am building a REST API using JAX-RS. In angular front-end, I am sending the object to be deleted in the body of the HTTP request (JSON format). Now I need a way to map this HTTP DELETE body request which is containing the object that needs to be deleted to a local variable in the REST method.
For instance, on SPRING I did this by simply annotating an object variable with #RequestBody.
I was checking oracle's javaEE7 docs but the examples there are really basic and don't include complex objects, also the different tutorials that I found elsewhere were on the track of simple delete requests mapping a simple id with #PathParam.
Maybe before this question, the first question I should ask is whether sending the object in an HTTP's request body is at all a good approach? I was reading some articles which designated it as not such a good practice, although it is not explicitly forbidden. What would be the disadvantages of this approach?
I remember while I was researching about this method in SPRING, I read somewhere that malicious attacks could be possible by specially crafted user inputs (the persistence framework that I am using is JPA, EclipseLink).
Would it perhaps be better to map the primary key on a series of #Path variables and then map them using #PathParam?
So to sum up, first of all, is this a good approach?
And how can I read the object in the HTTP's request body?
Some pointers would be highly appreciated!
Unlike Spring MVC, JAX-RS does not define any annotation for the request payload.
The JAX-RS approach is slightly different: the value of the parameter not annotated with any #***Param annotations is mapped from the request entity body. Such parameter is called entity parameter.
The first question I should ask is whether sending the object in an HTTP's request body is at all a good approach?
Please refrain from doing that, as it's not how DELETE is supposed to work.
Find below a quote from the RFC 7231, the document that currently defines the semantics and content of the HTTP/1.1 protocol:
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
For interoperability, I advise you to stick to the standards as much as you can. And you definitely shouldn't be require to send any payload to identify the resource to be deleted.
Its primary key is 8 fields long.
The URI, which stands for Universal Resource Identifier, is meant to identify a resource.
As you have a bunch of fields that, in conjunction, identify a resource, I advise you to rethink your application design. You could, for example, introduce some sort of unique value to identify your resources. Have a look at UUID.
With JAX-RS you don't need a something like a #RequestBody.
You can simply add the class as parameter and it will be filled with the request body.
In you case passing the data in the body makes sense but how does your URL look like? As with REST you should have resources that are addressable by a URL
Related
I’m trying to find the best pracice on what type of response should I send when a path parameter in a REST service is blank or null when using a PUT method.
For example, imagine we have the following resource:
PUT report/{report-id}/client/{client-id}
Should I validate that the parameter report-id and client-id are not null or blank?
If they are blank or null I can think of two types of messages:
Return a 400 response with a message indicating that a mandatory
parameter is missing.
Return a 404 response, indicating that we can’t create or update the resource because that resource dosn’t exist?
I don't think there is a standard convention of doing it. Is there? However, I would like to hear opinions on what's the best practice to use in this case.
The specification for REST might be insightful here:
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.
Since the lack of a resource cannot logically be given a name it can never exist in REST. As a consequence I think you'd find that most public APIs will return 404. Take getting a user's information from GitHub for example. The documentation states that a user can be found at https://api.github.com/users/{username}. https://api.github.com/users/ (notice the trailing slash) returns 404. Regardless of what the HTTP spec says (although following it is always a good idea) if you adhere to the principle of least surprise returning 404 is your best bet.
As a side note, when naming resources the convention is that collections should be plural. So, for your example you would actually want the resource to look more like: /reports/{report-id}/clients/{client-id}. Especially when dealing with 'empty' parameters it will make it much clearer exactly what the request was for.
I’m trying to find the best practice on what type of response should I send when a path parameter in a REST service is blank or null when using a PUT method.
An important thing to understand is that the body of the response is available to you to describe in detail what the actual problem is. See RFC 7231, section 6.5
the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.
The status code is metadata, which allows general-purpose components to understand what is going on. The metadata all belongs to the uniform interface, which is to say it is of the "transferring documents over a network" domain.
In this case, I think your best fit for a status code is 403 Forbidden
The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.
We have a system that uses http POST with JSON as an RPC method.
It is an in house solution for internal components communication.
The requests and responses are described each by a Java bean (POJO).
My question is, how can I use swagger annotations to create nice documentation in the swagger standard?
I am not afraid from messing around with existing code, but I was wondering if anyone has some experience with something similar.
The goal is to use Swagger UI to display nice docs and give a playground for users to invoke the Apis.
Based on the comments above, it's impossible to describe this sort of API using Swagger. The Swagger specification is intended to REST-based APIs, where the URLs serve as a unique endpoints to describe an operation, and not the payloads.
By definition, Swagger considers a unique operation to be the combination of a URL and the HTTP method (there are requests to expand the definition to include the mime type as well, for example, but it is not currently available).
There is simply no way to describe a single endpoint that operates multiple requests types, each having its own output.
There may be a solution for what you request in the future, but it is not in the near future, not will it answer your requirements to the fullest.
To be clear - this is not an issue of messing around with code or anything. The specification itself doesn't support it.
There are 2 simple tweaks required to make a swagger file work for any generic hand-built RPC application.
The first tweak is to make the swagger endpoints appear to be unique. This is done by defining each endpoint with a unique name after a hash in the context. This works because your app will not process the url past the '#' and this allows swagger to consider the path to be "unique". In reality though this technique will allow every unique path defined in the swagger file to actually invoke the same endpoint.
paths:
/endpoint#myUniqueCommandA
...
/endpoint#myUniqueCommandB
...
The other tweak is needed to ensure the generated swagger clients will actually call the correct operation inside your RPC app. This is done by implementing a "defaulted single value" enum in each command's request object. The defined enum represents the corresponding attribute / value combo the api needs to pass to get dispatched to the right target action inside your application:
...
definitions:
MyUniqueCommandARequest:
type: object
properties:
rest_call:
type: string
enum:
- myUniqueCommandA
default: myUniqueCommandA
...
MyUniqueCommandBRequest:
type: object
properties:
rest_call:
type: string
enum:
- myUniqueCommandB
default: myUniqueCommandB
...
In the above example, the property "rest_call" is what my underlying system uses to dispatch the request to the right underlying operation.
The request object for myUniqueCommandA has its rest_call attribute defined as enum["myUniqueCommandA"]. The request object for myUniqueCommandB has its rest_call attribute defined as enum["myUniqueCommandB"].
Since these are defined as a single value enums that are also defaulted to that same value, the generated swagger classes that calls these apis will be wired to pass their correct routing value automatically.
I am creating an API and I wonder why it is common to have a id parameter in URI for PUT?
Such as PUT /cars/5
Why don't have PUT /cars? The request entity contains an id field isn't that enough? I can get the id from that entity, or is it some downsides to this, and is it considered bad to do it?
Because if you were to send a PUT request to /cars, semantically that would imply you are trying to modify attributes about the set of cars, rather than modifying attributes of an individual car. The URI in a RESTful API should indicate the exact resource the action is acting upon, so if you are modifying a resource, your URI should exactly indicate that resource.
Also, from RFC 2616:
The URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.
So the spec indicates that if the client knows the resource's unique ID, it should be included in the URI.
this comes from rest "ideology".
the idea is that a url uniquely represents an entity - so you must PUT the entity youre creating/editing to the url of that entity.
to quote from the wikipedia page:
Identification of resources
Individual resources are identified in requests, for example using URIs in web-based REST systems. The resources themselves are conceptually separate from the representations that are returned to the client.
PUT aims to udpate ONE precised entity.
With merely using /cars, you aren't focus on a specific entity.
And on the contrary of what you wrote, your full entity isn't passed in a basic String (URI).
Excepted if your targeted method focus on a hard-coded car id ... but I don't think so..
It comes down to the API interface. There are several approaches to API design. And, like you suggested, you can leave the id out of the request. However, since many API designs are structured in a fashion you described, like PUT /cars/5, it`s considered good practise.
Basically, you have 8 ways to interact with your API. GET, POST, PUT, DELETE and an optional HEAD. ( if you count head, the total would be 9 or 10, depending on the interactions).
So, to clear it up, you have 2 ways of GET. GET /cars would retrieve all cars, GET /cars/5 would retrieve any car with an ID of 5.So, you have 2 ways of using GET. The same goes for POST, PUT and DELETE. 4*2 = 8 right?
Now, there are people who would say that PUT /cars would be ambigious, however you are completely valid in doing it without the extra ID field, because, as you mentioned, you are already passing in the ID field in the request.
The guys at Apigee have been researching API designs for a while now. I recommend watching some of their video`s to understand better what API design means and why some arguments are valid, and others are not.
Apigee Best practises
This must have been answered previously, but my Google powers are off today and I have been struggling with this for a bit. We are migrating from an old PHP base to a Jersey-based JVM stack, which will ultimately provide a JSON-based RESTful API that can be consumed from many applications. Things have been really good so far and we love the easy POJO-to-JSON conversion. However, we are dealing with difficulties in Cross-Domain JSON requests. We essentially have all of our responses returning JSON (using #Produces("application/json") and the com.sun.jersey.api.json.POJOMappingFeature set to true) but for JSONP support we need to change our methods to return an instance of JSONWithPadding. This of course also requires us to add a #QueryParam("callback") parameter to each method, which will essentially duplicate our efforts, causing two methods to be needed to respond with the same data depending on whether or not there is a callback parameter in the request. Obviously, this is not what we want.
So we essentially have tried a couple different options. Being relatively new to Jersey, I am sure this problem has been solved. I read from a few places that I could write a request filter or I could extend the JSON Provider. My ideal solution is to have no impact on our data or logic layers and instead have some code that says "if there is a call back parameter, surround the JSON with the callback, otherwise just return the JSON". A solution was found here:
http://jersey.576304.n2.nabble.com/JsonP-without-using-JSONWithPadding-td7015082.html
However, that solution extends the Jackson JSON object, not the default JSON provider.
What are the best practices? If I am on the right track, what is class for the default JSON filter that I can extend? Is there any additional configuration needed? Am I completely off track?
If all your resource methods return JSONWithPadding object, then Jersey automatically figures out if it should return JSON (i.e. just the object wrapped by it) or the callback as well based on the requested media type - i.e. if the media type requested by the client is any of application/javascript, application/x-javascript, text/ecmascript, application/ecmascript or text/jscript, then Jersey returns the object wrapped by the callback. If the requested media type is application/json, Jersey returns the JSON object (i.e. does not wrap it with the callback). So, one way to make this work is to make your resource method produce all the above media types (including application/json), always return JSONWithPadding and let Jersey figure out what to do.
If this does not work for you, let us know why it does not cover your use case (at users at jersey.java.net). Anyway, in that case you can use ContainerRequest/ResponseFilters. In the request filter you can modify the request headers any way you want (e.g. adjust the accept header) to ensure it matches the right resource method. Then in the response filter you can wrap the response entity using the JSONWithPadding depending on whether the callback query param is available and adjust the content type header.
So what I ultimately ended up doing (before Martin's great response came in) was creating a Filter and a ResponseWrapper that intercepted the output. The basis for the code is at http://docs.oracle.com/cd/B31017_01/web.1013/b28959/filters.htm
Essentially, the filter checks to see if the callback parameter exists. If it does, it prepends the callback to the outputted JSON and appends the ) at the end. This works great for us in our testing, although it has not been hardened yet. While I would have loved for Jersey to be able to handle it automatically, I could not get it to work with jQuery correctly (probably something on my side, not a problem with Jersey). We have pre-existing jQuery calls and we are changing the URLs to look at the new Jersey Server and we really didn't want to go into each $.ajax call to change any headers or content types in the calls if we didn't have to.
Aside from the small issue, Jersey has been great to work with!
I am creating a web application that incorporates REST-style services and I wanted some clarification as to the preferred (standard) method of how the POST requests should be accepted by my Java server side:
Method 1:
http://localhost:8080/services/processser/uid/{uidvalue}/eid/{eidvalue}
Method 2:
http://localhost:8080/services/processuser
{uid:"",eid:""} - this would be sent as JSON in the post body
Both methods would use the "application/json" content-type, but are there advantages, disadvantages to each method. One disadvantage to method 2, I can immediately think of is that the JSON data, would need to be mapped to a Java Object, thus creating a Java object any time any user access the "processuser" servlet api. Your input is much appreciated.
In this particular instance, the data would be used to query the database, to return a json response back to the client.
I think we need to go back a little from your question. Your path segment starts with:
/services/processuser
This is a mistake. The URI should identify a resource, not an operation. This may not be always possible, but it's something you should strive for.
In this case, you seem to identify your user with a uid and an eid (whatever those are). You could build paths such as a user is referred to by /user/<uid>/<eid>, /user/<uid>-<eid> (if you must /user/uid/<uid>/eid/<eid>); if eid is a specialization, and not on equal footing with uid, then /user/<uid>;eid=<eid> would be more appropriate.
You would create new users by posting to /user/ or /user/<uid>/<eid> if you knew the identifiers in advance, deleting users by using DELETE on /user/<uid>/<eid> and change state by using PUT on /user/<uid>/<eid>.
So to answer your question, you should use PUT on /user/<uid>/<eid> if "processuser" aims to change the state of the user with data you provide. Otherwise, the mapping to the REST model is not so clean, possibly the best option would be to define a resource /user/process/<uid>/<eid> and POST there with all the data, but a POST to /user/process with all the data would be more or less the same, since we're already in RPC-like camp.
For POST requests, Method 2 is usually preferred, although often the resource name will be pluralized, so that you actually post to:
http://localhost:8080/services/processusers
This is for creating new records, however.
It looks like you're really using what most RESTful services would use a GET request for (retrieving a record), in which case, Method 1 is preferred.
Edit:
I realize I didn't source my answer, so consider the standards set by Rails. You may or may not agree that it is a valid standard.