Headerparam in Restful web services - java-ee-6

Hye. I have this code set up in Rest:
#Path("companyTypes/{companyCode}")
#GET
public Response getCompanyDetails(#PathParam("companyCode") String permitTypeCode,
#HeaderParam(HttpConfig.HEADER_TOKEN) String token) {}
My ws will send companyCode through http like this "..ws/company/companyTypes/1" and what is #HeaderParam means. Is it related with #PathParam?

From Oracle
The #PathParam parameter and the other parameter-based annotations,
#MatrixParam, #HeaderParam, #CookieParam, and #FormParam obey the same
rules as #QueryParam
Header parameters (indicated by decorating the parameter with
javax.ws.rs.HeaderParam) extracts information from the HTTP headers

Related

How to pass any number of headers to Feign client without knowing all the names?

I've a use case where I need to pass all headers that start with a certain prefix to the feign client. I don't know the number or exact names of these headers. There doesn't seem to be a way to to do this easily as the Feign client expects all headers to be specified using #RequestHeader("name"). It doesn't seem to support something like #RequestHeader HttpHeaders, which would be very useful.
Any suggestions?
As of this writing, Feign doesn't support dynamic headers or query parameters using a Map. The Spring Cloud Feign client relies on the Spring annotations instead of Feign annotations, and the implementations of AnnotatedParameterProcessor have a bug such that they don't do what the documentation states they should be doing.
RequestHeader doc:
If the method parameter is Map, MultiValueMap, or HttpHeaders then the
map is populated with all header names and values.
RequestParam doc:
If the method parameter is Map or MultiValueMap and a parameter name
is not specified, then the map parameter is populated with all request
parameter names and values.
I submitted a pull request that will fix this. Until then, I'm using an extension of SpringMvcContract that uses my own AnnotatedParameterProcessor implementations. I set the custom SpringMvcContract using a Feign.Builder as follows:
#Autowired
FormattingConversionService feignConversionService;
#Bean
#Scope(SCOPE_PROTOTYPE)
public Feign.Builder feignBuilder() {
return HystrixFeign.builder()
.contract(feignContract());
}
#Bean
public Contract feignContract() {
return new EnhancedSpringMvcContract(feignConversionService);
}
From the documentation, you should be able to specify a header map for dynamic headers.
In cases where both the header field keys and values are dynamic and the range of possible keys cannot be known ahead of time and may vary between different method calls in the same api/client (e.g. custom metadata header fields such as "x-amz-meta-" or "x-goog-meta-"), a Map parameter can be annotated with HeaderMap to construct a query that uses the contents of the map as its header parameters.
#RequestLine("POST /")
void post(#HeaderMap Map<String, Object> headerMap);

Protect REST URL with same path and different http methods

I have a situation that I need some assistance with. I have four REST URL with same path and different http methods
/api/users/** GET,POST,PUT,DELETE
I want to use Shiro to protoct the PUP, POST, DELETE and keep GET is anonymous. I configured the following URLs but with out luck
/api/users/** =rest[user:update,user:delete,user:create]
/api/users/** =anon
Maybe you could do something like this:
/api/users/**=rest[user]
Then, it kind of depends on how you are creating the REST APIs. With a JAX-RS implementation, like Jersey for example, you could do the following:
#Path("/api/users")
public class SomeResource {
#RequiresPermissions("user:read")
#GET
public Response getResource() {..}
#RequiresPermissions("user:create")
#PUT
public Response putResource() {..}
#RequiresPermissions("user:update")
#POST
public Response postResource() {..}
#RequiresPermissions("user:delete")
#DELETE
public Response deleteResource() {..}
}
This is assuming that you are going with the Annotations based authorization. You could also use the SecurityUtils.getSubject() mechanism.

What is the restTemplate.exchange() method for?

Actually what does the restTemplate.exchange() method do?
#RequestMapping(value = "/getphoto", method = RequestMethod.GET)
public void getPhoto(#RequestParam("id") Long id, HttpServletResponse response) {
logger.debug("Retrieve photo with id: " + id);
// Prepare acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.IMAGE_JPEG);
// Prepare header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
HttpEntity<String> entity = new HttpEntity<String>(headers);
// Send the request as GET
ResponseEntity<byte[]> result =
restTemplate.exchange("http://localhost:7070/spring-rest-provider/krams/person/{id}",
HttpMethod.GET, entity, byte[].class, id);
// Display the image
Writer.write(response, result.getBody());
}
The method documentation is pretty straightforward:
Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns the response as ResponseEntity.
URI Template variables are expanded using the given URI variables, if any.
Consider the following code extracted from your own question:
ResponseEntity<byte[]> result =
restTemplate.exchange("http://localhost:7070/spring-rest-provider/krams/person/{id}",
HttpMethod.GET, entity, byte[].class, id);
We have the following:
A GET request will be performed to the given URL sending the HTTP headers that are wrapped in the HttpEntity instance.
The given URL contains a template variable ({id}). It will be replaced with the value given in the last method parameter (id).
The response entity will be returned​ as a byte[] wrapped into a ResponseEntity instance.
TL;DR: Q: What is a request-response pair called? A: An "exchange".
The term exchange is used, almost incidentally, in the official technical documentation of HTTP to refer to an HTTP request combined with the corresponding response.
However looking at the answers to the following questions, it is clear that while this may have represented a de facto standard for some people, many other were not aware of it, or hadn't adopted it.
What is a request-response pair called?
Name for HTTP Request+Response
The documentation doesn't bother to mention the etymology of the name -- probably assuming that it's obvious.
Notice, however, that there are many different RestTemplate HTTP request methods listed and only a small fraction of them are named exchange. The list is primarily made up of HTTP method-specific names such as delete, put, getForEntity, postForObject, et cetera. Technically speaking, all of these methods perform exchanges in the same sense, but the more focused convenience methods are limited to a specific subset of the possible exchange functionality and parameter+return types.
To put it simply, the set of exchange functions are the most general/capable methods provided by RestTemplate, so you can use exchange when none of the other methods provides a complete enough parameter set to meet your needs.
For example:
Sending GET request with Authentication headers using restTemplate, in which the OP has noticed that "...the only way to send Headers such as accept and Authorization is by using the exchange method..."
The more generic exchange API requires a HttpMethod parameter and a request object for completeness. Compare:
ResponseEntity<Foo> response =
restTemplate.exchange(url, HttpMethod.GET, request, Foo.class);
ResponseEntity<Foo> response =
restTemplate.getForEntity(url, Foo.class);
The exchange method executes the HTTP method against the specified URI template, passing in the parameters for replacement. In this case it gets an image for a person entity for its Id parameter and returns the byte array for it.

Generating WADL request parameters for #InjectParam

I am using the #InjectParam to inject query parameters into a JAX-RS resource that contains #QueryParam annotated fields on a Jersey 1.12 implementation.
On the Resource:
#Path("query")
#GET
#Produces(MediaType.APPLICATION_XML)
public Query queryParam(#InjectParam Query query) {
return query;
}
And in the pojo that receives the injected parameters I have some JAXB and JAX-RS annotations.
#XmlRootElement
public class Query {
#QueryParam("value1")
String value1;
}
A simple test from a REST client:
http://localhost:8888/sandbox/query?value1=hello3
Produces the correct results:
<query>
<value1>hello3</value1>
</query>
That's great, but I also use the wadl-maven-plugin to generate a client which uses the WADL file to produce client code. The WADL file does not include the necessary request parameters that would be there if the #QueryParam annotation was included in the resource method parameters. Subsequently my client is produced to accept no parameters:
SandboxApi.sandbox().query().getAsQuery()
instead of accepting a populated generated client pojo.
Query queryClient = new Query();
queryClient.setValue1("hello3");
SandboxApi.sandbox().query().getAsQuery(queryClient);
Anyone know of a magic annotation I can put on the Jersey Resource that will produce a WADL with the right information so Wadl2Java could generate a client that will accept the POJO and subsequently send the appropriate fields as query parameters?
A response provided (via a private conversation) from some of the fine people working on Jersey:
#Path("query")
#GET
#Produces(MediaType.APPLICATION_XML)
public Query queryParam(#QueryParam("value1") String value1,
#InjectParam Query query) {
return query;
}
query param "value1" should appear in generated WADL.
In-built WADL generator does not contain support for these cases and I'm not sure whether it will be supported anytime soon.

Url as path parameter in restful api causes bad request

We are developing a restful api using jersey (1.9.1) and tomcat 5.5.
A given resource is identified with a urn and we would like to address a specific instance of that resource. In order to achieve this, we used the following code:
#Path("/XXXs")
public interface XXXResource {
#GET
#Path("{id}")
#Produces({ MediaType.APPLICATION_JSON })
XXXInfo getXXX(#PathParam("id") String id);
}
The idea is to address this resource using the following url:
http://localhost:8080/restapi/XXXs/http%3A%2F%2Fns.something.com%2FXXX%2F2
The decoded path param value should be:
http://ns.something.com/XXX/2
However, when I make the request using the encoded url I get a bad request message from tomcat. So my questions are:
Is it correct to use a Urn as a path parameter?
Why is tomcat considering this request as a bad request?
Just in case, I changed the signature of the method so that the parameter is taken from the query string and it worked fine, but I want the parameter to be part of the path.
Thanks.
Ok, I solved it by adding the following line in catalina.properties:
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true