Kilimanjaro as a Broker

Kilimanjaro sits between every OSID Consumer and every OSID Provider. This page catalogs the aspects of the OSID Specification that kilimanjaro enforces as it brokers that special relationship.

OsidManager Conformance

When a Consumer calls OsidRuntimeManager.getManager(OSID, String, Version) or getProxyManager(OSID, String, Version), NativeRuntimeManager resolves the OSID's canonical interface and loads the requested implementation class off the thread's context classloader.

The implementation class must implement the requested OsidManager interface and implement a no-arg constructor.

The OsidManager method initialize(runtime) is called. It is through the runtime the implementation may access the configuration managed by the runtime.

OSID Version Compatibility

After a manager is instantiated, Kilimanjaro re-checks the provider's own claim against the version the OSID Consumer asked for.

Compatibility itself is defined by the provider — kilimanjaro is the enforcement point that rejects a manager once it fails its own check.

Casting OSID Objects

This is a no-no. Access to OSID interfaces is brokered using dynamic proxies, which help hide the internals of OSID Providers from nosey OSID Consumers and discourage this kind of out-of-band agreement which keeps them glued together.

If an interface implements org.osid.Suppliable, it is designed to be passed from OSID Consumer to OSID Provider. Examples are OsidForms and OsidQueries. Suppliable interfaces always have an issuer in the OsidSession which ingests these Suppliables. Kilimanjaro will restore the availability of the native object implementation to the OSID Provider which issued them while denying access to other OSID Providers.

OsidPrimitives are immutable values and remain encapsulated once constructed and passed through an OSID boundary.

OSID Contract Enforcement

Interface definitions are only a piece of attaining interoperability. The OSID Specifications also define how they should be used such that if components are swapped, we don't get stuck behind mechanical road blocks.

Many programmers, and now AI coding assistants, can plow past specifications in the quest of getting code to work in isolation. It also matters how the code operates. The OSID Runtime Environment is where that operation occurs and a fail-fast environment enables OSID Consumers and OSID Providers to be shared without getting tripped up on the small stuff.

Consumer Contract Violations

Each of the following exceptions extend org.osid.ConsumerContractException.

For those defensive OSID Provider programmers among you who dutifully check everything before committing state, you don't have to check these conditions as they are checked for you.

ExceptionCircumstances
org.osid.NullArgumentException

A required argument is null — either the whole argument array where the OSID method expects parameters, or one specific parameter.

The OSIDs are a semantic interface definition where every method parameter has meaning. Nulls are used to convey a third possibility which is unknowable by another person coding off the OSID Specification.

The OSID Javadoc calls out the org.osid.NullArgumentException on every argument in which it may be thrown.

org.osid.InvalidArgumentException

An argument(s) value doesn't match what the OSID specifies.

Most common is supplying a negative number to an OSID parameter defined as a cardinal. This may be tricky to see in Java since you see the parameter as a long. The Javadoc calls out this condition.

If the wrong number of arguments, a primitive of the wrong type, an interface argument not assignable to the declared parameter type, or a non-array value where an array is required is detected, an org.osid.InvalidArgumentException will be thrown.

org.osid.IllegalStateException

Pay attention to the Javadoc on this one. The OSID Consumer called a method on a Closeable that's already closed or a manager was initialized twice (or used before initialization completed), or a Transaction was opened while one is already in flight.

Only the OsidManager may be shared by multiple threads. The remaining OSID interfaces from the OsidSession through the OsidLists and OsidObjects are assumed to be accessed by one and only one processing thread (this can be bad). An org.osid.IllegalStateException will be thrown if it is detected these interfaces are accessed by multiple threads (note: it is ok to acquire one and pass it to another thread).

org.osid.InvalidMethodException

An attempt at invoking a non-OSID method was detected, perhaps through reflection or a problem in versioning.

Provider Contract Violations

Each of these extends org.osid.ProviderContractException.

For those defensive OSID Consumer programmers among you who dutifully check every return value from an API, you don't have to check these conditions as they are checked for you.

ExceptionCircumstances
org.osid.NullReturnException

An OSID method returned null.

org.osid.InvalidReturnException

The returned value doesn't match the method's specified return type.

org.osid.InvalidErrorException

The OSID Provider threw an exception not defined in the specification of that OSID method. Implementors should pay mind to the Javadoc to see what the specified exceptions are.

org.osid.MissingMethodException

An attempt at invoking a valid OSID method which does not exist in the OSID Provider, typically because it was built against a different OSID interface version than the one running.

org.osid.ProviderContractException

The OSID Provider returned a non-null value where the OSID specified void.

The breakdown of the set of org.osid.ConsumerContractExceptions and org.osid.ProviderContractExceptions quickly identifies which side of the line a bug occurred. They blame an OSID Consumer or an OSID Provider to encourage the fix to be placed where the problem is, rather than trying to paper over it which will only bite later.

Both families extend org.osid.OsidRuntimeException. In rare circumstances Kilimanjaro throws exceptions for problems in its own internal wiring or if it detects reflective funniness interfering with the runtime.

Use of Dynamic Proxies

Implementing an OSID Provider using dynamic proxies is fine but your class must implement org.osid.binding.java.DynamicManager or it must be assignable to the requested OsidManager interface.