Covalent

A lightweight Java component model and runtime container.

View the Project on GitHub opales-org/covalent

Home | Previous: Covalent Tutorial | Next: Step 2: Services

In this step you write one component, deploy it in a container, start the container, and stop it.

The Ingredients

A managed Covalent component has two parts.

The component type is a tag interface: an empty interface annotated with @Component. It is the public identity of the component. At runtime there is at most one instance of a given component type.

@Component
public interface Hello {
}

The implementation is a class annotated with @Implementation that implements the component type. It holds the behavior.

@Implementation
public static final class HelloImpl implements Hello {

The implementation can declare lifecycle callbacks. A method annotated with @Activation is called when the component is activated, and a method annotated with @Removal is called when the component is removed. There are also @Initialization and @Passivation; we will come back to them in step 5.

@Activation
public void sayHello() {
    System.out.println("Hello from a Covalent component!");
}

The Container

Components live in a container. Covalent.main is the default container, and the simplest choice for an application that needs only one.

Starting an application takes two calls: deploy the implementations, then start the container.

container.deployComponents(HelloImpl.class);
StartupReport report = container.start();

start() instantiates, initializes and activates every deployed component, and returns a StartupReport that tells whether the startup was healthy, degraded or failed. stop() passivates, removes and undeploys them, and returns the equivalent ShutdownReport.

The Complete Program

package tutorial;

import org.opales.covalent.Covalent;
import org.opales.covalent.container.ContainerStatus;
import org.opales.covalent.container.CovalentContainer;
import org.opales.covalent.container.StartupReport;
import org.opales.covalent.container.component.annotations.Component;
import org.opales.covalent.container.component.annotations.Implementation;
import org.opales.covalent.container.lifecycle.Activation;
import org.opales.covalent.container.lifecycle.Removal;

public final class Step1 {

    @Component
    public interface Hello {
    }

    @Implementation
    public static final class HelloImpl implements Hello {

        @Activation
        public void sayHello() {
            System.out.println("Hello from a Covalent component!");
        }

        @Removal
        public void sayGoodbye() {
            System.out.println("Goodbye from a Covalent component!");
        }
    }

    public static void main(final String[] args) {
        CovalentContainer container = Covalent.main;
        try {
            container.deployComponents(HelloImpl.class);
            StartupReport report = container.start();
            System.out.println("Startup status: " + report.getStatus());
            if (report.getStatus() != ContainerStatus.healthy) {
                throw new IllegalStateException("Covalent startup failed: " + report.getStatus());
            }
        } finally {
            if (container.isStarted()) {
                container.stop();
            }
        }
    }
}

Its output:

Hello from a Covalent component!
Startup status: healthy
Goodbye from a Covalent component!

The greeting is printed during start(), when the component is activated. The farewell is printed during stop(), when it is removed.

Note: The program stops the container in a finally block, guarded by container.isStarted(). stop() throws an exception when the container is not started; without the guard, a failure during deployment or startup would be hidden behind that second exception.

What You Learned

Reference: Component Type, Implementation, Covalent Application Lifecycle.

Home | Previous: Covalent Tutorial | Next: Step 2: Services