Hi Alan,
thanks for going over this and giving feedback.
My first question is if there's a specific use case in mind
defining the return content or if you're simply exposing existing functionality/domain
models.
I have two things in mind currently - this operations POC is the 2nd item on the list
1) expose data that we have in the server in a (programming) language independent way so
that people that do not speak
java can still use the data in their favorite language to e.g. create über-dashboards that
display metrics in the way they
want. Or easily obtain availability of resources and so on.
Many admins speak scripting languages fluently, but not Java. The D3 examples show ways to
interpret the existing data
with the help of JavaScript in order to explore new ways of displaying. I think RHQ needs
to allow this freedom, as we
can never know in advance what the user will want. I've also talked about that last
monday at the London JBUG and the
general opinion was that this freedom is needed.
2) Try to model a workflow to things we have like scheduling an operation or defining an
alert definition or ... in a generic
way that follows the HATEOAS principle of REST. Meaning that the individual REST-resource
defines the next possible
steps by the links it exposes.
I have written a generic tool in Ruby that makes use of this and which does not know about
the specific REST-resources; of course
a client needs to know the meaning of the fields, But in general this allows to create
generic wizards in languages like
Ruby, Python etc. and the exchange of data with other tools. I think Dave Webster wrote
earlier in this mailing list, that this is
what they are already trying to achieve[1].
If the latter, it didn't work out too well for what I was trying
to do and I had to build my own facades before this was efficiently usable.
This is very possible. I did want to show what I have done so far in order to collect
feedback on what can be improved.
It is also obvious that doing all this via curl calls is tedious, but it shows what is
sent and received in a relatively direct manner.
Some questions below.
> # Getting the platforms
> $ curl --user rhqadmin:rhqadmin
http://localhost:7080/rest/1/resource/platforms
-HContent-Type:application/json
> [{"typeName":"Mac OS X",
Why does the return content differ from that below?
I omitted the links to make it more clear what is sent, but obviously missed the point and
made it more obscure this way.
> # Getting one resource
> $ curl --user rhqadmin:rhqadmin
http://localhost:7080/rest/1/resource/10001
-HContent-Type:application/json
> {"typeName":"Mac OS X",
> "resourceName":"snert",
> "parentId":0,
> "pluginName":"Platforms",
> "resourceId":"10001",
> "links":[
> {"rel":"operationDefinitions",
>
"href":"http://localhost:7080/rest/1/operation/definitions?resourceId=10001"},
> {"rel":"self",
> "href":"http://localhost:7080/rest/1/resource/10001"},
> {"rel":"schedules",
>
"href":"http://localhost:7080/rest/1/resource/10001/schedules"},
> {"rel":"children",
>
"href":"http://localhost:7080/rest/1/resource/10001/children"}
> ],
> "typeId":10020}
I assume the 'links' construct is a vestige from xhtml/xml/html? It's
awkward accessing this via javascript - this isn't just a stylistic concern.
Well, the links follow the AtomPub format (at least their XML representation)[2]. AtomPub
defines that a link has <link rel="x" href="x"> and
is a pretty common standard for links in resources. But yes, the AtomPub protocol seems to
take them from html.
for (var i = 0; i < this.links.length) {
if (this.links[i]['rel'] == 'children')
I see the issue here.
I found something like this much more accessible.
{
[..]
children: [ 'http://foo/N', 'http://foo/N+1', … ]
operations:
"http://localhost:7080/rest/1/operation/definitions?resourceId=10001"
}
Still you can not assume in a more generic way that a key 'children' or
'operations' is there.
The check is still needed.
With the current setup you can do
for (int i = 0 ; < links.length ; i++ ) {
var btn = ' <a class='button' href="' + links[i].href +
'">' + rel + '</a>';
display(btn);
}
to render the options the user has in a way that is not dependent on the rest-resource
But I have been trying to do what you suggest and this currently fails in RESTeasy, as for
a Java-ResourceWithType
that has a List<Link> embedded, RE is basically taking the RWT object and throws it
at JAXB which serializes
it into XML. The user/developer has no way to influence how the embedded java types are
rendered.
It may be possible to hack the JacksonProvider in some way to get it that way.
If you're querying a resource it seems reasonable that just the
immediate children be made available (vs. the entire tree). Also - it seems likely
you'll be accessing one of them next so putting the immediate children in cache is
beneficial to affinity.
Yes. Server-side caching is hard to get right with our Security setup (not impossible)
So overall, the 1st level (/platforms) contains very little
information. I didn't find it terribly useful as is - not enough information to do
anything other than more queries;
Platforms give you a single entry point into the system (for the resources, there also
exist such for groups and alerts and so on). This follows the
principle of the discoverability in REST. As I said above, I omitted the links in my mail,
which obviously was a mistake.
the 2nd level (/resource/N) contains more but was cumbersome to work
with javascript. What I found really missing was a detailed get - a single query that
pulled a resource + resource operations + resource alerts (plus other information when
that's implemented). I assume that would be a pretty common use-case and without it
someone needs to make several trips to the server to display a single resource.
If this is a use case that people want, I am all for implementing it, as more coarse
grained (and thus less frequent) access is better for performance
and scalability. Also here we need to be careful to e.g. only include operation
definitions and alert definitions, as these are much more stable and can
thus be much better cached by the client. Individual alerts or operation histories should
not be in that object as
I wasn't able to spend more time looking at anything else but did
find it nicely accessible; simple to get started with. It looks like a good start.
I'll try to keep up with the updates in your branch.
Thanks. I meanwhile updated the code to also display the operations history and to make it
possible to
pass (simple) parameters to operations.
I've also updated the d3 examples to match the latest REST code.
I will showcase the Ruby tool soon.
Thanks again for your feedback
Heiko
[1]
https://fedorahosted.org/pipermail/rhq-devel/2011-September/001226.html
[2]
http://bitworking.org/projects/atom/rfc5023.html#listing-collections