简体   繁体   中英

Spring, Infinispan and JGroups - configuration programmatically

I am using Spring 4.3, Infinispan 9.11 and JGroups 4.0.6. For JGroups I am using xml configuration, in which I have:

<TCPPING async_discovery="true"
         initial_hosts="${jgroups.tcpping.initial_hosts: HOSTS}"
(...)

Let's say I want to keep configuration in xml, however, I need to apply a list of hosts from another (yml) configuration file. A way to go might be to read yml properties from Java (I have that part) and set them somehow to the JGroups configuration.

This is what I've tried so far:

EmbeddedCacheManager cacheManager = new DefaultCacheManager(
            GlobalConfigurationBuilder.defaultClusteredBuilder()
                    .transport()
                    .nodeName(nodeName)
                    .addProperty(JGroupsTransport.CONFIGURATION_FILE, "tcp.xml")
                    .addProperty(JGroupsTransport.CONFIGURATION_STRING, "jgroups.tcpping.initial_hosts: HOSTS")
                    .build(),
            new ConfigurationBuilder()
                    ...
                    .build()
    );

However, configuration string doesn't do the job.

UPDATE. Another attempt:

JGroupsTransport transport = (JGroupsTransport)(cacheManager.getCacheManagerConfiguration().transport().transport());
    TCPPING ping = transport.getChannel().getProtocolStack().findProtocol(TCPPING.class);
    ping.setPortRange(1);
    ping.setInitialHosts(Arrays.asList(new IpAddress("HOST1:PORT1"), new IpAddress("HOST2:PORT2")));

That doesn't seem to be working neither.

如果您具有JGroups JChannel,则可以像这样获取TCPPING: channel.getProtocolStack().findProtocol(TCPPING.class) ,然后调用设置器在其上设置initial_hosts。

As Bela Ban and Altanis indicated, the problem is that Infinispan is calling JChannel.connect() before I am able to modify the transport properties. I've found a workaround though:

public class JGroupsChannelLookupImpl implements JGroupsChannelLookup {

    @Override
    public JChannel getJGroupsChannel(Properties p) {
        JChannel channel = null;
        try {
            channel = new JChannel("tcp.xml");
            TCPPING ping = channel.getProtocolStack().findProtocol(TCPPING.class);
            ping.setInitialHosts(Arrays.asList(HOST1, HOST2, HOST3, ...));
        }
        catch (Exception ex) {
            // do sth with the ex
        }
        Objects.requireNonNull(channel);
        return channel;
    }

(...)

}

Then when creating DefaultCacheManager, instead of loading the config directly from xml, just load channel lookup:

new DefaultCacheManager(
            GlobalConfigurationBuilder.defaultClusteredBuilder()
                    .transport()
                    .nodeName(nodeName)
                    .addProperty(JGroupsTransport.CHANNEL_LOOKUP, JGroupsChannelLookupImpl.class.getName())
                    .build(),
           (...)

Works as expected!

Before digging into Infinispan internals, let me try the easy path.

Do you know all the hosts on application boot time? If so, you can use environmental variable (or a system property) to inject the list of hosts. Just execute java myApp -Djgroups.tcpping.initial_hosts=host1.. .

The other way to do it is to dig into Infinispan internals just like you did. The only problem is that your implementation does this too late (JGroups channel is already initialized at that point). So you would need to inject a view (probably using an INJECT_VIEW protocol, see the manual )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM