Project

General

Profile

If i use ConfigSQLRepository, properties in init.properties file does not work.

Zhirong Zou
Added about 4 years ago

If i configure --tigase-config-repo-class = tigase.conf.ConfigSQLRepository in init.properties, in the table tigase_configuration, there will be a key has two values, one is which i configure in init.properties, and the other is the component default value.

e.g.

I configure http api conponent in init.properties like this:

--comp-name-1 = rest

--comp-class-1 = tigase.http.rest.RestMessageReceiver

rest/port[I] = 8888

Then the port property of rest component will be inserted into the table tigase_configuration twice with two values like this:

mysql> select * from tigase_configuration where component_name="rest" and key_name="port";             
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| component_name | key_name | value | cluster_node | key_node | flag    | value_type | last_update         |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| rest           | port     | 8088  |              |          | DEFAULT | I          | 2014-11-03 12:14:20 |
| rest           | port     | 8080  | localhost    |          | DEFAULT | I          | 2014-11-03 12:16:09 |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+

The first record is the value of my configuration, and the second record is the default value 8080 that hard-coded in the HttpServer.class, it cause my configuration failure.

And I found some relevant information in file logs/tigase.log.0, as follows:

2014-11-03 13:26:38.165 [main]             ConfiguratorAbstract.setup()       CONFIG:   Setting up component: rest
2014-11-03 13:26:38.173 [main]             ConfiguratorAbstract.setup()       CONFIG:   Component rest defaults: {component-id=rest@localhost, def-hostname=localhost, admins=[Ljava.lang.String;@615fd9fd, scripts-dir=scripts/admin, command/ALL=ADMIN, max-queue-size=466, scheduler-threads=1, incoming-filters=tigase.server.filters.PacketCounter, outgoing-filters=tigase.server.filters.PacketCounter, api-keys=[Ljava.lang.String;@5be0a2fc, port=8080, context=/rest, context-file-path=etc/tigase-http-context.xml, use-local-server=true, rest-scripts-dir=scripts/rest}
2014-11-03 13:26:38.173 [main]             ConfiguratorAbstract.setup()       CONFIG:   Component rest configuration: {/port=8088, /admins=[Ljava.lang.String;@78ec7d83, /api-keys=[Ljava.lang.String;@6e24617a, /component-id=rest@localhost, /context=/rest, /context-file-path=etc/tigase-http-context.xml, /def-hostname=localhost, /incoming-filters=tigase.server.filters.PacketCounter, /max-queue-size=466, /outgoing-filters=tigase.server.filters.PacketCounter, /rest-scripts-dir=scripts/rest, /scheduler-threads=1, /scripts-dir=scripts/admin, /use-local-server=true, command/ALL=ADMIN, component-id=rest@localhost, def-hostname=localhost, admins=[Ljava.lang.String;@615fd9fd, scripts-dir=scripts/admin, max-queue-size=466, scheduler-threads=1, incoming-filters=tigase.server.filters.PacketCounter, outgoing-filters=tigase.server.filters.PacketCounter, api-keys=[Ljava.lang.String;@5be0a2fc, port=8080, context=/rest, context-file-path=etc/tigase-http-context.xml, use-local-server=true, rest-scripts-dir=scripts/rest}

In Component rest configuration log, the port property appears twice, that is /port=8088 and port=8080, the former is my configuration.

The following is my personal opinion.

In ConfiguratorAbstract.init(String[] args) method, the properties in init.properties file are saved to the SQL Repository in table tigase_configuration.

        for (String prop : initSettings) {
            ConfigItem item = configRepo.getItemInstance();

            item.initFromPropertyString(prop);
            configRepo.addItem(item);
        }

At this time, only one record in the table tigase_configuration.

mysql> select * from tigase_configuration where component_name="rest" and key_name="port";             
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| component_name | key_name | value | cluster_node | key_node | flag    | value_type | last_update         |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| rest           | port     | 8088  |              |          | DEFAULT | I          | 2014-11-03 12:14:20 |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+

In ConfiguratorAbstract.setup(Configurable component) method, the properties that not configured in init.properties file will be saved to the SQL Repository in table tigase_configuration.

        String compId = component.getName();

        log.log(Level.CONFIG, "Setting up component: {0}", compId);

        Map<String, Object> prop = null;

        try {
            prop = configRepo.getProperties(compId);
        } catch (ConfigurationException ex) {
            log.log(Level.WARNING,
                    "Propblem retrieving configuration properties for component: " + compId, ex);

            return;
        }

        Map<String, Object> defs = component.getDefaults(getDefConfigParams());

        log.log(Level.CONFIG, "Component {0} defaults: {1}", new Object[] { compId, defs });

        Set<Map.Entry<String, Object>> defs_entries = defs.entrySet();
        boolean                        modified     = false;

        for (Map.Entry<String, Object> entry : defs_entries) {
            if (!prop.containsKey(entry.getKey())) {
                prop.put(entry.getKey(), entry.getValue());
                modified = true;
            }    // end of if ()
        }      // end of for ()

At this time, there will be two record in the table tigase_configuration.

mysql> select * from tigase_configuration where component_name="rest" and key_name="port";             
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| component_name | key_name | value | cluster_node | key_node | flag    | value_type | last_update         |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| rest           | port     | 8088  |              |          | DEFAULT | I          | 2014-11-03 12:14:20 |
| rest           | port     | 8080  | localhost    |          | DEFAULT | I          | 2014-11-03 12:16:09 |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+

The problem lies in this line

prop = configRepo.getProperties(compId);

It read properties from SQL Repository

+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| component_name | key_name | value | cluster_node | key_node | flag    | value_type | last_update         |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+
| rest           | port     | 8088  |              |          | DEFAULT | I          | 2014-11-03 12:14:20 |
+----------------+----------+-------+--------------+----------+---------+------------+---------------------+

The key_node field is empty, not null. So the ConfigItem field nodeName is "", not null.

In ConfigItem.getConfigKey() method, if the nodeName field is not null, is will return nodeName + "/" + keyName, if the nodeName field is "", is will return "" + "/" + keyName. For example "/port".

    public String getConfigKey() {
        return ((nodeName != null)
                        ? nodeName + "/"
                        : "") + keyName;
    }

To solve this problem, my personal recommendation is to modify the method ConfigItem.getConfigKey() like this:

    public String getConfigKey() {
        return ((nodeName != null && nodeName.length() > 0)
                        ? nodeName + "/"
                        : "") + keyName;
    }

But now, my version is tigase-server-5.2.2-b3463, how can I solve this problem?


Replies (3)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 4 years ago

I am sorry for the delay with response to your question. I was away for last few days, hence lack of response.

Thank you very much for all the details and deep analysis of the problem. I think you might be correct with your suggested solution. Have you tried to run Tigase with your modification of the code? Does it solve your problem?

The thing with ConfigSQLRepository is, that it was implemented a few years ago and almost never used. You are actually, the first person trying it and reporting any problem. Therefore, you are the best person to give us recommendations and suggestions about it.

If your code modification solves the problem you are experiencing, please let me know. We can include the fix in the Tigase code, so it future releases it won't happen again. If this does not solve the problem completely, please let me know and we will help you to find optimal solution.

Added by Zhirong Zou about 4 years ago

I have tried to run Tigase with my modification of the code and it does solve my problem.

But i think the best way to solve this problem is modifying the method ConfigItem.set(String clusterNode_m, String compName_m, String nodeName_m, String key_m, Object value_m, FLAGS flag_m).

    public void set(String clusterNode_m, String compName_m, String nodeName_m,
            String key_m, Object value_m, FLAGS flag_m) {
        if (clusterNode_m != null) {
            this.clusterNode = clusterNode_m;
        }
        if (compName_m != null) {
            this.compName = compName_m;
        }
        if (nodeName_m != null && nodeName_m.length() > 0) {
            this.nodeName = nodeName_m;
        }
        if (key_m != null) {
            this.keyName = key_m;
        }
        if (value_m != null) {
            this.value = value_m;
        }
        if (flag_m != null) {
            this.flag = flag_m;
        }
        lastModificationTime = System.currentTimeMillis();
    }

It does works!

Perhaps there are other better solution, if there is, please tell me.

The thing with ConfigSQLRepository is, that it was implemented a few years ago and almost never used.

I want to use ConfigSQLRepository in my cluster. If this issue has been there, is there any better implementations to replace ConfigSQLRepository in cluster mode? ConfigurationCache or ConfigXMLRepository? Or implement one of my own?

What is your proposal?

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 4 years ago

I recommend and suggest to use the standard configuration way for the Tigase in a cluster mode. This is based on the init.properties file. This is what we use and all our customers use as well. Benefit of using this file is, that in typical setup, it is identical for all cluster nodes. So you can even put it on to some shared file system or have automated scripts deploying config changes.

As I said before, the SQL based configuration was implemented a long time ago and almost never used. Only one customer used this feature years ago and possible they still use it, but on some old version.

    (1-3/3)