Skip to content

InstructionHandler API

The net.solarnetwork.node.reactor.InstructionHandler API is implemented by services that want to respond to and handle instructions in SolarNode.

package net.solarnetwork.node.reactor;

public interface InstructionHandler {

    /**
     * Test if a topic is handled by this handler.
     *
     * @param topic
     *        the topic
     * @return {@literal true} only if this handler can execute the job for the
     *         given topic
     */
    boolean handlesTopic(@Nullable String topic);

    /**
     * Process an instruction.
     *
     * @param instruction
     *        the instruction to process
     * @return the status for the instruction, or {@code null} if the
     *         instruction was not handled
     */
    @Nullable
    InstructionStatus processInstruction(Instruction instruction);

}
package net.solarnetwork.node.setup.example;

import java.time.Instant;
import java.util.Map;
import net.solarnetwork.node.reactor.Instruction;
import net.solarnetwork.node.reactor.InstructionHandler;
import net.solarnetwork.node.reactor.InstructionStatus;
import net.solarnetwork.node.reactor.InstructionUtils;

public class ExampleHandler implements InstructionHandler {

    @Override
    public boolean handlesTopic(@Nullable String topic) {
        return InstructionHandler.TOPIC_SYSTEM_CONFIGURE.equals(topic);
    }

    @Override
    public @Nullable InstructionStatus processInstruction(Instruction instruction) {
        // verify we handle this topic
        if ( instruction == null || !handlesTopic(instruction.getTopic()) ) {
            return null;
        }

        // validate the service parameter == "example"
        final String service = instruction.getParameterValue(InstructionHandler.PARAM_SERVICE);
        if ( !"example".equals(service) ) {
            return null;
        }

        // a real handler would now do something useful, and then return the status
        return InstructionUtils.createStatus(instruction, InstructionState.Completed, Instant.now(),
                Map.of(InstructionHandler.PARAM_SERVICE_RESULT, "ok"));
    }
}
<service interface="net.solarnetwork.node.reactor.InstructionHandler">
    <service-properties>
        <entry key="instruction">
            <list>
                <value>#{T(net.solarnetwork.node.reactor.InstructionHandler).TOPIC_SYSTEM_CONFIGURE}</value>
            </list>
        </entry>
    </service-properties>
    <bean class="net.solarnetwork.node.setup.example.ExampleHandler"/>
</service>

The API has just two methods to be implemented. The handlesTopic(String) method needs to return true for any instruction topic the handler supports. The processInstruction(Instruction) method does the work of executing a given Instruction.

Even though a handler might return true from handlesTopic() for a given topic, it might not actually support executing a specific Instruction with that topic. A good example of this is the SetControlParameter instruction topic, which expects a parameter named after the Control ID the instruction is meant to operate on. There could be many handler component instances active in SolarNode when such an instruction arrives, but only one which actually has responsibility for the given Control ID. SolarNode will call the processInstruction() method on each handler instance in an undefined order, and stop after the first one that returns a non-null InstructionStatus object.

Tip

A handler should return null from processInstruction() if it cannot claim responsibility for the instruction's intended target.