Component Implementation - Lesson 2 - Configuration

It might be hard to tell what the first important thing you should do with your new component implementation. Different developers may have a different view on this. It seems to me however that it is always a good idea to give to your component a way to configure it and provide some runtime settings.

This guide describes how to add configuration handling to your component.

To demonstrate how to implement component configuration let’s say we want to configure which types of packets will be logged by the component. There are three possible packet types: message, presence and iq and we want to be able to configure logging of any combination of the three. Furthermore we also want to be able to configure the text which is prepended to the logged message and to optionally switch secure login. (Secure logging replaces all packet CData with text: CData size: NN to protect user privacy.)

Let’s create the following private variables in our component TestModule:

@ConfigField(desc = "Logged packet types", alias = "packet-types")
private String[] packetTypes = {"message", "presence", "iq"};
@ConfigField(desc = "Prefix", alias = "log-prepend")
private String prependText = "My packet: ";
@ConfigField(desc = "Secure logging", alias = "secure-logging")
private boolean secureLogging = false;

And this is it. Tigase Kernel will take care of this fields and will update them when configuration will change.

The syntax in config.tdsl file is very simple and is described in details in the Admin Guide. To set the configuration for your component in config.tdsl file you have to append following lines to the file inside test component configuration block:

test-module {
  log-prepend = 'My packet: '
  packet-types = [ 'message', 'presence', 'iq' ]
  secure-logging = true
}

The square brackets are used to mark that we set a list consisting of a few elements, have a look at the Admin Guide documentation for more details.

And this is the complete code of the new component module with a modified process(…​) method taking advantage of configuration settings:

@Bean(name = "test-module", parent = TestComponent.class, active = true)
public static class TestModule extends AbstractModule {

  private static final Logger log = Logger.getLogger(TestModule.class.getCanonicalName());

  private Criteria CRITERIA = ElementCriteria.name("message");

  @ConfigField(desc = "Logged packet types", alias = "packet-types")
  private String[] packetTypes = {"message", "presence", "iq"};
  @ConfigField(desc = "Prefix", alias = "log-prepend")
  private String prependText = "My packet: ";
  @ConfigField(desc = "Secure logging", alias = "secure-logging")
  private boolean secureLogging = false;

  @Override
  public Criteria getModuleCriteria() {
    return CRITERIA;
  }

  public void setPacketTypes(String[] packetTypes) {
    this.packetTypes = packetTypes;
    Criteria crit = new Or();
    for (String packetType : packetTypes) {
      crit.add(ElementCriteria.name(packetType));
    }
    CRITERIA = crit;
  }

  @Override
  public void process(Packet packet) throws ComponentException, TigaseStringprepException {
    log.finest(prependText + packet.toString(secureLogging));
  }
}

Of course we can do much more useful packet processing in the process(…​) method. This is just an example code.

Tip

Here we used a setter setPacketType(String[] packetTypes) which is a setter for field packetTypes. Tigase Kernel will use it instead of assigning value directly to a field which gives up opportunity to convert value to different type and update other field - in our case we updated CRITERIA field which will result in change of packet types which for which method void process(…​) will be called.