Ability to substract attributes of a type


#1

Hi guys!

I’ve a question for all you gurues here!

I’ve noticed RAML Spec 1.0 (RC2) has amazing “extensions” capabilities around a Raml Type, including:

  1. Modularization (thru #RAML 1.0 extension or #RAML 1.0 overlays),
  2. The required/optional facet on ObjectType,
  3. The “additionalProperties” facet on ObjectType,
  4. Multiheritance and union types,
  5. User-defined Facets…

So, there is a lot of posibilities to “increase” the length or structure of any type. That’s incredibly usefull, of course. But, what if we need to “decrease” the structure or length of any type… How can we reach such goal?


The use case that justifies this need is described as following:


Coming from the world of strongly typed languages, I’m used to thinking in terms of interfaces, abstract classes, inheritance, aggregation and composition, so, considering such flexibility offered by the RAML 1.0 specification, I always feel tempted to declare flexible or polymorphic types, using multi-inheritance and union. When it’s used togheter with RAML Extension and Overlays (and some other cool features mentioned above), I have always been able to “extend” functionality. The major problem comes when I want to “decrease” funcionality.

For example: Consider we want to use RAML types in order to maintain a complete set of business entities that conform a canonical model of data. It is reasonable to think that an entity, conceptually speaking, is the same in independence of which facet of certain functionality is used. But, when attempting to use that entity as part of a functionality exposed in an API, it may not be required to use ALL the attributes of that entity, but only a portion of them (without losing sight of the fact that not using all attributes within such functionality, do not mean that they do not make sense as part of the aforementioned entity).

So, if we want to use a portion of an entity as income for a POST method invokation of any endpoint, it could be desirable to use the same entity, with a different subset of attributes, when invoking a GET method for the same (or even other) endpoint.

So, in conclusion… there is a way to adapt the structure of a RAML Type conveniently according to it use inside the entire API, that is:

  • Declaring a “entity-base” that can mutate if it’s used in income body for a POST or as outcome body for a GET, for example?.
  • There is an elegant way to declare a complete set of attributes for a type, but cutting the non-used attributes for a specific used inside de API?.
  • If it were not possible, would there be a way to “extend” the functionality of a base type, without declaring ‘n’ child entities, one for each possible use within the API?

#2

Hi there,

Off the top of my head… assuming you were using the parser to parse RAML yourself, you could use annotations at the field level to indicate a given property that should not be exposed as part of the API. This would require a bit of work on your part to parse the RAML, check for the annotation on each field, and generate code (I assume that is how you would handle this…generate code). Perhaps you have an annotation called (private). You can then put that in any of the property definitions, and your parser would be able to then ensure that the field associated with that annotation were not part of the public generated code.

The other way, which I think you touched on is to create a base type that has only the properties to expose, then extend that type with extra properties that should not be exposed… and in your code, return the base type as part of the API response, and not the extended types. Not entirely sure how much work this would be, and currently there isnt a good way to get at all the RAML type details. If you reach out to the author of the updated RAML2JAXRS project, he is doing some work like this to generate Java POJOs from RAML Types, he may be able to help a bit more here.


#3

HI @Kevin_Duffey. I really appretiate your interest.

Effectivelly, I have already tried to go the way of the annotations, but I do not feel at all comfortable with the solutions that I have found. Basically, my resistance to continue to base the solution on annotations is that, in principle, it is contrary to the spirit that the creators have given to the annotations. That is, the annotations do not seem to be intended to provide functional or structural aspects of APIs, but rather add meta information of particular utility to other types of API users, such as: the developers. In one way or another, I firmly believe that annotations should not be used, in my humble opinion, to communicate functional information to consumers.

In relation to the need to have an own parser to interpret the annotations (with which I agree absolutely, that parser would be necessary), is another reason why I prefer not to base the solution on them.

The truth is that I hope my API can be “understood”, “interpreted”, “consumed” and “built” by anyone who adheres to the standard, without any dependence on any artifact I should provide.


About your last contribution, very valuable for me too, I agree on the interpretation that “there is not a good way to get all RAML type details”. Finally, since you mention it, I plan to give you a look back at the RAML2JAXRS project, since the last time I looked at it was still oriented to RAML 0.8, and maybe now there is some good idea that can serve my purposes.

Anyway, I really thank you @Kevin_Duffey

Best regards


#4

Hey…happy to help where I can… if I can. Annotations are an interesting beast… they require every parser out there to agree upon some “standard” ones so that they are not proprietary to your own parsing code of RAML to make use of them… though… they do make sense in some ways. I actually have been trying to push the idea about a common set of annotations that parsers/generators should support, like annotations for deprecation, public/private API endpoints, etc. Lots of uses for them… if only the majority of parsers would support them.

RAML2JAXRS… look for a v1.0 (or v10) branch.


#5

Good idea… But. If one could think of a set of common annotations that had only one meaning, should not these annotations be a formal part of the rest of the structures that RAML supports, such as Resource and Types?


#6

Well… so no…I dont think so. The purpose of annotations in the spec is to allow anyone to extend RAML in some not thought of way. I do think the spec could have benefited from actually having something like deprecation and such in the spec, but… things like versioning, deprecation, etc could be handled different depending on the needs of a given application or companies needs. Who knows really how one company may want to interpret them to render HTML vs another. So they allow for a path of extension outside the default spec.

Hence my thought was a sort of central location to look for common annotations that are collaborated upon… and by that I mean the name of the annotation, the RAML definition of it to be used by anyone, and then how it should be interpreted. Anyone wanting to support it could provide some level of parsing of the annotation, and maybe the site would have a list of generators/parsers/whatever that support a given annotation and how so. A product like RAML2HTML might want to support as much as possible to provide avenues of documentation for annotations. Where as a RAML2JAXRS may not benefit from all annotations, but some.


#7

@Kevin_Duffey I have started to create such a repo here. Happy for any contribution.