Skip to content
lxndrp edited this page Oct 12, 2011 · 4 revisions

The tuOCCI Annotations API

Overview

The tuOCCI Annotations API is designed to allow the simple exposure of standard, JavaBeans-compliant classes in a non-invasive way. To this end, it offers a number of JSR 175-compatible annotations to enrich types with OCCI-specific metadata information.

The following sections detail the available annotations and explains how they work together. Most concepts explained here are directly derived from the OCCI Core; regarding the detailed semantics please refer to the normative specification text.

For details on how things are wired together, please take a look at the Entity documentation.

Fundamentals: @Category, @Kind, and @Mixin

The fundamental elements of the tuOCCI Annotations API are @Category, @Kind, and @Mixin. They specify the type of resource that will be exposed by the OCCI service.

@Category

The @Category annotation wires the OCCI type system to a Java class. This way, every annotated type can be exposed as a specific Category via the OCCI service. @Category is a type-level annotation and must be attached to the class.

Example:

@Category(term="foo", scheme="http://example.com/bar#")
public class Foo {
    ...
}

Every @Category is uniquely identified by a term and a scheme, separated by the hash (#) character. As such, the full identifier for the example above would be http://example.com/bar#foo. It is important to make sure that the full identifier is globally unique; tuOCCI does not provide a mechanism to achieve this, but using a URL namespace that is under your control is a good starting point. Within the tuOCCI framework, only the uniqueness among the exposed categories will be enforced.

@Kind

The @Kind annotation denotes that the annotated class is a first-class citizen resource in the OCCI world. It indicates to the tuOCCI framework that the annotated type should be exposed as a resource, discoverable through the Query Interface, and manipulable via the protocol rendering in use.

Example:

@Category(term="foo", scheme="http://example.com/bar#")
@Kind
public class Foo {
    ...
}

In the above code snipped, the class Foo is exposed as an OCCI Kind in the Category 'http://example.com/bar#foo' via the Query Interface, and instances of it can be created using the protocol rendering in charge. Because no further information is given, an instance of Foo created via OCCI will only comprise the category and kind information, but no "payload" (such as fields of the class or methods that can be accessed through OCCI.

@Mixin

With a @Mixin annotation, a class is declared to be an attachable extension in the OCCI model, a so-called Mixin. Mixins are no resources by themselves; rather than that, they add a capability to an already existing @Kind. This way, OCCI provides a way for "decorating" Kind instances with additional features.

Example:

@Category(term="foo", scheme="http://example.com/bar#")
@Mixin
public class Foo {
    ...
}

From the API perspective, @Mixin-annotated classes are not different in their structure from a @Kind: both share a @Category annotation, and both indicate their role in the OCCI Core. The only difference lies in the usage via and handling by the OCCI service.

Exposing Fields: @Attribute

Having Kind and Mixin without additional payload is of limited usefulness only: the former can only act as indicator resources, showing that a certain concept is present or not; the latter may serve as a tagging mechanism to group resources under a user-defined Category.

To allow more useful resources, OCCI introduces the concept of an Attribute. It is conceptually is the equivalent to a Java Field that can be manipulated via getter and setter methods as described in the JavaBeans model (see above). The @Attribute annotation serves as a way to tell the OCCI service that a specific field of the annotated class should be exposed as an Attribute via OCCI.

Example:

@Category(term="foo", scheme="http://example.com/bar#")
@Kind
public class Foo {
    
    @Attribute(name = "bar.foo.somevalue", required = false, mutable = true)
    private String someValue;

    ...

    public String getSomeValue() { ... }

    public void setSomeValue(String someValue) { ... }
}

In the above example, the Field "someValue" is exposed as an OCCI Attribute named "bar.foo.somevalue" in the Category namespace "http://example.com/bar#foo". Setting the attribute via OCCI is optional (indicated by the required = false parameter); that is, a newly created instance of the Kind does not need to set it—the equivalent concept in Java would be a field that is set via the class constructor. In addition, "bar.foo.somevalue" is a mutable Attribute; that is, it can be modified via OCCI.

tuOCCI will take care of binding the manipulative actions on the OCCI service to your classes automatically via introspection. In order to make this possible, it is crucial that, for every field you wish to expose, corresponding getters and setters following the JavaBeans conventions are available.

Note that tuOCCI will enforce the setting of an Attribute marked with required = true only via the OCCI service, but not internally—you need to take care in your own code that the corresponding field is properly initialized with sane data.

Exposing Methods: @Action

While having the ability of exposing an Attribute via OCCI is useful, many applications require the possibility of invoking complex operations on a resource. Although in many cases, a change of state of an Attribute may indicate the need for larger changes in the backend, this mechanism tends to add clutter to the resources.

To avoid this, OCCI introduces the concept of an Action: operations on a resource that are independent from the resource's attributes and model complex modification processes. An Action in OCCI can be compared to a method on a class in Java, which modifies the state of one or more objects in the context of the instance it is invoked on. tuOCCI provides the @Action annotation as a means of indicating that a certain method on a class should be exposed as an Action on the corresponding Kind or Mixin.

Example:

@Category(term="foo", scheme="http://example.com/bar#")
@Kind
public class Foo {
    
    @Attribute(name = "bar.foo.somevalue", required = false, mutable = true)
    private String someValue;

    ...

    public String getSomeValue() { ... }

    public void setSomeValue(String someValue) { ... }

    @Category(term = "dosomething", scheme = "http://example.com/bar/foo#")
    @Action
    public void doSomething(@Attribute(name = "someparameter") String someParameter) { ... }
}

In the above example, the doSomething(String) method is exposed as an OCCI action with the Category identifier "http://example.com/bar/foo#dosomething". This Action needs one parameter to be invoked, namely "someparameter", which—on invocation is mapped to the method's argument someParameter.

Narrowing Scope: @Attaches

Although the OCCI Core does not impose any limitations on what Mixin can be attached to which Kind whatsoever, real world implementations do: to make a @Mixin a useful companion to a @Kind, the latter obviously must have some logic implemented to handle the former in a sensible way.

Obviously, this flexibility needs to be channeled, and tuOCCI provides the @Attaches annotation to do so. It accepts as parameter a set of classes, and the tuOCCI runtime will automatically enforce on the OCCI service layer that a Mixin can only be attached to an Entity (again, see OCCI Core terminology) if the @Kind-annotated class has an additional @Attaches annotation with the given @Mixin's class.

Example:

@Category(term="foo", scheme="http://example.com/bar#")
@Kind
@Attaches({ Baz.class })
public class Foo {
    
    @Attribute(name = "bar.foo.somevalue", required = false, mutable = true)
    private String someValue;

    ...

    public String getSomeValue() { ... }

    public void setSomeValue(String someValue) { ... }

    @Category(term = "dosomething", scheme = "http://example.com/bar/foo#")
    @Action
    public void doSomething(@Attribute(name = "someparameter") String someParameter) { ... }
}

@Category(term="baz", scheme="http://example.com/bar#")
@Mixin
public class Baz {
    ...
}

In the above example, tuOCCI will make sure that attaching a "http://example.com/bar#baz" Mixin to a "http://example.com/bar#foo" Entity is allowed, while some other Mixin, say "http://example.com/bar#other" is not.