YAWP! 1.4.0 Released

YAWP! 1.4.0 is ready to roll and, among other minor improvements, it brings:

Hierarchical APIs

YAWP! has now a full hierarchical API mechanism. When designing your endpoint models based on inheritance, it is now possible to design your feature classes (actions, hooks, transformers, shields) to reutilize behavior through inheritance too.

For instance, imagine we have the following endpoint inheritance:

public abstract class Vehicle<T> {
    @Id
    IdRef<T> id;
}

public class Car extends Vehicle<Car> {
}

public class Truck extends Vehicle<Truck> {
}

public class Airplane extends Vehicle<Airplane> {
}

Now imagine that we want an API to start/stop our vehicles. Let’s assume that all vehicles, with the exception of airplanes, have the same start/stop behavior. To design those features with hierarchical APIs we only need to do the following:

public class VehicleStartStopAction<T extends Vehicle> extends Action<T> {
    @PUT
    public void start(IdRef<Vehicle> id) {
        // do something
    }
    @PUT
    public void stop(IdRef<Vehicle> id) {
        // do something
    }
}

public class AirplaneStartStopAction extends VehicleStartStopAction<Airplane> {
    @PUT
    public void start(IdRef<Airplane> id) {
        // do another something
    }
    @PUT
    public void stop(IdRef<Airplane> id) {
        // do another something
    }
}

Since VehicleStartStopAction is not an abstract class, all vehicles will have the same action routes. The following routes are all valid ones:

PUT /api/cars/1/start
PUT /api/trucks/1/start
PUT /api/airplanes/1/start

PUT /api/cars/1/stop
PUT /api/trucks/1/stop
PUT /api/airplanes/1/stop

Note that only the airplane’s routes will have different functionality.

Finally, it is also possible to define global features (for all endpoints) if you target your inheritance to the Object superclass. For instance, to create a Shield for all endpoints, we can create:

public class BaseShield<T> extends Shield<T> {

    @Override
    public void defaults() {
        allow();
    }
}

If you want to create a more specific Shield for an endpoint, just subclass the BaseShield.

jQuery dependency removed

Thanks to (rsolci)[http://github.com/rsolci], the javascript client is now self-contained and do not require jQuery anymore. Soon it will be available as a npm package too.

Improved Action signature support

The position of each action method argument is not relevant anymore. You can add them in any order you want without changing how the API will work. For instance:

// this:
@POST
public Person addAddress(IdRef<Person> id, Address address) {
    person.setAddress(address);
    yawp.save(person);
}
// could also be:
@POST
public Person addAddress(Address address, IdRef<Person> id) {
    person.setAddress(address);
    yawp.save(person);
}