As some of you have asked for more fluent API in Infinispan configuration I have completed a proposal for a review. We are not going to remove current setters and getters, setters will be deprecated in 5.0 and removed in Infinispan 6.0 leaving only fluent API for setter. I have myself been rather suprprised how much easier is it to use fluent API than the old flat API approach. Configuration classes are organized into logical units reflecting configuration structure described in http://docs.jboss.org/infinispan/4.2/apidocs/config.html
Here is a sample setting GlobalConfiguration:
GlobalConfiguration gc = new GlobalConfiguration(); GlobalJmxStatisticsConfig jmxStatistics = gc.configureGlobalJmxStatistics(); jmxStatistics.setAllowDuplicateDomains(true).setEnabled(true); TransportConfig transport = gc.configureTransport(); transport.setClusterName("blah").setMachineId("id").setRackId("rack").setStrictPeerToPeer(true); ExecutorFactoryConfig<ExecutorFactory> asyncTransportExecutor = gc.configureAsyncTransportExecutor(); asyncTransportExecutor.setClass(DefaultExecutorFactory.class).addProperty("blah", "blah");
Configuration c = new Configuration(); LockingConfig locking = c.configureLocking(); locking.setIsolationLevel(IsolationLevel.REPEATABLE_READ).setLockAcquisitionTimeout(1000L); ExpirationConfig expiration = c.configureExpiration(); expiration.setLifespan(1000L).setMaxIdle(1000L); EvictionConfig eviction = c.configureEviction(); eviction.setMaxEntries(1000).setStrategy(EvictionStrategy.LRU); ClusteringConfig clustering = c.configureClustering(); clustering.configureAsync().setAsyncMarshalling(true).setReplQueueInterval(1000L); clustering.configureHash().setRehashEnabled(true).setRehashRpcTimeout(1000L); clustering.configureL1().setEnabled(true).setOnRehash(true).setLifespan(1000L); clustering.configureStateRetrieval().setAlwaysProvideInMemoryState(true).setInitialRetryWaitTime(1000L); clustering.setMode(CacheMode.DIST_SYNC); LoadersConfig loaders = c.configureLoaders(); loaders.setPassivation(true).setPreload(true).setShared(false); FileCacheStoreConfig fcsc = new FileCacheStoreConfig(); fcsc.configureAsyncStore().setEnabled(true).setFlushLockTimeout(1000L); fcsc.configureSingletonStore().setPushStateTimeout(1000L).setSingletonStoreEnabled(true); loaders.addCacheLoaderConfig(fcsc);
I have still some final details to complete, mark deprecated methods, write javadoc before I integrate these changes in 5.0 branch. In the meantime you can review a complete proposal here https://github.com/vblagoje/infinispan/commit/d6aff87
Related JIRA is https://issues.jboss.org/browse/ISPN-911
Convention is that a fluent API doesn't include the word set, e.g.
In order to support this naming convention our configuration beans (inner classes of Configuration and GlobalConfiguration) would have to have "duplicate" setter methods: the current ones, and these fluent API version setters. It is not the end of the world to have this duplication, I am not just sure if it is worth it? :-)
My first thought was aligned with Pete, thinking "remove those set", but now I have no strong opinion. It's nice that IDE's help with the builder, but also having a prefix "set" isn't bad at least it hides those meaningless methods such as join/wait/equals. So I'd prefer to avoid code duplication, but I'm fine with both.
In the first paragraph, by "removing the setters", you mean on the Configuration class only right?
Will it be possible to use pre-configured services, like if I have already a Transport instance, to have a new CacheManager started by using it?
I will need to be able to pass both an existing Transport instance and an existing TransactionManager, but I can ask for that in a different JIRA.
To make sure this reaches bigger audience, Alpha3 will allow config like:
TransportConfig transport = gc.configureTransport(); transport.clusterName("blah").machineId("id").rackId("rack").strictPeerToPeer(true); ExecutorFactoryConfig<ExecutorFactory> asyncTransportExecutor = gc.configureAsyncTransportExecutor(); asyncTransportExecutor.factory(DefaultExecutorFactory.class).addProperty("blah", "blah");
As suggested in Vladimir's pull, it'd be great if you could be further shortened to :
gc.configureTransport().clusterName("blah").machineId("id").rackId("rack").strictPeerToPeer(true) .configureAsyncTransportExecutor().factory(DefaultExecutorFactory.class).addProperty("blah", "blah");
Note that that's a single line.
And in fact, after further thought, the fact that gc is already GlobalConfiguration, I don't think there's a need to repeat "configure". You could simply do:
gc.transport().clusterName("blah").machineId("id").rackId("rack").strictPeerToPeer(true) .asyncTransportExecutor().factory(DefaultExecutorFactory.class).addProperty("blah", "blah");
Much nicer - As said before, these are further refinements that we could add for Beta1?
Galder, I thought a bit more about your suggestion and if it makes sense for others as well we can do it. In your proposal every configuration bean has access to configuration root's children beans. In another words, no matter which configuration bean one has a reference to he/she can invoke transport(), globalJmxStatistics() and then invoke setters and/or navigate to other configuration beans.
Galder, I thought a bit more about your suggestion and if it makes sense for others as well we can do it. In your proposal every configuration bean has access to configuration root's children beans
So each config to inherit root? This may polute the current context with too many methods (harder code compleation) and make it harder for the user to see what configuration options are specific to the current context. -1.
Not inherit from root but implement, in GlobalConfiguration: transport(), globalJMXStatistics(), serialization() and so on. In Configuration, each bean would implement clustering(), expiration(), eviction() and so on....you get the gist of it. Implementing beans would get a hold of ancestors references and return appropriate bean....somethign like that!
By inherit I mean e.g. TransportConfig to inherit from Configuration. This way TransportConfig.clustering()/expiration() etc are there.
The other approach is to duplicate clustering()/expiration() etc methods in TransportConfig - not desirable IMO. Actually -1 for supporting TransportConfig.clustering() for the reasons mentioned in the previous post.