We store the configuration data as json string in database, please check Merge JSON Objects: Jackson + BeanUtils.copyProperties to learn how to use jackson and spring BeanUtils to merge two objects.But one issue is that the class is getting bigger and bigger: it contains fields, their getter, setters, toString, hashCode, equals and extractXXX methods which returns Nonnull value - it read value from database, if not exists, either return coded default value or default value from from property file.The SolutionLombok comes to rescue. All we need is to add the @Data annotation, it will generate getter, setter, toString, hashCode, equals. This reduces lines of the class from 300+ to about 100.Also we use SpringContextBridge to read default value from property file if the field isn't set in db.

The problemWe are evolving our application from single-purpose to multi-tenant application.The solutionWe use LDAP to authenticate user and define different LDAP Group for different roles in different environment for different sub-application.In login page, user selects what sub-applications to login. The application will call LDAP to do authentication, which will return what what groups user belongs to. Then the application will check the group-mapping to decide whether user can access this application and what roles user should have.We also store the sub-application name in the session, so it can be used later.

We store supported Applications - the application name and the mapping of application's ldap groups in database.

We change server code to use the EmbeddedSolrRepositery. - So there is only little change to existing code.

DataSyncService.copyMessagesFromSolrCloudToEmbeddedSolr deletes expired data from embedded Solr and then copies (only) updated/new data from solr cloud to embeddedSolr. - it ignores data that already exists(with same id and _version_ values).

It's already be called in the ContextLoaderListener so it copies all data from solrcloud to embedded Solr before application startup finishes.

It's also a scheduled task - it will be called periodically.

Here we use SchedulingConfigurer - not @Scheduled because we want to make the interval configurable and changeable. - @Scheduled only supports read value from property file, but doesn't support to call bean method.

Also admin application can change the configuration to enable/disable embedded solr and change the frequency of sync.

OverviewCreate custom data transformer to remove fields and remove field from json data in Solr.The ProblemWe store campaign message in Solr. One type of campaign is voucher. We return this user's voucher and other data based on user's accountId.To support this, we add one searchable field: accountIds which includes all accountIds for this campaign. Add another field: details field which is a json string (mapping to java class) and non-searchable. It includes vouchers properties - a mapping from accountId to voucherCode.-- We choose this approach to be consistent with existing data and make server code simpler.accountIds and details.vouchers fields are big, and when return to client, actually we only need c this user's voucherCode.The SolutionExcluding one fieldWe can build only fl to only include all fields except accountIds. - This is kind of cumbersome, and every time we add a new field, we have to change the fl in SolrQuery.[SOLR-3191] field exclusion from fl is promising, but it's not merged into Solr release.So we create a data transformer which supports the following params:removeFields - what fields to removeExample: removeFields=accountIds,field1,field2removeOthersVoucher - enable the feature if it's trueIf removeOthersVoucher is true:If accountId is empty, then remove all voucherCodes from details field.If accountId is not empty, then remove all voucherCodes except accountId's voucher.How to uses itfl=*,[removeFeilds]&removeFields=accountIds&removeOthersVoucher=true&accountId=account1Writing Custom Data TransformerWe use Jackson ObjectMapper to deserialize details field from String to Map<String, Object>.