• Modules
    • By category
    • By name
    • Most popular
    • Most downloaded
    • Repository
  • Register
  • Log in
  • Help
    • Start using Ceylon Herd
    • Publish your first module
    • Module publishing guidelines
    • All about Ceylon
    • Keyboard Shortcuts

    • s Focus search module bar
      ? Open this information panel
      j Move selection down
      k Move selection up
      enter Open current selection
Module info
Name
jogro / se.westshed.bushel / 0.4.0
Backends JVM JavaScript
Maven coordinates
Compatible Ceylon release JVM: 1.2.x, 1.3.x (latest)
JavaScript: 1.2.0 (outdated)
Published Dec 15, 2015
Stats Downloads (JVM): 210
Downloads (JS): 69
Source downloads: 295
Authors Jonas Grönberg
Description

bushel

Bushel is a Dependency Injection (DI) framework, written especially for the Ceylon programming language.

Bushel features the things you normally expect from modern Java DI frameworks, like

  • annotation-driven autowiring of components, and
  • qualifiers (Java CDI style)

The goal is to provide familiar and proven Java DI concepts in a more ceylonic way, primarily utilizing the expressive type system of Ceylon.

intro

Consider the Bushel scanAnnotated function that can scan one or several packages for components to be managed by a container.

Container container = scanAnnotated<ComponentAnnotation> {
    `package se.westshed.pump`
};

Then, consider the following components residing in the package, handed to the container:

component
Heater heater() => ElectricHeater();

component
class Thermosiphon(Heater heater) satisfies Pump {
    shared actual void pump() {
        if (heater.hot) {
            print("=> => pumping => =>");
        }
    }
}

Doing

Thermosiphon t = container.get<Thermosiphon>();

will get you … a thermosiphon.

Normally, you would ask the container for a pump like this:

Pump pump = container.get<Pump>();
assert(is Thermosiphon pump);

If you suspect that there might be no Pump implementation in the container, then you can write:

Pump? p = container.get<Pump?>();

This also opens up for components having optional dependencies:

class Widget(Pump? pump) {}

qualifiers

Consider that we have two different implementations of the same Heater interface in the container.

component
Heater heater1() => ElectricHeater();

component
Heater heater2() => ManualHeater();

component
class Thermosiphon(Heater heater) satisfies Pump {
    shared actual void pump() {
        if (heater.hot) {
            print("=> => pumping => =>");
        }
    }
}

In this case, it is impossible for the Bushel container to know, which Heater implementation to use when wiring the heater dependency for the Thermosiphon component. Simply put, we have to provide a hint to the container.

Assume that we want to use the ElectricHeater.

The most type safe way of doing this, is using a Qualifier annotation, provided by the Bushel framework.

"The electric heater qualifier"
shared annotation ElectricHeaterQualifier electricHeater() 
     => ElectricHeaterQualifier();

"The qualifier class for electricHeater."
shared final sealed
annotation class ElectricHeaterQualifier()
        satisfies Qualifier<ElectricHeaterQualifier,Heater> {

    equals(Object that) => that is ElectricHeaterQualifier;
    hash => 0;
}

You can now annotate the ElectricHeater component as well as the heater parameter to be wired, like this to let the Bushel container know about the association:

component
electricHeater
shared Heater heater1() => ElectricHeater();

component
Heater heater2() => ManualHeater();

component
class Thermosiphon(shared electricHeater Heater heater) satisfies Pump {
//...
}

This now holds true:

Thermosiphon t = container.get<Thermosiphon>();
assert(is ElectricHeater heater = t.heater);

The Ceylon type system will ensure that you never accidentally annotate another type but a Heater implementation, because that will give you a compile error.

The Ceylon type system will even let you do this, inferring the right type on the fly.

Heater heater = container.getQualified(electricHeater());
Dependencies
All backends JVM JavaScript
ceylon.collection/1.2.0
ceylon.language/1.2.0
ceylon.logging/1.2.0 shared
ceylon.time/1.2.0
java.base/8 JDK
Usage
  • Import
  • Run from command-line
  • Run from Ant
 import se.westshed.bushel "0.4.0";
$ ceylon run se.westshed.bushel/0.4.0
<property name="ceylon.home" value="…"/>
<property name="ceylon.ant.lib" 
  value="${ceylon.home}/lib/ceylon-ant.jar"/>
<path id="ant-tasks">
  <pathelement path="${ceylon.ant.lib}"/>
</path>
<typedef resource="com/redhat/ceylon/ant/antlib.xml" classpathref="ant-tasks"/>

<target name="run">
  <ceylon-run module="se.westshed.bushel/0.4.0"/>
</target>
Module links Members
Imported By
Browse
Download .car
Download .js
Download source archive
Download module documentation
View API documentation

Ceylon Herd v1.24 Copyright 2012-2021 Red Hat. About