Sample change log consumer
Configure
Setup this consumer to print out entries (Grouper 2.3+)
...
in grouper-loader.properties
Code Block |
---|
# note, change "myApp" in configId to be the name of the consumer changeLog.consumer.printTestmyApp.class = edu.internet2.middleware.grouper.changeLog.esb.consumer.PrintTestEsbConsumer # quartz cron, run every minute changeLog.consumer.printTestmyApp.quartzCron = |
Start the loader, do some things in GSH
Code Block |
---|
GrouperSession grouperSession = GrouperSession.startRootSession();
Group group = new GroupSave(grouperSession).assignName("test:testGroup").assignCreateParentStemsIfNotExist(true).save();
addMember("test:testGroup", "GrouperSystem");
delMember("test:testGroup", "GrouperSystem");
|
Wait until the top of the next minute, and see some output in STDOUT
Code Block |
---|
Change log entry: stem -> addStem, null
Change log entry: privilege -> addPrivilege, null
Group add, name: test:testGroup
Change log entry: member -> addMember, null
Change log entry: privilege -> addPrivilege, null
Change log entry: privilege -> addPrivilege, null
Change log entry: privilege -> addPrivilege, null
Change log entry: membership -> addMembership, null
Change log entry: membership -> deleteMembership, null |
PrintTest.java
0 * * * * ?
# el filter to filter events before they reach the consumer
changeLog.consumer.myApp.elfilter = (event.eventType eq 'MEMBERSHIP_UPDATE' || event.eventType eq 'MEMBERSHIP_DELETE' || event.eventType eq 'MEMBERSHIP_ADD') && (event.groupName =~ '^app\\:groups\\:.*$')
changeLog.consumer.myApp.publisher.class = edu.school.it.EsbConsumerForApp
# some ad hoc param for the consumer if needed
changeLog.consumer.myApp.publisher.groupName = a:b:c:Group
|
Code
Code Block |
---|
package edu.school.it;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import edu.internet2.middleware.grouper.SubjectFinder;
import edu.internet2.middleware.grouper.app.loader.GrouperLoaderConfig;
import edu.internet2.middleware.grouper.app.loader.db.Hib3GrouperLoaderLog;
import edu.internet2.middleware.grouper.app.provisioning.GrouperProvisioningProcessingResult;
import edu.internet2.middleware.grouper.changeLog.esb.consumer.EsbEvent;
import edu.internet2.middleware.grouper.changeLog.esb.consumer.EsbEventContainer;
import edu.internet2.middleware.grouper.esb.listener.EsbListenerBase;
import edu.internet2.middleware.grouper.esb.listener.ProvisioningSyncConsumerResult;
import edu.internet2.middleware.grouper.util.GrouperUtil;
import edu.internet2.middleware.subject.Subject;
public class EsbConsumerForApp extends EsbListenerBase {
/** logger */
private static final Log LOG = GrouperUtil.getLog(EsbConsumerForApp.class);
@Override
public boolean dispatchEvent(String eventJsonString, String consumerName) {
// we arent using this method
throw new RuntimeException("Not implemented");
}
@Override
public void disconnect() {
// maybe not needed
}
private Map<String, Object> debugMap = new LinkedHashMap<String, Object>();
@Override
public ProvisioningSyncConsumerResult dispatchEventList(
List<EsbEventContainer> esbEventContainers,
GrouperProvisioningProcessingResult grouperProvisioningProcessingResult) {
// this object maps to daemon (loader) log in database
Hib3GrouperLoaderLog hib3GrouperLoaderLog = this.getEsbConsumer().getChangeLogProcessorMetadata().getHib3GrouperLoaderLog();
// keep track of counts
int countToProcess = 0;
int countToNotProcess = 0;
try {
// add things to this map to print in loader log to show on ui
this.debugMap.put("eventCount", GrouperUtil.length(esbEventContainers));
ProvisioningSyncConsumerResult provisioningSyncConsumerResult = new ProvisioningSyncConsumerResult();
for (EsbEventContainer esbEventContainer : GrouperUtil.nonNull(esbEventContainers)) {
EsbEvent esbEvent = esbEventContainer.getEsbEvent();
// organize things in a "shouldProcess" method
if (shouldProcess(esbEventContainer)) {
countToProcess++;
try {
// note you could batch things if the api to the application supports it for efficiency
processEvent(esbEventContainer);
} catch (RuntimeException e) {
// error handling on each event
String errorMessage = "Error processing event " + esbEvent;
LOG.error(errorMessage, e);
this.debugMap.put("error", errorMessage);
this.debugMap.put("exception", GrouperUtil.getFullStackTrace(e));
// ignore or end?
return provisioningSyncConsumerResult;
}
} else |
Code Block |
/** * Copyright 2014 Internet2 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @author mchyzer * $Id: PrintTest.java,v 1.1 2009-06-10 05:31:35 mchyzer Exp $ */ package edu.internet2.middleware.grouper.changeLog.consumer; import java.util.List; import edu.internet2.middleware.grouper.changeLog.ChangeLogConsumerBase; import edu.internet2.middleware.grouper.changeLog.ChangeLogEntry; import edu.internet2.middleware.grouper.changeLog.ChangeLogLabels; import edu.internet2.middleware.grouper.changeLog.ChangeLogProcessorMetadata; import edu.internet2.middleware.grouper.changeLog.ChangeLogTypeBuiltin; /** * just print out some of the events */ public class PrintTest extends ChangeLogConsumerBase { /** * @see edu.internet2.middleware.grouper.changeLog.ChangeLogConsumerBase#processChangeLogEntries(List, ChangeLogProcessorMetadata) */ @Override public long processChangeLogEntries(List<ChangeLogEntry> changeLogEntryList, ChangeLogProcessorMetadata changeLogProcessorMetadata) { long currentId = -1; //try catch so we can track that we made some progress try { for (ChangeLogEntry changeLogEntry : changeLogEntryList) { currentId = changeLogEntry.getSequenceNumber(); countToNotProcess++; } // if thiswe are isretrying afailures, groupthen addreturn actionthe andlast categorysuccess if (changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.GROUP_ADD)) { provisioningSyncConsumerResult.setLastProcessedSequenceNumber(esbEventContainer.getSequenceNumber()); } //print the namereturn fromprovisioningSyncConsumerResult; the entry } finally { SystemdebugMap.out.printlnput("Group add, name: " countToProcess", countToProcess); debugMap.put("countToNotProcess", countToNotProcess); String debugMapString = GrouperUtil.mapToString(this.debugMap); + changeLogEntryLOG.retrieveValueForLabel(ChangeLogLabels.GROUP_ADD.name))debug(debugMapString); // save the debug map in the database } else if (changeLogEntryhib3GrouperLoaderLog.equalsCategoryAndAction(ChangeLogTypeBuiltin.GROUP_DELETE)) {appendJobMessage(debugMapString); } } private void processEvent(EsbEventContainer esbEventContainer) { EsbEvent esbEvent = esbEventContainer.getEsbEvent(); //print Get the nameuserName from the changelog entry String userName = esbEvent.getSubjectId(); // Try to find userName in LDAP System.out.println("Group delete, name: " Subject ldapSubject = SubjectFinder.findByIdAndSource(userName, "ldap", false); // If not in LDAP, don't try to proceed. // This will catch group membership records that are not actually "subjects" if (ldapSubject == null) { return; } Hib3GrouperLoaderLog hib3GrouperLoaderLog += changeLogEntrythis.retrieveValueForLabelgetEsbConsumer(ChangeLogLabels.GROUP_DELETE.name)); ).getChangeLogProcessorMetadata().getHib3GrouperLoaderLog(); // Otherwise, proceed } else if (changeLogEntry.equalsCategoryAndAction(ChangeLogTypeBuiltin.GROUP_UPDATE String login = userName + "@school.edu"; // Check if the user already exists AppUser appUser = null; appUser = someLogicToGetUser(login); switch (esbEventContainer.getEsbEventType()) { case MEMBERSHIP_DELETE: if (appUser != null) { //print the name from the entry hib3GrouperLoaderLog.addDeleteCount(1); System.out.println("Group update, name: " deleteUser(login); } break; case + changeLogEntry.retrieveValueForLabel(ChangeLogLabels.GROUP_UPDATE.name)MEMBERSHIP_ADD: case MEMBERSHIP_UPDATE: boolean isUpdate = false; // Create a new Box user + ", property: " +if changeLogEntry.retrieveValueForLabel(ChangeLogLabels.GROUP_UPDATE.propertyChanged) (appUser == null) { appUser = createUser(login); + ", from: '" + changeLogEntryhib3GrouperLoaderLog.retrieveValueForLabel(ChangeLogLabels.GROUP_UPDATE.propertyOldValue)addInsertCount(1); } else { + "', to: '" + changeLogEntry.retrieveValueForLabel(ChangeLogLabels.GROUP_UPDATE.propertyNewValue) + "'"); // Ensure existing user is active if (activateUser(appUser)) { isUpdate = true; } else { } // Try to add schoolMail values as aliases to user Set<String> schoolMail System.out.println("Change log entry: " + changeLogEntry.getChangeLogType().getChangeLogCategory() + = ldapSubject.getAttributeValues("schoolMail"); if (schoolMail != null) { if (setAliases(schoolMail, login, appUser)) { isUpdate = true; } } " -> " +if changeLogEntry.getChangeLogType().getActionName() + ", " + changeLogEntry.getId()isUpdate) { hib3GrouperLoaderLog.addUpdateCount(1); } break; default : //we successfully processed this record throw new RuntimeException("Not expecting event type: " + esbEventContainer.getEsbEventType()); } } }private catchboolean shouldProcess(ExceptionEsbEventContainer eesbEventContainer) { // changeLogProcessorMetadata.registerProblem(e, "Error processing record", currentId); generally the ESB config in loader will filter events appropriately, if not, do that here //we made it to this -1 e.g. the below can easily be dont in grouper-loader.properties for this consumer. This is just an example EsbEvent esbEvent return currentId-1= esbEventContainer.getEsbEvent(); } switch (esbEventContainer.getEsbEventType()) { case MEMBERSHIP_ADD: case MEMBERSHIP_DELETE: if (currentId == -1) {case MEMBERSHIP_UPDATE: throw new RuntimeException("Couldnt process any records" String groupName = GrouperLoaderConfig.retrieveConfig().propertyValueStringRequired("changeLog.consumer.app.grouperGroupIdPath"); return StringUtils.equals(esbEvent.getGroupName(), groupName); } default: return currentId;false; } } } |