Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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;
    }
  }


  

}