Restlet 2, milestone 4. Handling variants.
Hi, I'm having a problem with returning a proper resource representation based on the request Accept header value. I'd like to return 2 representations: String or JSON base on corresponding request media types: ALL, APPLICATION_JSON. My understanding is that I have to add supported variants in my server resource code like this: protected void doInit() throws ResourceException { getVariants().put(Method.GET, Arrays.asList(new Variant[]{ new Variant(MediaType.ALL), new Variant(MediaType.APPLICATION_JSON) })); } I check the request media type in the @Get method and build a proper representation: @Get public Representation getRepresentation(Variant variant) throws JSONException { Representation result = null; if(mtype.equals(MediaType.ALL)) { // Return XML representation result = new StringRepresentation(…); } else if(mtype.equals(MediaType.APPLICATION_JSON)) { // Return JSON representation result = new StringRepresentation(XML.toJSONObject(…).toString()); } else { setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE); // Generate error representation here } return result; } In my Restlet test client I run 2 test requests expecting to get 2 different representations like this: Public void foo() { ClientResource poiResource = new ClientResource(http://myhost:myport/path;); Representation rep = poiResource.get(MediaType.ALL); if(!(poiResource.getStatus().isSuccess() poiResource.getResponseEntity().isAvailable())) { fail(The request has failed: + rep.getText()); } rep = poiResource.get(MediaType.APPLICATION_JSON); if(!(poiResource.getStatus().isSuccess() poiResource.getResponseEntity().isAvailable())) { fail(The request has failed: + rep.getText()); } } But I got 2 problems with that: 1. After I add the varian adding code all my requests fail with The method specified in the request is not allowed for the resource identified by the request URI 2. If I remove variant adding code from server resource Init() method, no matter what media type I specify in a client resource, in the server resource's @Get method the value of the 'variant' argument is always MEdiaType.ALL. Am I doing something wrong? Thanks! -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2395647
Re: Servlet Container with multiple URL Mappings
Further to this... servlet servlet-nameabcservlet/servlet-name servlet-classorg.restlet.ext.servlet.ServerServlet/servlet- class init-param param-nameorg.restlet.application/param-name param-valueca.mysite.MyABCApplication/param-value /init-param /servlet servlet servlet-namexyzservlet/servlet-name servlet-classorg.restlet.ext.servlet.ServerServlet/servlet- class init-param param-nameorg.restlet.application/param-name param-valueca.mysite.MyXYZApplication/param-value /init-param /servlet servlet-mapping servlet-nameabcservlet/servlet-name url-pattern/abc/*/url-pattern /servlet-mapping servlet-mapping servlet-namexyzservlet/servlet-name url-pattern/xyz/*/url-pattern /servlet-mapping Given this setup, the Applications are never being created, which means the createRoot() method is never creating the Routers necessary. I then tried to supply a Component instead: servlet servlet-nameabcservlet/servlet-name servlet-classorg.restlet.ext.servlet.ServerServlet/servlet- class init-param param-nameorg.restlet.component/param-name param-valueca.mysite.MyABCComponent/param-value /init-param /servlet servlet servlet-namexyzservlet/servlet-name servlet-classorg.restlet.ext.servlet.ServerServlet/servlet- class init-param param-nameorg.restlet.component/param-name param-valueca.mysite.MyXYZComponent/param-value /init-param /servlet And in each constructor, all they do is attach their respecitve Applications to their default hosts via the getDefaultHost().attach() method. I was using the getContext().createChildContext() method to pass to the Application's constructor: ... public MyXYZComponent() { super(); getDefaultHost().attach(new MyXYZApplication(getContext().createChildContext()); } But none of the parameters from the context-params are being copied over. Even the getContext() method doesn't contain them anymore. I know this is still a Milestone for Restlet 2.0, but is there a but in here anywhere? How do I correctly do this? Many thanks! Dustin On 16-Sep-09, at 2:03 PM, Dustin Jenkins wrote: I'm using JDK 1.6, Restlet 2.0M4 on FC8 running Tomcat 6. My current web.xml maps two different URLs like so: web-app context-param param-nameorg.restlet.application/param-name param-valueca.mysite.MyApplication/param-value /context-param servlet servlet-nameserver/servlet-name servlet-classorg.restlet.ext.servlet.ServerServlet/servlet- class /servlet servlet-mapping servlet-nameserver/servlet-name url-pattern/abc/*/url-pattern /servlet-mapping servlet-mapping servlet-nameserver/servlet-name url-pattern/xyz/*/url-pattern /servlet-mapping /web-app Which means that there is only one Application with one Router to serve these two URLs. So if I want to route just the /abc/ and /xyz/ Resources, the Router will need to attach the / to two different Resources; one for abc, and the other for xyz, which can't be done. I think the documentation's suggestion was to use a Virtual Host instead, and have it map to different Applications. Is that the best solution in this case? Would it even work? Is there something simpler? If I did go that way, would I instead create my own Component, and attach separate Virtual Hosts, or one Virtual Host with separate Applications? Many thanks, Dustin Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2395736 Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396082
NullPointerException in ServerResource::getAvailableVariants() (r 2.0 M4)
I encountered the following exception (snippet): java.lang.NullPointerException at org.restlet.resource.ServerResource.getAvailableVariants(ServerResource.java:681) at org.restlet.resource.ServerResource.doNegotiatedHandle(ServerResource.java:556) at org.restlet.resource.ServerResource.doConditionalHandle(ServerResource.java:254) at org.restlet.resource.ServerResource.handle(ServerResource.java:930) ... while trying to implement the following post method (snippet): @Post(xml:xml) public Representation postXml() throws IOException { ...} Apparently, the following call in ServerResource::getAvailableVariants(): ListMetadata allMetadata = getMetadataService() .getAllMetadata(annotationInfo.getValue()); returns null when the annotation is xml:xml, but not just xml. I didn't see anything in the bug database, but just wanted to make sure before reporting it. [The javadoc for the Post annotation actually has an example of @Post(xml:xml) which I originally assumed was a convention for @Post(consumes:produces).] The other, related questions I have are: Q1 - What is the @Post annotation's value supposed to mean? I originally assumed was a convention for @Post(consumes), but it's acting like @Post(produces)[1]. If so, then it seems like I can't implement the following functionality via annotations only: @Post(html:html|xml|json) That is, I'd like to: - submit form data (e.g. application/x-www-form-urlencoded) from a client that accepts html, xml, or json - route the call to the method that can process form data - return xml|json|html based on a provided query parameter (e.g. resource_url?format=json) (which overrides any accept header preference) Q2 - is the JAX-RS support (which provides parallel functionality) ready for general use? I remember seeing a note somewhere that it wasn't ready (at least in release 2.0 M4). If it's ready then I'm assuming I could do something like (I'm sure I don't have the right annotation values, but you get the gist): @Post @Consumes(html) @Produces(xml|json|html) public Representation methodThatAcceptsFormDataButCanReturnHtmlOrJsonOrXmlBasedOnQueryParameter() { ... } Regards, Bob Notes: [1] I have the following code (snippet) @Post(xml) public Representation postXml() {...} @Post(html) public Representation postHtml() {...} If I post form data via a browser (which has an accept header that prefers HTML over XML) then postHtml() gets called. If I post form data via curl (which has accept header with */*) then postXml() gets called (because xml shows up first in the supported variants list and no format preference was stated). -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396102
Client Authentication PKI
I noticed the example on http://wiki.restlet.org/docs_1.1/13-restlet/27-restlet/46-restlet/213-restlet.html which configures one way SSL between the server and client by setting the system properties javax.net.ssl.trustStore, javax.net.ssl.trustStoreType, javax.net.ssl.trustStore.Password for the client. I have a requirement to set up two way SSL and not to use the aforementioned system properties. I am trying to piece together from the API how to do this. I realize I have to use the org.restlet.data.ChallengeResponse. I was thinking of using the constructor ChallengeResponse(ChallengeScheme scheme, String identifier, SeriesParameter parameters). I just wasn't about a few things. For the ChallengeScheme can I use ChallengeScheme.CUSTOM? What do I use for the identifier argument? For SeriesParameter argument do I just load them much the same way they are loaded on http://wiki.restlet.org/docs_1.1/13-restlet/27-restlet/46-restlet/213-restlet.html (just replacing with the context for the Client and adding the trustore properties)? Is there anything else I might need? -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396050
Resource Cleanup
Hello, I am using a router and the attach method (attach(uri pattern,class extends Resource) for my application. My question is: when I'm finished with the resource (and I know I no longer need it), what do I do to clean up? Is it as simple as calling router.detach? or must I also delete the resource somehow so that garbage collection can reclaim that memory? Thanks, Matt -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396013
Re: Resource Cleanup
Hi Matt, On Sep 17, 2009, at 9:14 AM, webp...@tigris.org wrote: I am using a router and the attach method (attach(uri pattern,class extends Resource) for my application. My question is: when I'm finished with the resource (and I know I no longer need it), what do I do to clean up? Is it as simple as calling router.detach? or must I also delete the resource somehow so that garbage collection can reclaim that memory? Restlet creates a new instance of your resource class for each request. It will go out of scope and be eligible for garbage collection after the request is complete. If you are talking about having the resource class itself garbage collected, then I think that calling detach would be sufficient from the restlet perspective. (Whether or not the class will actually be eligible for collection at that point depends on the environment in which you're running.) I've never tried that myself, though. Rhett -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396121
Re: Client Authentication PKI
Hi Dan, You can't really do this with a ChallengeScheme/ChallengeResponse or something similar, since it the certificates are passed at the SSL/TLS layer, which is under HTTP. If you don't want to use the system properties, you can use your own SslContextFactory passed as an argument to the client connector. Best wishes, Bruno. Dan S wrote: I noticed the example on http://wiki.restlet.org/docs_1.1/13-restlet/27-restlet/46-restlet/213-restlet.html which configures one way SSL between the server and client by setting the system properties javax.net.ssl.trustStore, javax.net.ssl.trustStoreType, javax.net.ssl.trustStore.Password for the client. I have a requirement to set up two way SSL and not to use the aforementioned system properties. I am trying to piece together from the API how to do this. I realize I have to use the org.restlet.data.ChallengeResponse. I was thinking of using the constructor ChallengeResponse(ChallengeScheme scheme, String identifier, SeriesParameter parameters). I just wasn't about a few things. For the ChallengeScheme can I use ChallengeScheme.CUSTOM? What do I use for the identifier argument? For SeriesParameter argument do I just load them much the same way they are loaded on http://wiki.restlet.org/docs_1.1/13-restlet/27-restlet/46-restlet/213-restlet.html (just replacing with the context for the Client and adding the trustore properties)? Is there anything else I might need? -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396050 -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396122
Re: Client Authentication PKI
I should also say that this feature has only been implemented quite recently on the client side, so you might need a recent version of Restlet. More on this topic at: http://restlet.tigris.org/issues/show_bug.cgi?id=586 Best wishes, Bruno. Bruno Harbulot wrote: Hi Dan, You can't really do this with a ChallengeScheme/ChallengeResponse or something similar, since it the certificates are passed at the SSL/TLS layer, which is under HTTP. If you don't want to use the system properties, you can use your own SslContextFactory passed as an argument to the client connector. Best wishes, Bruno. Dan S wrote: I noticed the example on http://wiki.restlet.org/docs_1.1/13-restlet/27-restlet/46-restlet/213-restlet.html which configures one way SSL between the server and client by setting the system properties javax.net.ssl.trustStore, javax.net.ssl.trustStoreType, javax.net.ssl.trustStore.Password for the client. I have a requirement to set up two way SSL and not to use the aforementioned system properties. I am trying to piece together from the API how to do this. I realize I have to use the org.restlet.data.ChallengeResponse. I was thinking of using the constructor ChallengeResponse(ChallengeScheme scheme, String identifier, SeriesParameter parameters). I just wasn't about a few things. For the ChallengeScheme can I use ChallengeScheme.CUSTOM? What do I use for the identifier argument? For SeriesParameter argument do I just load them much the same way they are loaded on http://wiki.restlet.org/docs_1.1/13-restlet/27-restlet/46-restlet/213-restlet.html (just replacing with the context for the Client and adding the trustore properties)? Is there anything else I might need? -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396050 -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396122 -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396125
Volatile Application - WAS: Servlet Container with multiple URL Mappings
I think I've finally come to the crux of my angst. The Application and Context are both volatile in the ServerServlet class, so they will be shared across instances of the ServerServlet class. In my web descriptor, I map two different URL patterns to two different ServerServlet servlet instances, but they will both have the same Application instance. I can't map /* to a single Servlet as we need to pass everything but those two URLs to the Proxy. Sorry for the small flood of e-mails, but I think this is the main part of my problem, and I'm not sure where to go. Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396130
Re: Problem routing using VirtualHosts and differentiating on Port number
Hello John, you can configure the logging (see http://wiki.restlet.org/docs_2.0/101-restlet.html), or you can also inherits your VirtualHost and override the logRoute(Route route) method. best regards, Thierry Boileau Hi, Thierry- Thanks for taking a look at this. I have taken your sample code, and I agree, it seems to work fine. I've been adding features to it to try to get it to fail, but haven't been able to so far. I've also been trying to disable stuff in my real app, to see if I can get it to start working like the sample, but haven't gotten that to work, either. Is there a way to enable detailed logging in the routing code, so that I can see which routes are being tested and which ones chosen? Maybe if I can identify what routes are being tried/rejected, I can figure out what I'm doing wrong. Thanks once again for your help! John Wismar Architect - ALLDATA Technology Team (916) 478-3296 mailto:john.wis...@autozone.com Dedicated to technology leadership and innovation. Thierry Boileau thierry.boil...@noelios.com wrote on 09/11/2009 12:40:45 AM: [image removed] Re: Problem routing using VirtualHosts and differentiating on Port number Thierry Boileau to: discuss 09/11/2009 12:40 AM Please respond to discuss Hello John, I send you a sample code that works for me (with current trunk of Restlet and HttpClient 3.1). Could you run it, and maybe send a reproductible test? Best regards, Thierry Boileau -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2393547 http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2393547 package virtualHosts; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.restlet.Component; import org.restlet.Request; import org.restlet.Response; import org.restlet.Restlet; import org.restlet.data.Protocol; import org.restlet.routing.VirtualHost; public class TestVirtualHostPort { public static void main(String[] args) throws Exception { Component component = new Component(); component.getServers().add(Protocol.HTTP, 8182); component.getServers().add(Protocol.HTTP, 8183); // Application A Restlet restletA = new Restlet() { @Override public void handle(Request request, Response response) { System.out.println(host A + request.getResourceRef()); } }; // Application B Restlet restletB = new Restlet() { @Override public void handle(Request request, Response response) { System.out.println(host B + request.getResourceRef()); } }; // Virtual hosts VirtualHost hostA = new VirtualHost(); hostA.setHostPort(8182); component.getHosts().add(hostA); VirtualHost hostB = new VirtualHost(); hostB.setHostPort(8183); component.getHosts().add(hostB); hostA.attachDefault(restletA); hostB.attachDefault(restletB); component.start(); HttpClient client = new HttpClient(); HttpMethod method8182 = new GetMethod(http://localhost:8182/;); HttpMethod method8183 = new GetMethod(http://localhost:8183/;); // Prints on the console : host A http://localhost:8182/ client.executeMethod(method8182); // Prints on the console : host B http://localhost:8183/ client.executeMethod(method8183); component.stop(); } } -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396150
Is Atom extension usable where workspace and service not defined?
I am trying to post to an Atom Pub which currently does not support workspaces and the complete service document. Is there still a way for me to use the org.restlet.ext.atom API to post? -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396202
Re: Volatile Application - WAS: Servlet Container with multiple URL Mappings
I think you're right, thanks Rhett. The Application still appears to only be generated once though, even though both ServerServlets are being instantiated. It's really weird. Thanks, Dustin On 17-Sep-09, at 12:29 PM, Rhett Sutphin wrote: Hi Dustin, On Sep 17, 2009, at 12:45 PM, Dustin Jenkins wrote: I think I've finally come to the crux of my angst. The Application and Context are both volatile in the ServerServlet class, so they will be shared across instances of the ServerServlet class. I don't think this is what volatile means. (It's more like what static means.) volatile indicates that an instance variable is allowed to be accessed by multiple threads simultaneously[1]. If you have separate ServerServlet instances, those instance variables should stay separate. There are static elements involved with contexts -- e.g., Context.getCurrent() -- however I think they are all implemented thread-locally. I don't have a solution for you, but I'm pretty sure volatiles aren't the problem. Rhett In my web descriptor, I map two different URL patterns to two different ServerServlet servlet instances, but they will both have the same Application instance. I can't map /* to a single Servlet as we need to pass everything but those two URLs to the Proxy. Sorry for the small flood of e-mails, but I think this is the main part of my problem, and I'm not sure where to go. Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396130 [1]: http://www.javamex.com/tutorials/synchronization_volatile.shtml is a nice overview. -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396166 Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396203
Re: Volatile Application - WAS: Servlet Container with multiple URL Mappings
Yes, you're definitely right, Rhett. The problem is the ServletContext stores the Application and the Component as an Attribute, which then makes it available to other Servlets it appears. I didn't know the ServletContext made its attributes available to the Container. Thanks, Dustin On 17-Sep-09, at 12:29 PM, Rhett Sutphin wrote: Hi Dustin, On Sep 17, 2009, at 12:45 PM, Dustin Jenkins wrote: I think I've finally come to the crux of my angst. The Application and Context are both volatile in the ServerServlet class, so they will be shared across instances of the ServerServlet class. I don't think this is what volatile means. (It's more like what static means.) volatile indicates that an instance variable is allowed to be accessed by multiple threads simultaneously[1]. If you have separate ServerServlet instances, those instance variables should stay separate. There are static elements involved with contexts -- e.g., Context.getCurrent() -- however I think they are all implemented thread-locally. I don't have a solution for you, but I'm pretty sure volatiles aren't the problem. Rhett In my web descriptor, I map two different URL patterns to two different ServerServlet servlet instances, but they will both have the same Application instance. I can't map /* to a single Servlet as we need to pass everything but those two URLs to the Proxy. Sorry for the small flood of e-mails, but I think this is the main part of my problem, and I'm not sure where to go. Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396130 [1]: http://www.javamex.com/tutorials/synchronization_volatile.shtml is a nice overview. -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396166 Dustin Jenkins dustin.jenk...@nrc-cnrc.gc.ca -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=2396208