On Fri, Dec 2, 2011 at 4:40 PM, Mark Kharitonov
<[email protected]>wrote:

> > [Tim wrote:] Restlet can support all kinds of things, including the
> ability to have the same ServerResource class provide different subsets of
> the uniform interface depending on the URI.
>


> Can you show an example of this, please? [...] I would like to understand
> how do I override the default ServerResource behavior. Not that I am going
> to rush and do it, but it will contribute to my understanding of the
> ServerResource abilities.


If you're serious, dig into the source code and look at the protected
methods of ServerResource; these are the ones that you can override to
replace or augment default behavior. For starters, look at overriding
ServerResource.getVariants(Method).



> > [Tim wrote:] It sounds like you're pushing against the constraints of
> the REST paradigm, which limit you to exposing at most one GET operation
> per resource. If you have both GET-by-name and GET-by-identity operations,
> you need to have two kinds of resource (if you want to be RESTful), which
> most naturally corresponds in Restlet to two ServerResource subclasses.
>


> I disagree. It is a common practice to provide multiple urls to the same
> resource. Take for instance, the Jenkins (Hudson) CI server. Given a job
> MyJob and 535 being the latest build number, then the same resource, namely
> the job build #535 is available using two different urls:
>  - http://bla-bla/jenkins/job/MyJob/12
>  - http://bla-bla/jenkins/job/MyJob/lastBuild

How do I implement this in Restlet using a single ServerResource?


"Build 535" and "the latest build" are different resources, even if their
representations coincide (until the next build). You don't have to agree
with me, but that interpretation fits well with the standard Restlet
approach.



> This ServerResource class is going to have a single Get() method and it
> would be my responsibility to check whether the url is parameterized with
> an id or it is the lastBuild permalink. This is a boring boilerplate code.


All the more reason to have two ServerResource subclasses:

public class BuildServerResource extends ServerResource {
    @Get public Build getBuild() {
        return getBuildFromId(toBuildId(getRequestAttribute("buildId")));
    }
    protected Build getBuildFromId(BuildId buildId) { ... }
    private BuildId toBuildId(String id) { ... }
    ...
}

public class LastBuildServerResource extends BuildServerResource {
    @Get public Build getLastBuild() {
        return getBuildFromId(getLastBuildId());
    }
    private BuildId getLastBuildId() { ... }
    ...
}

// In Application.createInboundRoot, with MODE_FIRST_MATCH:
    ...
    router.attach("/build/lastBuild", LastBuildServerResource.class);
    router.attach("/build/{buildId}", BuildServerResource.class);

The application-specific methods to validate strings found in URIs and
convert them to build ids (toBuildId) and to obtain the id of the latest
build (getLastBuildId) are *not* boilerplate -- you need them in any event.


If the native Restlet API supported strongly typed request handlers, then I
> would have two Get methods:
>  public BuildBean Get(int id) { return GetBuild(id); }
>  public BuildBean Get(){ return GetLastBuild(); }
>
(Of course, this example limits me to only one permalink, when in fact
> there may be more, like lastFailedBuild, lastSuccessfulBuild, etc ... But,
> I hope it conveys my point)
>

I would model these as different resources and different ServerResource
implementations, perhaps all extending an abstract superclass that provides
common behavior.



> Another real world example are Mercurial changesets. Any changeset has a
> universal identity, which is a string, quite a long string, if I may add.
> But in addition to this, any changeset has a numeric id, which is unique
> within the particular repository clone. Hence we have a resource, which can
> be accessed using two unique keys of different types, which is modeled
> rather easily with two Get methods:
>  public ChangesetBean Get(int id) { ... }
>  public ChangesetBean Get(string hash) { ... }
> Both return exactly the same resource.
>

They return representations, not resources; it's REpresentational State
Transfer. Again, if you model these as distinct resources (that may refer
to the same underlying state and have identical representations), Restlet
makes it easy for you. If you insist on saying that they are actually the
same resource, you're making things harder for yourself in Restlet. (Not
impossible, but I'm not willing to flesh out something that seems so wrong
to me.)



> I do not see how these examples contradict the REST paradigm. If you do -
> please explain.
>

Not so much contradict as push against the constraints. You're willing to
conflate two different kinds of resource in your eagerness to confine
implementation details to a single class. Again, this is like using switch
statements to dispatch on a type discriminator field so you can keep all
logic in the same source file.



> Why do I mention JAX-RS? Well, I am complaining about being unable to
> write strongly typed request handlers and that having parameterless
> handlers (having the body parameter does not change the picture much)
> forces the developer to write tons of boring boilerplate code.
>

My sketch above demonstrates that very little boilerplate is needed in
Restlet. That's one of the reasons I like Restlet so much.

Complaining about the absence of strongly typed request handlers for a REST
framework is a little strange. (It's like complaining about the absence of
clothing at a nude beach!) With a uniform interface, all resources have the
same type: resource!

Restlet gives you the tools to bridge the gap between the uniform interface
and the rich Java interface that your resource handlers have access to. It
doesn't make it easy to overload handling for multiple kinds of resource in
one ServerResource subclass; nor should it, in my view.



> JAX-RS is brought simply because this specification satisfies my
> complaints. This discussion has never mentioned JAX-RS and I would have
> never mention it had I seen another solution to my problems.
>

If the JAX-RS extension fits your needs, why do you want another solution?



> What strikes me the most is that folks seem to be OK with this methodology
> (of having parameterless request handlers). For me, it is a major turn off,
> but I cannot ignore the fact that Restlet is extremely popular, so I am
> trying to figure out how to work with it efficiently. Right now, I do not
> see it possible without the JAX-RS extension.
>

By now anyone who is still reading gets that you prefer JAX-RS. :-)

--tim

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2890210

Reply via email to