Let's assume that I have simple class:
public class Test
{
#Path("/test")
#POST
#Produces(APPLICATION_JSON)
#Consumes(APPLICATION_JSON)
public TestResponse post(TestResponse request, #HeaderParam("text") String text)
{
return new TestResponse(request.getData());
}
}
and I want to test this class. So how I can param in code like this:
Entity<TestRequest> requestEntity = Entity.entity(request, MediaType.APPLICATION_JSON);
final TestResponse response = target("test").request().post(requestEntity, TestResponse.class);
target("test").request().header("text", "value").post(...);
When you call request(). You get back an Invocation.Builder. You can take a look at the other methods. For the most part they all return the same Invocation.Builder, so can just chain the calls.
Related
I'd like to create a single method and configure both GET + POST on it, using spring-mvc:
#RestController
public class MyServlet {
#RequestMapping(value = "test", method = {RequestMethod.GET, RequestMethod.POST})
public void test(#Valid MyReq req) {
//MyReq contains some params
}
}
Problem: with the code above, any POST request leads to an empty MyReq object.
If I change the method signature to #RequestBody #Valid MyReq req, then the post works, but the GET request fails.
So isn't is possible to just use get and post together on the same method, if a bean is used as input parameters?
The best solution to your problem seems to be something like this:
#RestController
public class MyServlet {
#RequestMapping(value = "test", method = {RequestMethod.GET})
public void testGet(#Valid #RequestParam("foo") String foo) {
doStuff(foo)
}
#RequestMapping(value = "test", method = {RequestMethod.POST})
public void testPost(#Valid #RequestBody MyReq req) {
doStuff(req.getFoo());
}
}
You can process the request data in different ways depending on how you receive it and call the same method to do the business logic.
#RequestMapping(value = "/test", method = { RequestMethod.POST, RequestMethod.GET })
public void test(#ModelAttribute("xxxx") POJO pojo) {
//your code
}
This will work for both POST and GET. (make sure the order first POST and then GET)
For GET your POJO has to contain the attribute which you're using in request parameter
like below
public class POJO {
private String parameter1;
private String parameter2;
//getters and setters
URl should be like below
/test?parameter1=blah
Like this way u can use it for both GET and POST
I was unable to get this working on the same method and I'd like to know a solution, but this is my workaround, which differs from luizfzs's in that you take the same request object and not use #RequestParam
#RestController
public class Controller {
#GetMapping("people")
public void getPeople(MyReq req) {
//do it...
}
#PostMapping("people")
public void getPeoplePost(#RequestBody MyReq req) {
getPeople(req);
}
}
I want to authorize calls made to my rest api differently depending on which method is being called. But the RequestHandler looks like this:
public interface RequestHandler {
Response handleRequest(Message m,
ClassResourceInfo resourceClass);
}
I can't figure out how to get the Method that will be called from that resourceClass. Is this possible?
The ResponseHandler seems to have a parameter that can do this named OperationResourceInfo:
public interface ResponseHandler {
Response handleResponse(Message m,
OperationResourceInfo ori,
Response response);
}
But by that time, I will have already deleted something I had no permission to delete (as an example).
How do I figure out what method will be called in a request filter? FWIW, the reason I want the Method is because I want to search for a custom built annotation I will put on each method. If there is a better way to approach this, I'm open to the idea.
For completeness, here's the documentation on the topic: http://cxf.apache.org/docs/jax-rs-filters.html
You can use Interceptors, rather than RequestHandler filters as the request handlers are deprecated and replaced in JAXRS 2.0 with ContainerRequestFilter and ContainerResponseFilter
For Example
Say I've RestService shown below
#Service
#Path("/Course")
public class KPRestService {
private final Logger LOG = LoggerFactory.getLogger(KPRestService.class);
#POST
#Path("/create")
#Consumes(MediaType.APPLICATION_JSON)
public Response create(CourseType course){
LOG.info("You have selected {}", course.getCName());
return Response.ok().build();
}
#POST
#Path("/get")
#Produces(MediaType.APPLICATION_JSON)
public CourseType get(#FormParam("cDate")Date date){
final CourseType course = new CourseType();
if(date.after(new Date())){
course.setCName("E&C");
course.setCDuration(4);
}else{
course.setCName("Mech");
course.setCDuration(3);
}
return course;
}
}
I prevent calling the get method using interceptor as shown below.
#Component
public class KPFilter extends AbstractPhaseInterceptor<Message> {
private final static Logger LOG = LoggerFactory.getLogger(KPFilter.class);
public KPFilter() {
super(Phase.PRE_LOGICAL);
}
public void handleMessage(Message message) throws Fault {
final Exchange exchange = message.getExchange();
exchange.put(Message.REST_MESSAGE, Boolean.TRUE);
OperationResourceInfo resourceInfo = exchange.get(OperationResourceInfo.class);
LOG.info("Method name is {}", resourceInfo.getMethodToInvoke().getName());
if (resourceInfo != null && resourceInfo.getMethodToInvoke().getName().equals("get")) {
Response response = Response.status(Response.Status.FORBIDDEN).entity("You are not authorised")
.type(MediaType.TEXT_XML).build();
exchange.put(Response.class, response);
}
}
}
Is it possible to retrieve http headers inside JAXRS resource method without explicitly specifying these headers as method parameters?
For example I have a following interface:
#Path("/posts")
public interface PostsResource {
#GET
public List<Post> getAllPosts();
}
and the following class that implements this interface:
public class PostsResourceImpl implements PostsResource {
#Autowired
private PostsService postsService;
public List<Post> getAllPosts() {
return postsService.getAllPosts();
}
}
I don't want to change my method signature to:
public List<Post> getAllPosts(#HeaderParam("X-MyCustomHeader") String myCustomHeader);
This header will be added by interceptor on the client side so the client code doesn't know what to put here and this should not be explicit method parameter.
You can inject an object of type HttpHeaders within your resource as class variable to have access to request headers, as described below:
#Path("/test")
public class TestService {
#Context
private HttpHeaders headers;
#GET
#Path("/{pathParameter}")
public Response testMethod() {
(...)
List<String> customHeaderValues = headers.getRequestHeader("X-MyCustomHeader");
System.out.println(">> X-MyCustomHeader = " + customHeaderValues);
(...)
String response = (...)
return Response.status(200).entity(response).build();
}
}
Hope it answers your question.
Thierry
I have following jersey method declaration:
#POST
#Path("/fooPath")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public Response isSellableOnline(#FormParam("productCodes") final List<String> productCodes,
#FormParam("storeName") final String storeName,
#Context HttpServletRequest request) {
In rest client I try to invoke following method like this:
When I debug method I see that received parameters are null:
How to rewrite method declaration?
It is because on the isSellableOnlie method you are expecting or trying to extract form parameters, but the incoming POST request is JSON.
Well if you want JSON you should make POJO Class to be able to serialize the JSON.
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Store {
private String storeName;
private List<String> productCodes;
public Store() {
}
public String getName() {
return name;
}
public List<String> getProductCodes() {
return productCodes;
}
}
And then in your method:
#POST
#Path("/fooPath")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public Response isSellableOnline(Store store) {
store.getName();
...
}
I have a resource:
#Path("/")
public class Resource {
#GET
public Response getResponse() {
//..
final GenericEntity<List<BusinessObject>> entity = new GenericEntity<List<BusinessObject>>(businessobjects) { };
return Response.status(httpResultCode).entity(entity).build();
}
}
I want to unit test this method without using a Jersey client, but I don't know how to get the body of the Response object. I can't see a method that works. Here's the test method:
#Test
public void testMethod() {
Resource resourceUnderTest = new Resource();
Response response = resourceUnderTest.getResponse();
List<BusinessObject> result = ???;
}
I can get the result I want if I go though a Jersey Client, but I would rather just call the method directly without making any HTTP requests.
List<BusinessObject> result = (List<BusinessObject>)response.getEntity();
This will return the object you pass into the entity method of response builder. The Response object doesn't serialize the result. Looking at the previous method, getEntity will probably return GenericEntity> so you'd want code like this.
GenericEntity<List<BusinessObject>> result = (GenericEntity<List<BusinessObject>>)response.getEntity();