I'm trying to map a "legacy" REST server using RESTEasy client.
The urls of this ws are mapped like this:
http://localhost/webservice/rest/server.php?wstoken=reallylongtokenhash&wsfunction=core_course_get_courses
The endpoint is always server.php, and the function to call is mapped using a queryparam.
#POST
#Path("/server.php")
#Produces("application/json")
List<Map<String, Object>> getCourses(
#QueryParam("wstoken") String token
, #QueryParam("wsfunction") String function
, #QueryParam("moodlewsrestformat") String format);
#POST
#Path("/server.php")
#Produces("application/json")
String createUser(
#QueryParam("wstoken") String token
, #QueryParam("wsfunction") String function
, #QueryParam("moodlewsrestformat") String format
, #Form User user);
which I call in this way
private static void getCourses() {
final MoodleRest client = ProxyFactory.create(MoodleRest.class, "http://localhost/webservice/rest/");
final List<Map<String, Object>> s = client.getCourses(token, "core_course_get_courses", "json");
System.out.println("s = " + s);
}
Let's ignore the fact that a "get_courses" method is mapped using a POST, and that the token are passed using the QueryParameter on this post, is it possible to avoid passing the function and the response format on every method? I would like to map it using the annotations.
I tried to write in directly into the #Path using
/server.php?function=core_course_get_courses
But obviously this is not the right way to proceed (plus, it doesn't work since it's escaped)
Maybe it would be better to use HttpServletRequest directly in your method and parse request parameters "by hand". I mean:
#POST
#Path("/server.php")
#Produces("application/json")
List<Map<String, Object>> getCourses(#Context HttpServletRequest request){
//parse request.getParameters()
}
Related
I have Liferay 7.2.
I created a module rest.
It is possibile to save a variable in session ad use it in other method?
My idea of code is:
#GET
#Path("/save/paramt")
public String jsonSaveParamRequest() throws Exception {
String json = "xx";
//SAVE IN SESSION json
return "ok";
}
#GET
#Path("/get/paramt")
public String jsonGetParamRequest() throws Exception {
String xx= SESSION VARIABLE json
return xx;
}
Saving state in a HTTP session in a REST API is not recommended and should be avoided. Please refer to the discussions here SO:how-to-understand-restful-api-is-stateless.
Technically, I guess this is possible as you can inject the HttpServletRequest as a method param via #Context HttpServletRequest request to your annotated method and use getSession(). But I am not sure if you can rely on that.
We are using JAX-RS to implement a REST API for one of our projects. Requirement is that the users would pass in the request object in JSON format.
Let us assume that we have a method that is invoked on hitting an API endpoint
#POST
#PATH("/api/user")
#Produces("application/json")
#Consumes("application/json")
public CustomResponse methodA(#RequestBody UserInfo userDTO)
Sample Request Object:
{
"firstName":"Test",
"lastName":"Name",
"sno":"A123"
}
UserInfo DTO
private String firstName;
private String lastName;
private String sno;
getters and setters
Now if the user tries to add other parameters to the request object given above (for ex: "age") and invokes api endpoint, we have not been able to intercept and report the same back to the user saying "Invalid parameter age" as it seems that the request is being filtered out for invalid/unknown parameters and not reporting any error as such.
Any thoughts on how this can be addressed?
I was able to identify unrecognized properties by adding following piece of code:
Change the method signature to
public CustomResponse methodA(#RequestBody String reqObj)
and then
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
UserInfo userDTO = mapper.readValue(reqObj, UserInfo.class);
We now see a
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "<>" for any unsupported parameter
I m trying to send http request as follows, using citrus test framework http://www.citrusframework.org/
http().client(ENV).post("/xx/v1/ouxxtbound/tel%3A%2B94xxxxxxx")
.header("Authorization", authorization)**strong text**
.header("Accept", "application/json")
.payload(send)
.contentType("application/json");
its is passing a url encoded values, but when it encode again when sending request by Citrus.as tel%253A%252B94xxxxxxx
Is there are way to send encoded URI correctly?
Citrus uses the following method on the Spring RestTemplate
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {
...
}
The url is given as String value and Spring will automatically encode this value. When passing in some already encoded String the encoding is done twice. When using non-encoded String value the Spring RestTemplate applies uriVariables logic which is also causing errors.
Citrus should use some other method signature on the RestTemplate that uses the URL object instead of String value. As a temporary workaround you can use a custom RestTemplate subclass that overwrites the methods like this and automatically creates the URL object from String:
#Override
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {
return super.exchange(URI.create(url), method, requestEntity, responseType);
}
You can add the custom RestTemplate subclass as Spring bean into the configuration and reference the bean on the Citrus client component by using the attribute rest-template.
I`ve written a RESTService that creates a PDF and returns it via Response Object.
Here is my Client:
final Response response = target.request(MediaType.APPLICATION_OCTET_STREAM).post(Entity.entity(building, MediaType.APPLICATION_JSON + ";charset=utf-8"));
int responseCode = response.getStatus();
String fileName = Response.getHeaderString("fileName");
And here is the important part of my Web Service method:
return Response.ok(report, MediaType.APPLICATION_OCTET_STREAM).header("fileName", reportName).build();
My problem is that the umlauts of my filename are just erased:
So for example, if the fileName is : "Gebäude2_2014" the Client will receive "Geb ude2_2014".
Anybody an idea?
You should be able to use the JAX-RS #Produces in your web service controller and force the UTF-8 encoding. This should fix your issue.
here an example:
#Path("/ws/v1")
#Produces("\"application/json\";charset=utf-8")
public class Documents extends AbstractController {
#GET
#Path("/documents/{id}")
public Response show(#Context UriInfo uri, #PathParam("id") String id) {
...
return Response.ok(report, MediaType.APPLICATION_OCTET_STREAM).header("fileName", reportName).build();
}
}
I've tried to pass a header in response with MediaType.APPLICATION_OCTET_STREAM in my project, and your "Gebäude2_2014" String is read correctly.
In my project all source files are encoded with UTF-8.
I need to create a RESTful service which should support async calls in follwing way. When user calls some method he got the http '202' code and url to poll where he can see the status of his request. Currently I use JAX-RS and its annoations:
#Path("")
public interface MyService {
#POST
#Path("/myService/{name}")
#Consumes({APPLICATION_XML, APPLICATION_JSON})
void postSomething(#PathParam("name") String name, MyObject data);
}
Such mapping would expose MyService's postSomething() method by url /myService/{name} which serves POST requests, get 'name' parameter from url and 'data' from request body.
I want that after making this PUT request client get 202 http code and some callback url to poll to get the result once method will be executed.
So the question is:
1. How to make JAX-RS return 202 code?
2. How to pass callback url to the client?
Have the postSomething method return a Response object:
public Response postSomething(#PathParam("name") String name, MyObject data) {
return Response.status(Status.ACCEPTED).build();
}
If you want the callback URI as plain-text in the HTTP Body you could do something like this:
public Response postSomething(#PathParam("name") String name, MyObject data) {
return Response.status(Status.ACCEPTED).entity("http://google.com").build();
}
For generating URIs by resource classes, have a look at UriBuilder
Use #Context HttpServletResponse servletResponse to get direct control over the servlet's response mechanism.
#PUT
#Path("/myService/{name}")
#Consumes({APPLICATION_XML, APPLICATION_JSON})
void postSomething(#PathParam("name") String name, #Context HttpServletResponse response, MyObject data) {
// ...
response.setStatus(HttpServletResponse.SC_ACCEPTED);
response.setHeader("Location", myURL);
// ...
}