I am trying to add a new endpoint to a WCF based REST service with the following URL template:
/books/{bookId}/pdf
but it gives an error saying:
The UriTemplate '/books/*/pdf' is not valid; the wildcard ('*') cannot appear in a variable name or literal, unless as a construct for a wildcard segment. Note that a wildcard segment, either a literal or a variable, is valid only as the last path segment in the template; the wildcard can appear only once. See the documentation for UriTemplate for more details.'
Here's the service contract:
[OperationContract]
[WebInvoke(UriTemplate = "/books/{bookId}/pdf", Method = "POST")]
Message GetBookPDF(string bookId);
Is this a limitation that the variable is only valid as the last part of the url? I couldn't find any link that confirms that.
I am sure that the variable needn’t configured in the last part of the URL.
My service contract
public interface ITestService
{
[OperationContract]
[WebInvoke(Method ="POST",UriTemplate ="/books/{id}/pdf")]
string Test(string id);
}
Result.
Please have a look at this link.
https://stackoverflow.com/questions/13956889/in-wcf-can-i-have-a-wildcard-character-in-a-literal-segment-of-my-uritemplate
The most likely scenario is that the UriTemplate can match multiple OperationContract, thus the error happened.
Feel free to let me know if the problem still exists.
TLDR: Create a new AEM page called "mypage.html". Supply suffixes in the URL. Pass this suffixes to an Sling servlet. The suffixes act as URL parameters.
sample desired URL: http://localhost:4502/mypage.html/john/smith
So I created a servlet (used this guide: http://www.aemcq5tutorials.com/tutorials/sling-servlet-in-aem/) that can read a suffix.
#SuppressWarnings("serial")
#SlingServlet(paths="geometrixx/components/hompepage", selectors="name", extensions="html",methods="GET", metatype=true)
public class StaffProfileServlet extends SlingAllMethodsServlet {
private static final Logger log = LoggerFactory.getLogger(CourseBookmarkServlet.class);
#Override
protected void doGet(final SlingHttpServletRequest request,
final SlingHttpServletResponse response) throws ServletException, IOException {
RequestPathInfo rpi = request.getRequestPathInfo();
String[] suffixes = rpi.getSuffix().split("/");
and it working fine if I access it via http://localhost:4502/content/geometrixx/en.name.html/first/last
What I want to do next is create a new page called "mypage.html" and supply first and last as suffixes.
mypage will display information relevant to the person in a properly formatted page. With code above, all I get is JSON response.
Some assumptions/changes which I think is needed to achieve my goal:
I will be using paths and using request parameters (i.e. using request.getParameter("myparameter") on servlet code
I will be using AJAX to access the servlet
If my assumptions are correct, how do I access suffixes from HTL/Sightly? I understand I can get the URI via ${request.requestURI} or even Javascript. And using this value, I can then use this in my AJAX call.
But is this the AEM/Sling way of doing it? Or perhaps there is a better way to do what I want?
Thanks a lot!
You can use RequestPathInfo interface from HTL to access suffix's. ${request.requestPathInfo.suffix}
Global objects accessible through HTL -> here.
Methods accessible through request object -> here.
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.
I had made a REST webservice using redirecting to various paths like if i need to delete some user then i will redirect the user to this address in the #Path annotation :
user/delete
and therefore there is no thing like RESPONSE i have used.
While going through a code given to me by my senior i came accross these lines :
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
Response.created(uri).build();
What are these lines doing, i have no idea.
Can someone explain me this w/o wiki links or any other 'Basic Rest Service' links.
Without any explicit details about the uriInfo object I can only speculate its type is the JAX-RS UriInfo class.
The first line can be broken down as below:
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
The getAbsolutePathBuilder is documented http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/UriInfo.html#getAbsolutePathBuilder%28%29
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
The method returns a UriBuilder object. On which the 'path(...)' method is called passing the id so if the absolute path returned http://www.host.com (this may or may not have a port number) adding the id in this method will then result in the effectively Builder holding the two parts. The base URI and the path. The two values have not yet been put together
The build method then concatenates the two values resulting a full URI. For example http://www.google.com/id (Where http://www.google.com is the absolute path)
The second line
Response.created(uri).build();
Is basically saying 'Respond with a created (201) response code, and set a Location header containing the build uri value'
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