Home > Articles > Programming > Java

This chapter is from the book

MBean Notification Mechanism

Building a component-based system often requires the ability for the components to communicate between parts of the system, sending important events and state changes. The JMX architecture defines a notification mechanism for MBeans that allows management events or notifications to be sent to other MBeans or management applications.

The JMX notification mechanism is based on the Java event mechanism. It involves listener objects that are registered to the MBeans emitting notifications, called broadcaster MBeans. The broadcaster MBeans send out notification objects to all interested listeners whose notification filters accept the notification's type.

The JMX notification mechanism builds upon the following four classes:

  • Notification

  • NotificationBroadcaster

  • NotificationFilter

  • NotificationListener

The Notification object is a generic event object sent to the listeners when an event occurs. It extends the java.util.EventObject, which is the standard Java event class. The listener object implements the NotificationListener interface that contains one method, handleNotification(). This is a generic event handler used for all JMX notification listeners, regardless of the notification type.

The NotificationBroadcaster interface is implemented by the MBeans emitting management events. The NotificationBroadcaster interface declares methods for registering (addNotificationListener) and unregistering (removeNotificationListener) listeners and an additional method for retrieving the notification metadata (getNotificationInfo). It is important to notice that the notifications sent by the broadcaster MBeans are part of the management interface. The management applications can query the agent for information about what types of notification the MBean emits.

The NotificationFilter interface is passed to the broadcaster MBean as an argument when the listener is registered. The interface contains one method, isNotificationEnabled(), which must always be invoked by the broadcaster MBean before the management event is sent. This allows the object registering as a listener to select which notifications to receive of all the possible notifications the MBean is emitting.

Note

Notifications are part of the MBeans' management interface.

The registering of the listener to the broadcaster MBean is done through the agent layer. As with all the other MBean invocations, the MBean server sits between the consumer and the producer of the notifications. The MBeanServer interface exposes two methods for adding a listener to an MBean, and two for removing the listener. The declarations of the four methods are shown next. Exceptions have been left out for the sake of brevity.

public void addNotificationListener(
        ObjectName name,
        NotificationListener listener,
        NotificationFilter filter,
        Object handback)

public void addNotificationListener(
        ObjectName name,
        ObjectName listener,
        NotificationFilter filter,
        Object handback)

public void removeNotificationListener(
        ObjectName name,
        NotificationListener listener)

public void removeNotificationListener(
        ObjectName name,
        ObjectName listener)

Both the addNotificationListener() method and the removeNotificationListener() method are overloaded to take a listener argument either as a direct implementation of the NotificationListener interface, or an ObjectName reference to a registered listener MBean. If the ObjectName reference is used, the listener MBean must implement the NotificationListener interface.

Next, we will look at each of the notification interfaces in a little more detail.

Notification

The Notification class represents a generic event sent by an MBean. It is a subclass of the standard Java EventObject class that should be familiar to those who have worked with Java's event mechanism before. The Notification class can be used for any type of management event the MBean wants to broadcast, or it can be subclassed to provide more specific event notifications.

The JMX Notification class extends the EventObject class by adding fields for the event's type, a sequence number, time stamp, message, and an optional user data. The type string is used to convey the semantics of the notification and is formed by adding string components separated by dots. This is not to be confused with the Java class type and a fully-qualified classname that is a dot-separated string of package structure. A type string can be freely formed and contain as many parts as necessary. Notice, however, that all type strings prefixed with jmx. are reserved for the JMX implementation. The following are some examples of notification type strings.

MyApp.MyEvent
Acme.Application.User.CreateEvent
Acme.Application.User.RemoveEvent
jmx.modelmbean.general// RESERVED !!

As you can see, the type string can be used to build a hierarchical structure for the different types of management events.

The sequence number can be retrieved from the Notification object by calling the getSequenceNumber() method. This field allows individual notifications to be identified by the receiver, acting as a serial number. The sequence number is valid in the context of a broadcaster MBean instance. Constructing the Notification object requires you to supply the sequence number as an argument.

The getTimeStamp() method allows access to the date and time the notification was sent. The time stamp can also be set in the constructor, but it is also possible to leave the time stamp creation up to the Notification implementation.

In addition to the message field that can be used for an explanation of the notification, the Notification object allows the broadcaster to attach a user data object to the management event. The user data object can contain any additional information the broadcaster wants to relay to its consumers. There are no specific restrictions to what kind of object can be attached to the notification. However, it is probably a good idea to have the user data objects implement the Serializable interface, making it considerably easier for the connectors to send notifications with user data attached to remote management applications.

NotificationBroadcaster and NotificationFilter

The NotificationBroadcaster interface must be implemented by those MBeans broadcasting management events. The interface declares three methods that the MBean implementation must provide. The declaration of the NotificationBroadcaster interface is shown in Listing 3.6.

Listing 3.6 NotificationBroadcaster Interface

package javax.management;
 
public interface NotificationBroadcaster {
 public void addNotificationListener(
      NotificationListener listener,
      NotificationFilter filter,
      Object handback)
     throws IllegalArgumentException;

 public void removeNotificationListener(
      NotificationListener listener)
     throws ListenerNotFoundException;

 public MBeanNotificationInfo[] getNotificationInfo();

}

The addNotificationListener() registers an event consumer with the MBean. It takes a NotificationListener reference as its first argument and two other arguments—the NotificationFilter object and a hand-back object reference.

The removeNotificationListener() method of the NotificationBroadcaster interface removes the given listener instance from the notification broadcaster. If the given listener instance was not found, a ListenerNotFoundException should be thrown.

The last method of the NotificationBroadcaster interface is a method to return the metadata of the broadcaster MBean to the agent. We will take an extensive look at the metadata structures of the JMX architecture in the Chapter 4, "Dynamic MBeans," when we investigate the Dynamic MBeans. The getNotificationInfo() method is part of the metadata that is being passed to the agent. It returns an array of MBeanNotificationInfo objects, each of which describe a notification class emitted from the broadcaster MBean. In turn, each MBeanNotificationInfo object describes all the notification types for the given notification class. Remember that the Notification class can be used to deliver several different types of notifications. It is very easy to get your classes and types mixed up here, so be careful.

The NotificationFilter interface allows the listener to communicate to the broadcaster MBean which notifications it is interested in receiving. The broadcaster MBean may be sending several different types of notifications. The listener can register to receive all or just some of them. When passing the filter to the broadcaster MBean, you can select which events you want to receive and avoid registering for each individual event type separately, or avoid having to handle dozens of notifications from the MBean when you're only interested in one particular type. It is also possible to implement more sophisticated logic in the filter that selects the notifications based on the time stamp, sequence number, or possibly the user data object of the notification.

The NotificationFilter is a very simple interface to implement. It only contains one method, isNotificationEnabled(), which returns a Boolean value true or false, depending on whether the broadcaster MBean should send the given Notification instance to the listener. The declaration of the NotificationFilter interface is shown in Listing 3.7.

Listing 3.7 NotificationFilter Interface

package javax.management;

public interface NotificationFilter 
      extends java.io.Serializable {

 boolean isNotificationEnabled(Notification notif);

}

The broadcaster is required to check the notification against the filter before sending it to the notification consumer. If the filter is a null reference, all notifications from the MBean will be delivered to the registered consumer.

The hand-back object is provided as an argument with the NotificationListener reference when the consumer is registered. It can be used to provide the listener instance an object reference that it can use to retrieve required context information with every broadcast notification. The hand-back object must be stored by the NotificationBroadcaster implementation and passed back to the listener with each notification. In addition, the hand-back object must not be changed by the broadcaster.

The same listener object can be registered more than once to the broadcaster with different hand-back objects. This will cause the listener to receive the notifications as many times as it has registered itself, each time with a different hand-back object.

Broadcaster MBean Example

The implementation of the NotificationBroadcaster interface can become quite complex compared to the usual JavaBeans event mechanism. You need to store a triplet of objects with each added listener— NotificationListener reference, the NotificationFilter reference, and the hand-back object. In addition, you will have to generate the sequence number for each Notification object and remember to invoke the isNotificationEnabled() method of the filter before sending the event to the registered listener.

Luckily, there is a NotificationBroadcasterSupport class available that implements the NotificationBroadcaster interface. You can either have your MBean extend the support class or delegate to it to gain the registration management and notification invocation support. In Listing 3.8, you will use the broadcaster support class to add notifications to the User MBean implementation. The example shows the implementation of the NotificationBroadcaster interface and adds notification to a new management operation remove(). Let's call this new MBean a BroadcastingUser and have it implement a corresponding management interface that extends from the UserMBean interface.

The management interface for the BroadcastingUser is shown in Listing 3.8.

Listing 3.8 BroadcastingUserMBean.java

package book.jmx.examples;


public interface BroadcastingUserMBean extends UserMBean {

  public void remove();
  
}

Remember that the Standard MBean inheritance patterns will expose all properties and operations declared in the ancestor interfaces to the management.

Next, you will write the MBean implementation. Most of the implementation will be inherited from the User class that already implements the attributes and all operations of the MBean, except for the remove() operation. You will use the NotificationBroadcasterSupport class to help implement the NotificationBroadcaster interface. Because you already used up the inheritance tree by extending the User class, you will delegate the NotificationBroadcaster method calls to a support class instance.

The notificationSequence field in the BroadcastingUser class is used for keeping track of the sequence numbers of sent notifications. The implementation of the remove() management operation uses the sendNotification() method of the support class to emit the Notification object. Each Notification object is created with example.user.remove as its type, notificationSequence as its sequence number, and the current BroadcastingUser instance as its source.

Notice that the source reference in the Notification instance will be converted by the agent to represent the ObjectName reference of the broadcaster MBean. This allows the notification consumer to reference the broadcasting MBean through the MBean server and also ensures the decoupling of the Notification objects from the broadcaster MBean. Remember that no direct references to the MBean instances should exist outside the agent. All communications must go through it.

The NotificationBroadcaster is implemented by delegating the functionality of the addNotificationListener() and removeNotificationListener() methods to the notification support object. In addition, you provide the metadata about the notification by returning an MBeanNotificationInfo object from the getNotificationInfo() method.

The complete source for the BroadcastingUser class is provided in Listing 3.9.

Listing 3.9 BroadcastingUser.java

package book.jmx.examples;

import javax.management.*;

public class BroadcastingUser extends User implements
   BroadcastingUserMBean, NotificationBroadcaster {


  // broadcaster support class
  private NotificationBroadcasterSupport broadcaster = 
        new NotificationBroadcasterSupport();
  
  // sequence number for notifications 
  private long notificationSequence = 0;
  
  
  // management operations 
  public void remove() {
    
   broadcaster.sendNotification(
     new Notification(
      "example.user.remove",     // type
      this,              // source
      ++notificationSequence,     // seq. number
      "User " +getName()+ " removed." // message
     )
   );
  }
  

  // notification broadcaster implementation 
   
  public void addNotificationListener(
      NotificationListener listener, 
      NotificationFilter filter,
      Object handback) {
     
   broadcaster.addNotificationListener(
        listener, filter, handback);  
  }
                  
  public void removeNotificationListener(
      NotificationListener listener)
      throws ListenerNotFoundException {
   
   broadcaster.removeNotificationListener(listener);     
  }

  public MBeanNotificationInfo[] getNotificationInfo() {
   return new MBeanNotificationInfo[] {
    new MBeanNotificationInfo(
     new String[] 
      { "example.user.remove" }, // notif. types
     Notification.class.getName(), // notif. class
     "User Notifications."     // description
    )
   };
  }

}

The remove() operation implementation was left empty apart from the notification send implementation. In a real-world case, you would add any necessary code to clean up the database records if a user was removed from the system.

NotificationListener

The NotificationListener is implemented by all classes wanting to act as management event consumers. The NotificationListener interface is a generic listener interface that can be used to receive several different types of notifications from different sources.

The interface defines only one method, handleNotification, which is declared as follows:

public void handleNotification(Notification notification,
                Object handBack)

The same listener can be registered to receive notifications from different notification broadcasters. In addition, the same listener can receive several different types of notifications from the same notification broadcaster, depending on the notification filter. There are several ways for the implementation of the NotificationListener interface to determine the source and meaning of the received notifications.

  • Use the getSource() method of the Notification class to determine the source of the notification. The object returned by the getSource() method is an ObjectName reference to the MBean that broadcast the notification.

  • Use the getType() method of the Notification class to retrieve the notification type information. This is a dot-separated string of the notification's semantic information.

  • Use the handBack object to map the notifications to a registered listener. The handBack object is guaranteed to be returned to the listener with every notification and can be used to pass any type of context information.

  • Optional use of user data objects. The broadcaster can attach additional data to the notifications. The user data can be retrieved via the getUserData() method call of the Notification class.

Notification Listener Example

Listing 3.10 will show how to register and receive the notifications from the BroadcastingUser MBean. You will register three instances of the BroadcastingUser class to the agent and add a listener object to each one of them, implemented as an inner class UserListener in the code. The notification listener registration is accompanied by a filter object and implemented as an inner class UserFilter, which only accepts notifications of type example.user.remove to be sent to the listener. In addition, you will use the ObjectName instance as a hand-back object with each registration. You will use the hand-back to reference the notification producer MBean in the listener code to unregister it when a notification to remove the user is received. Normally, you would use the getSource() method of the Notification object to retrieve the ObjectName reference to the broadcaster. Unfortunately, the JMX RI version 1.0 has a bug in how it handles the listener instance that is registered to more than one notification producer. This causes the getSource() to return the same ObjectName reference with each notification, regardless of which MBean instance sends it. We use the hand-back to work around this quirk in the reference implementation.

Listing 3.10 is the complete code for the ListenerClient class. After registering the MBeans and adding listeners to them, it invokes the remove() method of the BroadcastingUser objects that will cause a notification to be received in the listeners. The listeners will then unregister the MBeans.

Listing 3.10 ListenerClient.java

package book.jmx.examples;

import javax.management.*;
import java.util.List;

public class ListenerClient {

 private NotificationListener listener = null;
 private NotificationFilter filter   = null;
 private MBeanServer server      = null;
  
 public void run() {

  // Find an agent from this JVM. Null argument will
  // return a list of all MBeanServer instances.
  List list = MBeanServerFactory.findMBeanServer(null);
  server  = (MBeanServer)list.iterator().next();
     
  // create the listener and filter instances
  listener = new UserListener(server);
  filter  = new UserFilter();

  // Register three different instances of Broadcasting
  // User MBean to the agent. The single UserListener
  // instance is registered to each MBean. MBean
  // ObjectName is used as a hand-back object.
  try {
   ObjectName john = new ObjectName("user:name=John");
   ObjectName mike = new ObjectName("user:name=Mike");
   ObjectName xena = new ObjectName("user:name=Xena");
   Attribute jName = new Attribute("Name", "John");
   Attribute mName = new Attribute("Name", "Mike");
   Attribute xName = new Attribute("Name", "Xena");
  
   server.registerMBean(new BroadcastingUser(), john);
   server.registerMBean(new BroadcastingUser(), mike);
   server.registerMBean(new BroadcastingUser(), xena);

   server.addNotificationListener(
        john, listener, filter, john);
   server.addNotificationListener(
        mike, listener, filter, mike);
   server.addNotificationListener(
        xena, listener, filter, xena);

   server.setAttribute(john, jName);
   server.setAttribute(mike, mName);
   server.setAttribute(xena, xName);
     
   // Invoke remove on each MBean instance. This
   // will broadcast a notification from the MBean.
   server.invoke(john, "remove", null, null);
   server.invoke(mike, "remove", null, null);
   server.invoke(xena, "remove", null, null);
  }
  catch (JMException e) {
   e.printStackTrace();
  }
 }


 //
 // Notification listener implementation.
 //
 class UserListener implements NotificationListener {
   
  MBeanServer server = null;
   
  UserListener(MBeanServer server) {
   this.server = server;
  }
   
  public void handleNotification(Notification notif,
                  Object handback) {                   

   String type = notif.getType();
   
   if (type.equals("example.user.remove")) {                
    try {
     System.out.println(notif.getMessage());
     
     server.unregisterMBean((ObjectName)handback);
     System.out.println(handback + " unregistered.");
    }
    catch (JMException e) {
     e.printStackTrace();
    }
   }
  }   
 }


 //
 // Notification filter implementation.
 // 
 class UserFilter implements NotificationFilter {
        
  public boolean isNotificationEnabled(Notification n) {
   return (n.getType().equals("example.user.remove"))
       ? true
       : false;
  }
 }


 //
 // Main method for the client. This will instantiate
 // an agent in the JVM.
 //
 public static void main(String[] args) {
  
  MBeanServer server = 
    MBeanServerFactory.createMBeanServer();
   
  new ListenerClient().run();
 }
  
}

When you compile and run the BroadcastingUser MBean and the ListenerClient, you will see the following output on the console.

User John removed.
user:name=John unregistered.
User Mike removed.
user:name=Mike unregistered.
User Xena removed.
user:name=Xena unregistered.

The user removed messages are the contents of the Notification object's message field and retrieved with getMessage() method. The unregistered messages are generated by the listener after it has invoked the unregisterMBean() method on the MBeanServer.

Attribute Change Notifications

The JMX specification defines a specific AttributeChangeNotification class for MBeans that send notifications on change in their management attribute.

The AttributeChangeNotification class extends the Notification class by adding four new fields to the notification—name, type, oldvalue, and newvalue. The name field should contain the name of the management attribute whose value has been changed, and the type field should contain the runtime type of the management attribute. The oldvalue and newvalue fields should contain the old and new value of the attributes, respectively. All the new fields are accessible via respective getter methods for retrieving the values—getAttributeName(), getAttributeType(), getNewValue(), and getOldValue().

In addition, the AttributeChangeNotification class defines the notification type string that must be exposed as notification metadata in getNotificationInfo() method of the NotificationBroadcaster interface. The notification type is exposed as a static string ATTRIBUTE_CHANGE in the AttributeChangeNotification class.

The AttributeChangeNotificationFilter class is an implementation of the NotificationFilter interface. It contains methods for configuring the filter to accept or deny a pattern of attribute change notifications.

The methods of the AttributeChangeNotificationFilter are described in Table 3.1.

Table 3.1 Methods of the AttributeChangeNotificationFilter Class

Method

Description

enableAttribute(String name)

The attribute change notifications for the given attribute name will be enabled in the filter and sent to the listener.

disableAttribute(String name)

All of the attribute change notifications for the given attribute name will be denied by the filter.

disableAllAttributes()

All attribute change notifications for all management attributes in the filter will be disabled.

getEnabledAttributes()

Returns a vector of the enabled attributes in the notification filter.


The AttributeChangeNotification allows you to easily configure which attribute notifications you want the listener instance to receive.

Attribute Change Notification Example

Listing 3.11 will extend the previous BroadcastingUser example. You will add one attribute change notification to its management interface. It doesn't require many code changes, so only the changed parts are highlighted.

In the BroadcastingUser class, you will override the setUser() method of the superclass User to send an attribute change notification after its setUser() method has been called. In addition, you need to add the new notification type to your metadata in the getNotificationInfo() method. These changes are shown in Listing 3.11.

Listing 3.11 BroadcastingUser.java

...


public class BroadcastingUser extends User implements
   BroadcastingUserMBean, NotificationBroadcaster {

     
  // broadcaster support class
  private NotificationBroadcasterSupport broadcaster = 
        new NotificationBroadcasterSupport();
  
  // sequence number for notifications
  private long notificationSequence = 0;
  
  // override the 'Name' management attribute
  public void setName(String name) {
    String oldValue = super.getName();
    String newValue = name;
    String attrType = String.class.getName();
    String attrName = "Name";
    
    super.setName(name);
    
    broadcaster.sendNotification(
     new AttributeChangeNotification(
      this,              // source
      ++notificationSequence,     // seq. number
      System.currentTimeMillis(),   // time stamp
      "User's name has been changed.", // message
      attrName, attrType,
      oldValue, newValue
     )
    );
  }

...

  public MBeanNotificationInfo[] getNotificationInfo() {
   return new MBeanNotificationInfo[] {
     
    new MBeanNotificationInfo(
     new String[] 
      { "example.user.remove" }, // notif. types
     Notification.class.getName(), // notif. class
     "User Notifications."     // description
    ),
    
    // attribute change notification type
    new MBeanNotificationInfo(
     new String[] {
      AttributeChangeNotification.ATTRIBUTE_CHANGE
     },
     AttributeChangeNotification.class.getName(),
     "User attribute change notification."
    )
   };
  }

...

}

Also, you need to change the ListenerClient class to accept the new notifications in the notification filter object and change the NotificationListener implementation to process the attribute change notifications. The code changes to ListenerClient are shown in Listing 3.12.

Listing 3.12 ListenerClient.java

...

 //
 // Notification listener implementation.
 //
 class UserListener implements NotificationListener {
   
  ...

  public void handleNotification(Notification notif,
                  Object handback) {
   
   String type = notif.getType();
   
   if (type.equals("example.user.remove")) {                
    try {
     System.out.println(notif.getMessage());
     
     server.unregisterMBean((ObjectName)handback);
     System.out.println(handback + " unregistered.");
    }
    catch (JMException e) {
     e.printStackTrace();
    }
   }
   
   // process attribute change notifications
   else if (type.equals(
     AttributeChangeNotification.ATTRIBUTE_CHANGE)) {
    
    AttributeChangeNotification notification =
     (AttributeChangeNotification)notif;
     
    System.out.println(notification.getMessage()); 
    System.out.println(
     " New value=" + notification.getNewValue());
   }
  }   
 }

 //
 // Notification filter implementation.
 //
 class UserFilter implements NotificationFilter {
        
  public boolean isNotificationEnabled(Notification n) {
   return 
    (n.getType().equals
      ("example.user.remove") ||
     n.getType().equals
      (AttributeChangeNotification.ATTRIBUTE_CHANGE)
    )
      ? true
      : false;
  }
 }

...

}

Now, if you compile and run the changed classes, you should see the following output on the console.

User's name has been changed.
 New value=John
User's name has been changed.
 New value=Mike
User's name has been changed.
 New value=Xena
User John removed.
user:name=John unregistered.
User Mike removed.
user:name=Mike unregistered.
User Xena removed.
user:name=Xena unregistered.

The User's name has been changed messages are printed when the listener receives a notification from the MBean that has had its setName() method called to initialize it with a new value.

Notifications to Remote Systems

The JMX notification mechanism discussed so far is strictly a local one, notifying only the MBeans or management applications that are located in the same JVM. For most practical purposes, you will need the notifications to be able to propagate from the JVM to others that are possibly located on a different machine across the network.

The distributed services level of the JMX architecture is currently, at its 1.0 version, left mostly unspecified. The distribution in the management architecture is the responsibility of the JMX connectors and protocol adaptors. Therefore, these same components are the most likely candidates to take care of the propagation of management events to remote systems as well.

Because the distribution of the notifications is left unspecified, there are several possibilities how to implement them. The notifications can be sent to the management applications synchronously or asynchronously, they can be persisted, and so on. The actual functionality will often be dictated by the underlying connector implementation that is used to distribute the notifications. We will see some implementation possibilities in the second part of the book, which is more concentrated on the distributed services of the JMX architecture.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020