Hello World in Kompics
This section describes the simplest possible Kompics program, the well-known Hello World.
A proper introduction can be found in the Tutorial.
Setup
Set up a new sbt or maven project and follow the instructions in the Getting Started section to include the necessary dependencies. For this simple example the kompics-core
or kompics-scala
modules will be sufficient.
Hello World Component
This very simple component contains but a single handler, which is executed when a Start
event is triggered on the control
port. Start
events are part of Kompic’s component lifecycle and always need to be triggered on a component exactly once to get it to handle events. A component that is never started is considered paused and will queue up events on its ports, but never execute them.
- Java
-
package jexamples.helloworld; import se.sics.kompics.ComponentDefinition; import se.sics.kompics.Handler; import se.sics.kompics.Start; import se.sics.kompics.Kompics; public class HelloComponent extends ComponentDefinition { { Handler<Start> startHandler = new Handler<Start>() { @Override public void handle(Start event) { System.out.println("Hello World!"); Kompics.asyncShutdown(); } }; subscribe(startHandler, control); } }
- Scala
-
package sexamples.helloworld; import se.sics.kompics.sl._ class HelloComponent extends ComponentDefinition { ctrl uponEvent { case _: Start => { System.out.println("Hello World!"); Kompics.asyncShutdown(); } } }
Do not forget to subscribe Kompics handlers to ports in the Java version! It is the most common mistake, and it is very easy to overlook when debugging. In the Scala version, this happens automatically with uponEvent
, but if you use handler
instead to create a handler without automatic subscription, it may still become an issue later.
Main
The main
method is very simple and only starts the Kompics framework by calling Kompics.createAndStart
with the class of the root component. It also automatically sends a Start
event to the component once the constructor has finished.
- Java
-
package jexamples.helloworld; import se.sics.kompics.Kompics; public class Main { public static void main(String[] args) throws InterruptedException { Kompics.createAndStart(HelloComponent.class); Kompics.waitForTermination(); } }
- Scala
-
package sexamples.helloworld; import se.sics.kompics.sl._ object Main { def main(args: Array[String]): Unit = { Kompics.createAndStart(classOf[HelloComponent]); Kompics.waitForTermination(); } }
Compiling and Running
To compile the source code use:
sbt compile
To run the project from within sbt, execute:
runMain jexamples.helloworld.Main
runMain sexamples.helloworld.Main
This is all. Say hello to Kompics ;)
Logging
Kompics has built-in logging support, which adds context information to the logging output, such as what state the component is in and what its unique id is. You can access the provided SLF4J logger via the logger
field, or its Scala Logging wrapper via the log
field.
In order to make use of these features, a mapped diagnostic context (MDC) capable logging backend is required, such as Logback Classic, for example.
Logback requires a configuration file to work. Adding a simple src/main/resources/logback.xml
file to the project will configure the logging system, in this case such that all MDC information is printed:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %highlight(%-5level) %logger{1} [%thread] %X %n - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
It is also possible to add custom context information to a particular component, by using either loggingContextPut
for potentially transient values, or loggingContextPutAlways
for context values that definitely span the life-time of the component.