Home > Articles > Programming > Java

This chapter is from the book

Implementing Standard MBeans

The main constraint for writing a Standard MBean is the requirement to declare a statically typed Java interface that explicitly declares the management attributes and operations of an MBean. In some cases, having to declare such a rigid programmatic structure to expose the management interface may not be desirable. Usually, however, the Standard MBean mechanism is the simplest and most convenient method for bringing new Java classes into the JMX realm.

The naming conventions used in the MBean interface follow closely the rules set by the JavaBeans component model. To expose the management attributes, you declare getter and setter methods, similar to JavaBean component properties. There are some differences however, especially in the way the JMX agent takes into consideration the inheritance structure of the MBeans, which makes the naming conventions used by the Standard MBeans specific to the JMX specification. We will go through the naming conventions and see examples of the inheritance patterns in the next few pages.

The Hello MBean example used in Chapter 1 was a Standard MBean. We declared a statically typed Java interface called HelloMBean that was implemented by the resource class Hello. It is important to notice that the suffix of the interface name, MBean, is significant. The agent uses introspection on the MBean class to determine which interfaces the class implements. The agent will recognize the class as a Standard MBean type if it finds it implementing an interface with a corresponding MBean suffix in the name. For example, a User class implementing a UserMBean interface is recognized by the agent as a Standard MBean.

Let's take a closer look at the attribute naming conventions next.

Standard MBean Attributes

Management attributes are named characteristics of an MBean. With Standard MBeans, attributes are defined in the MBean interface via the use of naming conventions in the interface methods. There are three kinds of attributes, read-only, write-only, and read-write attributes. The agent determines what kind of attribute has been declared by introspecting the method naming in the MBean interface.

Read-only attributes are defined by declaring only a getter method in the interface. The naming for the getter follows the same rules as with the JavaBeans component model. In other words, a getAttribute() method defines a read-only attribute named Attribute. Similarly, you define a write-only attribute by declaring only a setter method in the MBean interface, for example, setAttribute(). If you declare both the getter and setter method, the agent will determine the attribute Attribute is a read-write type.

The naming convention for MBean attributes is as follows:

public AttributeType getAttributeName();
public void setAttributeName(AttributeType value);

Attributes can be any valid Java type. You can use the standard Java classes such as String, Integer, and Boolean, or you can use your own classes as attribute types. Java primitive types, such as int or byte, are acceptable as well. You can also use an array of any valid Java type. Remember that if you use your own classes, the classes need to be available to the agent at runtime.

There are some restrictions to defining the MBean attributes. You cannot overload attribute accessor methods. For example, you cannot declare an MBean attribute of Java type int that has overloaded setter method, such as follows:

public void setAttributeName(int value);
public void setAttributeName(String value); // NOT COMPLIANT!

Overloading an attribute setter method will lead to a non-compliant MBean.

Another restriction worth noting is the fact that attributes based on arrays can only have getter and setter methods that deal with the entire array all at once. In other words, you cannot declare a setter method for an attribute of Java type int[] that will set, for example, the value of the first item in the array. You will have to declare a setter method that operates on the entire array of integers instead. A workaround for this is to declare a management operation that will manipulate single entries in the array. You will see an example of how to do this in the "Standard MBean Example" section later in the chapter.

For boolean types, the Standard MBean naming conventions allow two alternative ways to declare the getter method. For example, for a management attribute named Active, you can declare either a getter method, getActive() or isActive(), in the management interface. Both methods will be recognized as accessors to the Active attribute. The isActive() form of declaration also implies the boolean type for the given management attribute.

The naming convention for boolean types can be expressed as follows:

public boolean isAttributeName();

Note, however, that you cannot use both the getAttributeName() method and isAttributeName() method for the same attribute in the MBean interface. You will have to pick one of the two methods.

MBean attribute names are case sensitive. Declaring two accessor methods for attributes that differ in capitalization will lead to two separate MBean attributes exposed by the agent.

Management Operations

Management operations for Standard MBeans include all the methods declared in the MBean interface that are not recognized by the agent as being either a read or write method to an attribute. The operations don't have to follow any specific naming rules as long as they do not intervene with the management attribute naming conventions.

The management operations can have return values. The returned values can be of any valid Java type, either primitive type or reference type. In case of the generic management tools, such as the two HTTP protocol adaptors we used earlier, it is up to the adaptor to decide how to deal with the return value. If the management application is aware of the semantics of the return value of the operation it has invoked, it may react to the return value in a specific way. Depending on the return value, the management application may attempt to display the returned object to the user, send a notification based on the value of the returned object, or execute other management code or business logic.

Exceptions in the Management Interface

When creating the Standard MBean interface, you can declare the methods to throw any type of exception as per the rules of Java programming language. The exception types can be those included in the Java standard libraries, such as the java.io.IOException, or they can be custom application exceptions declared by the application developer.

When the agent invokes a method of the management interface, whether a management operation method or management attribute's accessor method, it will catch all the instances of java.lang.Throwable and its subclasses if thrown. The agent will wrap the checked exceptions in a javax.management.MBeanException class and then proceed to propagate this exception to the originating caller. Unchecked exceptions—subclasses of RuntimeException—will be wrapped in a javax.management.RuntimeMBeanException class. Similarly, all errors thrown by the MBean implementation will be wrapped in javax.management.RuntimeErrorException.

Both the RuntimeMBeanException and MBeanException implement a getTargetException() method that allows you to access the original exception that was thrown in the MBean. The RuntimeErrorException implements a getRuntimeError() method for retrieving the error thrown by the MBean.

The methods in the MBeanServer interface used for accessing the MBeans, such as setAttribute(), getAttribute() and invoke(), declare the checked exception class MBeanException to be thrown, and, therefore, require a try–catch block in the management client. In the exception handling code, the client can extract the actual target exception and react accordingly.

Standard MBean Example

So far, you have learned several details about Standard MBeans, and now it is time to put that knowledge into practice with a code example. In the next few pages, you will define and implement a User resource and create a management interface for it. The User resource is not specific to any existing system. It is an abstract construct that stores the user ID, name, address, and phone numbers. It should be easy to see a User resource as part of many information systems. Managing users is a common administrative task in many environments.

You will define five attributes for the management interface of the user object. First, the user has a read-only attribute ID. The ID represents a unique identifier for this particular user, such as a primary key in the database. You will also define read-write attributes Name and Address. These two string attributes can be used to store the user's name and address.

public long getID();
public String getName();
public void setName(String name);
public String getAddress();
public void setAddress(String address);

To demonstrate the use of arrays, define an array-based attribute PhoneNumbers. It's a string array containing a maximum of three telephone numbers.

public String[] getPhoneNumbers();
public void setPhoneNumbers(String[] numbers);

Last, there is a write-only attribute Password. Because you only declare a setter method for this attribute, which makes it write-only, you can set a new password for the user via the management interface. But you are unable to read the stored password after you've set it. This prevents the HTTP adaptor from displaying the contents of the Password attribute on the Web page.

public void setPassword(String passwd);

Naturally, any management operation dealing with sensitive information, such as passwords, must be properly secured. The JMX specification does not currently define security features for MBeans. In practice, this responsibility is left mostly to the distributed services level and agent level of the JMX architecture—the connectors, protocol adaptors and the JMX agent.

In addition to the five attributes, you declare three operations for this MBean component. Two of the operations, addPhoneNumber() and removePhoneNumber(), are used for modifying individual elements of the PhoneNumbers array. The third operation, printInfo(), is used for printing the contents of the User object—name, address, and phone numbers. This time, you won't print the information to the console, as you did with the Hello example in Chapter 1. Instead, you declare the printInfo() operation to return a string value.

Listing 3.1 is the complete declaration of the management interface.

Listing 3.1 UserMBean.java

package book.jmx.examples;

public interface UserMBean {

  // read-only attribute 'ID'
  public long getID();
  
  // read-write attribute 'Name'
  public String getName();
  public void setName(String name);
  
  // read-write attribute 'Address'
  public String getAddress();
  public void setAddress(String address);
  
  // read-write array attribute 'PhoneNumbers'
  public String[] getPhoneNumbers();
  public void setPhoneNumbers(String[] numbers);
  
  // write-only attribute 'Password'
  public void setPassword(String passwd);
  
  // management operations
  public String printInfo();
  public void addPhoneNumber(String number);
  public void removePhoneNumber(int index);
}

In the MBean implementation, you will store the attribute values to object fields id, name, address, password, and numbers. This is a very straightforward assignment from parameters to fields. However, there are a couple of things you should notice.

In the example, the setID() method of the User class is implemented. Notice that you did not declare this method in the MBean interface. This is a usual practice in cases where the methods in the resource class are not meant to be exposed for management applications. In the User class, the reading of the ID attribute is allowed for management applications, but the ability to write the ID value is reserved for the application's internal methods only. The user of the management application will not be able to change the value of this attribute. For the ID value, the creation time of the object instance is used because a database or directory is not set up for this example.

The methods addPhoneNumber() and removePhoneNumber() have been implemented and exposed for management. They allow you to modify individual entries in the array attribute PhoneNumbers. The addPhoneNumber() method tries to add the string given as parameter to the first entry in the array containing a null reference. The removePhoneNumber() method will set the array entry to null for the given index.

Listing 3.2 is the full source code of the managed resource.

Listing 3.2 User.java

package book.jmx.examples;

public class User implements UserMBean {

  private long id     = System.currentTimeMillis();
  private String name   = "";
  private String address  = "";
  private String password = null;
  private String[] numbers = new String[3];
  

  // read-only attribute 'ID'
  public long getID() { 
    return id;
  }


  // application method, not exposed to management
  public void setID(long id) {
    this.id = id;
  }
  

  // read-write attribute 'Name'
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }

  
  // read-write attribute 'Address'
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }

  
  // read-write array attribute 'PhoneNumbers'
  public String[] getPhoneNumbers() {
    return numbers;
  }
  public void setPhoneNumbers(String[] numbers) {
    this.numbers = numbers;
  }

  
  // write-only attribute 'Password'
  public void setPassword(String passwd) {
    this.password = passwd;
  }

  
  // management operations
  public String printInfo() {
    return 
     "User: " + getName() +"\n"+
     "Address: " + getAddress() +"\n"+
     "Phone #: " + getPhoneNumbers()[0] +"\n"+
     "Phone #: " + getPhoneNumbers()[1] +"\n"+
     "Phone #: " + getPhoneNumbers()[2] +"\n";
  }
  
  public void addPhoneNumber(String number) {
    for (int i = 0; i < numbers.length; ++i)
      if (numbers[i] == null) {
        numbers[i] = number;
        break;
      }
  }

  public void removePhoneNumber(int index) {
    if (index < 0 || index >= numbers.length)
      return;
      
    numbers[index] = null;
  }
}

User Client

Next, you will build a simple management client for the MBean to demonstrate the use of the User MBean. The client will operate in the same Java Virtual Machine as the JMX agent but will be useful to show the programmatic invocation of the MBeans. Later, after you have read about the JMX connectors in Part II, "JMX in the J2EE Platform," you can also invoke the same MBeans using a wide variety of different protocol and messaging mechanisms.

As was shown in Chapter 2, "Architecture," where management architecture was covered, the MBeans themselves are never directly exposed to the management clients. What the management applications have access to is the agent layer of the JMX architecture, which offers the programmatic interface to manipulate the managed resources. This layer of indirection between the management application and the managed resource creates the decoupled nature of the JMX-based management systems. The only static information known to the management application about the resource is its name, which was used to register the component to the agent, and is represented by the ObjectName instance. Any change to the management interface of the resource is kept local between the resource and the agent. In effect, this decouples the management applications from the resources, and changes to the resources, as they evolve and go through maintenance, can be isolated.

Listing 3.3 should clearly explain this nature of the Java Management Extensions. As you will see, the name of the managed resource is involved in all invocations to the agent, which will then proceed to propagate the invocation to the correct managed resource known to it. Notice that you never at any point have a direct Java reference to the resource on which you invoke the operations. You should also notice that all the invocations to management operations are generic, and all the type information—in other words, the operation's signatures—are passed to the agent as string types instead of statically-typed method calls. This type of invocation is crucial to systems built for very long uptimes where new components are introduced to the system dynamically and the old ones are upgraded by hot-deploying the software components.

The whole agent API will be covered in Chapter 6, "Mbean Server," but for now look at two methods of the MBeanServer interface needed to use in the client—the setAttributes() and invoke() methods.

The setAttributes(), as the name implies, is used to set the management attributes of an MBean. The setAttributes() method takes an ObjectName instance and an AttributeList instance as its parameters, where the ObjectName is the name of the MBean registered to the agent, and the AttributeList is a collection of Attribute objects representing the management attributes.

The invoke() method of the MBeanServer is declared as follows (exceptions have been left out for the sake of brevity).

public Object invoke(ObjectName name, String operationName,
           Object[] params, String[] signature)

As you can see, there is no static type information involved in the invocation. The return value and parameters are passed as generic objects, the MBean instance to receive the invocation is identified by its object name, and the operation name and its signature are passed as strings. On the one hand, this kind of detyping of the invocation leads to a system capable of dynamically changing while maintaining high-availability capabilities. On the other hand, it puts you, the developer, in a position where extra rigor is needed in implementation. You should be extra careful when writing the invocations to avoid simple typos or disarranged signatures. Smart use of refactoring techniques to avoid replicating the invocations and use of constants and other measures are recommended.

Now that you are aware of the double-edged sword of the invocation and can handle it with care, take a look at the UserClient code. The management code to handle the programmatic invocation of management operations is shown in Listing 3.3.

Listing 3.3 UserClient.java

package book.jmx.examples;

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

public class UserClient {

  public void run() {

   // Find an agent from this JVM. Null argument will return
   // a list of all MBeanServer instances.
   List srvrList = MBeanServerFactory.findMBeanServer(null);
   MBeanServer server =
      (MBeanServer)srvrList.iterator().next();
   
   try {    
     // register the MBean
     ObjectName name = new ObjectName("example:name=user");
     server.registerMBean(new User(), name);

     // Invoke the printInfo operation on an
     // uninitialized MBean instance.
     Object result = server.invoke(
              name,     // MBean name
              "printInfo",  // operation name
              null,     // no parameters
              null      // void signature
             );
      
     System.out.println("Non-initialized User object:");
     System.out.println(result);
      
     // Create the list of management attribute value pairs
     AttributeList list = new AttributeList();
     list.add(new Attribute("Name", "John"));
     list.add(new Attribute("Address", "Strawberry Street"));
     list.add(new Attribute("PhoneNumbers", new String[]
                 {
                  "555-1232",
                  null,
                  null
                 }
                ));

     // Init the MBean instance by calling setAttributes()
     server.setAttributes(name, list);

     // Invoke the printInfo to retrieve the updated state      
     result = server.invoke(
              name,     // MBean name
              "printInfo",  // operation name
              null,     // no parameters
              null      // void signature
             );
  
     System.out.println("Initialized User object:");
     System.out.println(result);
   }
   catch (MalformedObjectNameException e) {
     e.printStackTrace();
   }
   catch (InstanceNotFoundException e) {
     e.printStackTrace();
   }
   catch (MBeanException e) {
     e.getTargetException().printStackTrace();
   }
   catch (ReflectionException e) {
     e.printStackTrace();
   }
   catch (InstanceAlreadyExistsException e) {
     e.printStackTrace();
   }
   catch (NotCompliantMBeanException e) {
     e.printStackTrace();
   }

  }

  /**
  * Main method for the client. This will instantiate an agent
  * and register the User MBean to it.
  */
  public static void main(String[] args) {
  
   MBeanServer server =
        MBeanServerFactory.createMBeanServer();
    
   new UserClient().run();
  }
}

At the main() method, the JMX agent instance is created with the createMBeanServer() method of the MBeanServerFactory class. Then the run() method is invoked, which implements the client logic. The client first tries to find a reference to the MBeanServer. This is achieved by using the MBeanServerFactory class and its findMBeanServer() method. The findMBeanServer() method will return an agent reference based on either an agent identifier, which can be passed as a parameter, or a list of all known MBean server instances found in the JVM. The UserClient code uses the latter option, and picks the first reference from the returned list, knowing that, in the case of this specific example, the only MBean server instance in the JVM is the one created in the main() method.

Next, you create the ObjectName instance that identifies the MBean in the agent. The object name represents the reference to the MBean, which the agent will know how to map to a Java reference to the managed resource. Remember that this is the mechanism keeping the management client decoupled from the resource implementation.

After you have created the ObjectName instance and registered the MBean to the server, you can use the MBean server to invoke the printInfo() operation. It returns a formatted string containing the managed resource's state.

To compile and run the code using Sun reference implementation, execute the following two commands:

C:\Examples> javac -d . -classpath .;jmx-1_0_1-ri_bin/jmx/lib/jmxri.jar
_ UserClient.java User.java UserMBean.java

C:\Examples> java -classpath .;jmx-1_0_1-ri_bin/jmx/lib/jmxri.jar
_ book.jmx.examples.UserClient

The client should output the following:

Non-initialized User object:
User:
Address:
Phone #: null
Phone #: null
Phone #: null

As you can see, none of the fields in the resource have been initialized yet. Next you build an AttributeList object containing the attributes you want to set on the MBean. The AttributeList contains instances of Attribute objects that represent the management attributes in our managed bean—Name, Address, and PhoneNumbers.

When the AttributeList has been created and initialized, you set all of the attributes with the setAttributes() call and invoke the printInfo operation again. This time, the output contains the attribute values you passed to the agent.

Initialized User object:
User: John
Address: Strawberry Street
Phone #: 555-1232
Phone #: null
Phone #: null

You can also try the User MBean with the JMX HTTP adapter that was tested in Chapter 1. You will need to alter the Agent.java from the Hello example (Listing 1.4 in Chapter 1) to register the User MBean component to the agent. The changes are shown in Listing 3.4.

To compile and run execute the following commands (using Sun Reference Implementation), use the following:

C:\Examples> javac -d . -classpath .;jmx-1_0_1-ri_bin/jmx/lib/jmxri.jar;
_jmx-1_0_1-ri_bin/jmx/lib/jmxtools.jar  _User.java UserMBean.java Agent.java

C:\Examples> java -classpath .;jmx-1_0_1-ri_bin/jmx/lib/jmxri.jar;
_jmx-1_0_1-ri_bin/jmx/lib/jmxtools.jar _book.jmx.examples.Agent

Listing 3.4 Agent.java

...

  try {
    // create the agent reference
    MBeanServer server = 
      MBeanServerFactory.createMBeanServer();

    // create object name reference
    ObjectName name = 
      new ObjectName("example:name=user");
    
    // register Hello MBean
    server.registerMBean(new User(), name);

    // create the adaptor instance
    com.sun.jdmk.comm.HtmlAdaptorServer adaptor =
      new com.sun.jdmk.comm.HtmlAdaptorServer();

    ... 
  }

Enter the query for the User component name, example:name=user and click the link to open the management view of the MBean (see Figure 3.1).

Figure 3.1 HTTP Adaptor view of the User MBean.

Now fill in some attribute values for Name, Address, and Password. Try viewing the values of PhoneNumbers and use the management operations addPhoneNumber() and removePhoneNumber() to add and remove single entries to the array.

The User MBean example covers the most common features of the Standard MBeans. You have written a simple management client and programmatically invoked operations on the MBean. You have seen, at the code level, the implications of decoupling the management applications from the managed resources and the agent's role in providing the said indirection. You have also seen examples of all three kinds of management attributes—read-only, write-only and read-write—as well as an example of an array-based attribute.

Next, you will look at how the inheritance of the Standard MBean management interfaces are interpreted by the agent, and how inheritance can be used to enable management of existing Java resources.

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