This question already has an answer here:
Spring #RestController Get Request Content-Type to response json or html
(1 answer)
Closed 4 years ago.
I need to make a single api, by which I can return data format of json or xml, as it has been requested from the customer.
guys, any idea how I achieve this because when I use #Produces annotation it makes it fix for specific format, but I need to return as it has been requested.
If you can use Spring, configure ContentNegotiationManager in DispatcherServlet.xml and then you can use response type as parameters to url.
For example:
http://localhost:8080/employee-management-system/viewEmployee/4?type=xml
http://localhost:8080/employee-management-system/viewEmployee/4?type=json
More detailed instructions you can find here:
https://www.javainuse.com/spring/rest4
You could specify the response content type using the ResponseEntity object as follows:
return ResponseEntity
.ok()
.contentType(MediaType.IMAGE_GIF);
What I would normally expect to see here are two methods, one that #Produces ("application/json"), and the other that #Produces("application/xml").
#Path("/foobar")
public final class FooBar {
#Produces("application/xml")
public String xml () { ... }
#Produces("application/json")
public String json() { ... }
}
The example in Oracle's description of the #Produces annotation includes an example for text/plain and text/html which is similar.
this is one way to do it, but I don't want to write 2 methods. I want to do it in one method.
Another reasonable approach would be to get closer to the metal
#Path("/foobar")
public final class FooBar {
public Response foobar() (#Context HttpHeaders headers) { ... }
}
And then inspect the headers yourself to decide what to do. See Get HTTP header in JAX-RS
Related
I am using jersey rest service in java to accept request.
Here is my snippet
#Path("main")
public class xxxx{
#GET
#Path("test/{path}")
public void test(#Context HttpServletRequest req ) {
System.out.println(req.getRequestURI());
}
}
I am invoking this using REST Api as test/abcd , it is working. I want #path to accept test/abcd or test/abcd/ab and so. I tried with "test/{path}/*" nothing works.
Please someone help me as I am new to this.
You should use regex in the #Path for example :
#Path("{parameter: .*}")
Response getData(#PathParam("parameter") List<String> parameter){
//do processing
}
For more details you can see the examples given here.
I'm working with Dropwizard, which uses Jersey internally. I have two methods on a controller:
PUT /garbage/[id1,id2,...idN] is intended to take a path parameter that's a list of numeric IDs representing resources to be updated. I'm using a regex-based PathParam here. I've fudged the regex in this example because I don't think it matters, but the point is that a single numeric ID should match the regex.
GET /garbage/[id] fetches data about a single piece of garbage.
Jersey seems to get confused, despite the difference in method. When I query with something like
curl localhost:8080/garbage/1
Jersey gives me a 405 error. If I take the PUT out of the picture (for example, sabotage the path param regex, or remove it entirely), the GET endpoint works fine.
I assume there is some detail in JAX-RS 3.7.2 I'm missing that explains why this should be the case, but I can't figure out what it is.
Here's the code:
#Path("/garbage")
#Produces(MediaType.APPLICATION_JSON)
public class GarbageController {
private static final Logger LOG = LoggerFactory.getLogger(GarbageController.class);
#PUT
#Path("/{params: [\\d,]+}")
#Consumes(MediaType.APPLICATION_JSON)
#Timed
public Response updateGarbage(#PathParam("params") List<PathSegment> params) {
LOG.warn("updateGarbage");
return Response.status(Response.Status.OK).build();
}
#GET
#Path("/{garbageId}")
public Response getGarbageById(#PathParam("garbageId") long garbageId) {
LOG.warn("getGarbage");
return Response.status(Response.Status.OK).build();
}
}
The main purpose of #PathSegment is to handle fragments of the URI which is useful to retrieve Matrix Parameters. For example the method below:
#GET
#Path("/book/{id}")
public String getBook(#PathParam("id") PathSegment id) {...}
Should be able to handle this request:
GET /book;name=EJB 3.0;author=Bill Burke
Because the #PathSegment intercepts the entire URL fragment the GET method seems to be ignored. You can handle the comma-separated IDs on the PUT request with a simple String split:
#PUT
#Path("/{params}")
#Consumes(MediaType.APPLICATION_JSON)
#Timed
public Response updateGarbage(#PathParam("params") String params) {
LOG.warn("updateGarbage ", params.split(","));
return Response.status(Response.Status.OK).build();
}
You can also change the request format to query parameters or implement a Converter/Provider to handle a custom object. All of them should solve the GET not implemented issue.
I believe this is not a case of route priorities between GET and PUT but instead this is related to the #Consumes annotation which cannot be used on a GET request. Either DW is ignoring this endpoint or is converting it into the default POST method, which would explain the 405 response for the GET request.
I figured this out, although I have not traced far enough into Jersey to know why it works. The solution is to rewrite the #GET method to use the same regex syntax as the #PUT. Jersey will handle the type conversion in the method signature, with the note that it will return a 404 if the type conversion fails (ie, GET /garbage/xyz).
#PUT
#Path("/{params: .+}")
#Consumes(MediaType.APPLICATION_JSON)
public Response updateGarbage(#PathParam("params") List<PathSegment> params) {
LOG.warn("updateGarbage");
return Response.status(Response.Status.OK).build();
}
#GET
#Path("/{params: .+}")
public Response getGarbageById(#PathParam("params") long garbageId) {
LOG.warn("getGarbage {}", garbageId);
return Response.status(Response.Status.OK).build();
}
I'm trying to create a Rest Api using Jax-rs Jersey from a base code generated by swagger.
The specifications are for exemple for a specific Request :
Code : 200
Description : User token for login
Schema : String
My problem is that the generated code use the class :javax.ws.rs.core.Response that should not be extended according to the documentation.
I'm using this kind of code to build the response :
return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK,apiToken)).build();
The response generated looks like that :
{"code":4,"type":"ok","message":"uHN2cE7REfZz1pD17ITa"}
When i only want to have :"uHN2cE7REfZz1pD17ITa" in the body. Is that possible using Jersey ? Or is this format part of the jax-rs specifications ?
Thank you.
ApiResponseMessage from Swagger does not extend Response from JAX-RS. Check the code and you will see that ApiResponseMessage is just a POJO. That is, the piece of code you posted in your question is just fine.
If you only need the token, you can use:
return Response.ok(apiToken).build();
The following gives you the same result:
return Response.ok().entity(apiToken).build();
Since your resource method will produce just a piece of text (not a valid JSON unless the piece of text is wrapped into quotes), the most suitable media type for the response would be text/plain. It could be achieved by either annotating the resource method with #Produces(MediaType.TEXT_PLAIN) or setting the media type in the response, as following:
#GET
#Produces(MediaType.TEXT_PLAIN)
public Response getToken() {
String apiToken = ...
return Response.ok(apiToken).build();
}
#GET
public Response getToken() {
String apiToken = ...
return Response.ok(apiToken, MediaType.TEXT_PLAIN).build();
}
Alternatively you also could make your method return just a String:
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getToken() {
String apiToken = ...
return apiToken;
}
JAX-RS does not require Request or Response in specific format for text,json, xml, or html fallowing a schema . But They all have to be well formated in according to their specifications.
You can send text response like this in jersey
like this
return Response.ok().entity("uHN2cE7REfZz1pD17ITa").build();
I am new to swagger myself So i don't know if the Response in question can be changed or not . But There is no restriction from jersey side
This question already has answers here:
Is it okay to use same resource name for both get and post rest api
(2 answers)
Closed 7 years ago.
In java RESTfull service can I define two methods in same path differentiate by http calling method.
EG : first method using GET and Second one using POST
#GET
#Produces("application/pdf")
public Response getFile(#Context HttpServletRequest req,#PathParam("search") final String search,Map<Object, Object> input) {
....}
#Post
#Produces("application/pdf")
public Response getFile(#Context HttpServletRequest req,#PathParam("search") final String search) {
....}
Annotation is just a decorator for the given method. The core principle is , it should not stop original structure of java classes. So it is perfectly legal to have multiple handler in single file.
Yes, it is perfectly valid to have separate handlers for different methods at the same path.
I've used a regular expression in #Path to achieve overloading and at first I thought it was really neat, but overloading methods is usually not good practice. Does the same apply to RESTful web services? Is there a better way to achieve this using JAX-RS?
So I can now call my getProject REST service by /project/ProjectNumber1000 or /project/12345
#Path("/project")
public class ProjectPropertiesResource
{
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/{name : [a-zA-Z]+}")
public Response getProjectPropertiesByName(#PathParam("name") String name)
{
...
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/{id : \\d+}")
public Response getProjectPropertiesById(#PathParam("id") long id)
{
...
}
}
You can do it, however, only one of the overloads should actually return response body with a 200. The other overloads should return a 303 redirect to the URI that returns the body.
This will ensure that caches only have one copy of the resource and if you do PUT or POST on the main URI you will invalidate the one copy. Otherwise, you can start to get inconsistent results due to different versions existing in the cache.