Home > Articles > Software Development & Management

From the book Solution

Solution

Use an Intercepting Filter as a pluggable filter to pre and postprocess requests and responses. A filter manager combines loosely coupled filters in a chain, delegating control to the appropriate filter. In this way, you can add, remove, and combine these filters in various ways without changing existing code.

As with other systems where there is a significant number of duplicated tasks, it’s a good idea to take that duplicated processing, factor it out, and make it coarse grained enough to apply broadly. This is what pluggable filters accomplish.

In effect, you are able to decorate the main processing with a variety of common services, such as logging and debugging. Filters are independent of the main application code, and you can add or remove them declaratively.

Filters are controlled declaratively using a deployment descriptor, as described in the "Servlet Specification,” version 2.3. The “Servlet 2.3 Specification” includes a standard mechanism for building filter chains and unobtrusively adding and removing filters from those chains. A deployment configuration file sets up a chain of filters and can include a mapping of specific URLs to this filter chain. When a client requests a resource that matches the configured URL mapping, the filters in the chain are invoked before (preprocessing) and/or after (postprocessing) the invocation of the requested target resource.

Structure

Figure 6.1 represents the Intercepting Filter class diagram.

Figure 6.1 Intercepting Filter Class Diagram

Participants and Responsibilities

Figure 6.2 represents the Intercepting Filter sequence diagram.

Figure 6.2 Intercepting Filter Sequence Diagram

Client

The Client sends a request to the FilterManager.

FilterManager

The FilterManager manages filter processing. It creates the FilterChain with the appropriate filters, in the correct order, and initiates processing.

FilterChain

The FilterChain is an ordered collection of independent filters.

FilterOne, FilterTwo

FilterOne and FilterTwo represent individual filters that are mapped to a Target. The FilterChain coordinates the processing of filters.

Target

The Target is the resource requested by the client.

Strategies

Standard Filter Strategy

Filters are controlled declaratively using a deployment descriptor, as described in the servlet specification, version 2.3. The Servlet 2.3 Specification includes a standard mechanism for building filter chains and unobtrusively adding and removing filters from those chains. Filters are based upon a standard interface, and are loosely coupled to each other, as well as to the target resources for which they perform pre or postprocessing. Configure each filter declaratively by modifying the deployment descriptor for a web application.

The example for this strategy is a filter that preprocesses requests of any encoding type such that the core request-handling code can handle each request.

Why might this be necessary? An example is HTML forms that include a file upload use a different encoding type than that of basic forms. As a result, form data that accompanies the upload is not available via simple getParameter() invocations. In order to get at this form data, the example includes two filters that preprocess requests, translating all encoding types into a single consistent format. The format has all form data available as request attributes.

Each filter handles a different encoding type:

  • One filter handles the standard form encoding of type application/ x-www-form-urlencoded
  • The other handles the less common encoding type multipart/form-data, which is used for forms that include file uploads.

The filters translate all form data into request attributes, so the core request handling mechanism can work with every request in the same manner, instead of with special casing for different encodings.

Example 6.1 through Example 6.4 provide code for this example, and Figure 6.3 shows the sequence diagram.

The base filter, shown in Example 6.1, provides default behavior for the Standard Filter callback methods.

Example 6.1 Base Filter – Standard Filter Strategy

1	public class BaseEncodeFilter implements javax.servlet.Filter {
2	
3	  private javax.servlet.FilterConfig filterConfig;
4	
5	  public void doFilter(
6	      javax.servlet.ServletRequest servletRequest,
7	          javax.servlet.ServletResponse servletResponse,
8	          javax.servlet.FilterChain filterChain) 
9	          throws java.io.IOException,
10	          javax.servlet.ServletException {
11	
12	    filterChain.doFilter(servletRequest, servletResponse);
13	  }
14	    
15	  protected javax.servlet.FilterConfig getFilterConfig() {
16	    return filterConfig;
17	  } 
18	  
19	  public void destroy() { }
20	    
21	  public void init(javax.servlet.FilterConfig filterConfig)
22	      throws javax.servlet.ServletException {
23	    this.filterConfig = filterConfig;
24	  }
25	 
26	}

Example 6.2 shows a filter that translates requests using the common application form encoding scheme.

Example 6.2 StandardEncodeFilter – Standard Filter Strategy

1	public class StandardEncodeFilter extends BaseEncodeFilter {
2	  // Creates new StandardEncodeFilter
3	  public StandardEncodeFilter() {  }
4	
5	  public void doFilter(javax.servlet.ServletRequest 
6	      servletRequest,javax.servlet.ServletResponse 
7	          servletResponse,javax.servlet.FilterChain filterChain) 
8	          throws java.io.IOException,
9	          javax.servlet.ServletException {
10	
11	    String contentType = servletRequest.getContentType();
12	    if ((contentType == null) || contentType.equalsIgnoreCase(
13	        "application/x-www-form-urlencoded")) {
14	      translateParamsToAttributes(servletRequest, servletResponse);
15	    }
16	
17	    filterChain.doFilter(servletRequest, servletResponse);
18	  }
19	
20	  private void translateParamsToAttributes(
21	      ServletRequest request, ServletResponse response) {
22	    Enumeration paramNames = request.getParameterNames();
23	
24	    while (paramNames.hasMoreElements()) {
25	      String paramName = (String) paramNames.nextElement();
26	      String [] values;
27	      values = request.getParameterValues(paramName);
28	      if (values.length == 1)
29	        request.setAttribute(paramName, values[0]);
30	      else
31	        request.setAttribute(paramName, values);
32	    }
33	  }
34	}

Example 6.3 shows the filter that handles the translation of requests. The requests use the multipart form encoding scheme. The code for these filters is based on the final draft of the servlet specification, version 2.3. Both filters inherit from a base filter (see Base Filter Strategy).

Example 6.3 MultipartEncodeFilter – Standard Filter Strategy

1	public class MultipartEncodeFilter extends BaseEncodeFilter {
2	  public MultipartEncodeFilter() { }
3	  public void doFilter(
4	      javax.servlet.ServletRequest servletRequest,
5	          javax.servlet.ServletResponse servletResponse,
6	          javax.servlet.FilterChain filterChain)
7	          throws java.io.IOException,
8	          javax.servlet.ServletException {
9	
10	    String contentType = servletRequest.getContentType();
11	    // Only filter this request if it is multipart 
12	    // encoding                
13	    if (contentType.startsWith("multipart/form-data")) {
14	      try {
15	        String uploadFolder = getFilterConfig().
16	            getInitParameter("UploadFolder");
17	        if (uploadFolder == null)
18	          uploadFolder = ".";
19	        /** The MultipartRequest class is: 
20	          * Copyright (C) 2001 by Jason Hunter 
21	          * <jhunter@servlets.com>. All rights reserved.
22	        **/
23	        MultipartRequest multi = new MultipartRequest(
24	            servletRequest, uploadFolder, 1 * 1024 * 1024 );
25	        Enumeration params = multi.getParameterNames();
26	        while (params.hasMoreElements()) {
27	          String name = (String)params.nextElement();
28	          String value = multi.getParameter(name);
29	          servletRequest.setAttribute(name, value);
30	        }
31	        Enumeration files = multi.getFileNames();
32	        while (files.hasMoreElements()) {
33	          String name = (String)files.nextElement();
34	          String filename = multi.getFilesystemName(name);
35	          String type = multi.getContentType(name);
36	          File f = multi.getFile(name);
37	          // At this point, do something with the 
38	          // file, as necessary
39	        }
40	      } catch (IOException e) {
41	        LogManager.logMessage("error reading or saving file"+ e);
42	      }
43	    } // end if
44	    filterChain.doFilter(servletRequest, servletResponse);
45	  } // end method doFilter()
46	}

The excerpt in Example 6.4 is from the deployment descriptor for the web application containing this example. It shows how these two filters are registered and then mapped to a resource; in this case it’s a simple test servlet.

Example 6.4 Deployment Descriptor – Standard Filter Strategy

1	.
2	.
3	.
4	<filter>
5	  <filter-name>StandardEncodeFilter</filter-name>
6	  <display-name>StandardEncodeFilter</display-name>
7	  <description></description>
8	  <filter-class> corepatterns.filters.encodefilter.
9	      StandardEncodeFilter</filter-class>
10	</filter>
11	<filter>
12	  <filter-name>MultipartEncodeFilter</filter-name>
13	  <display-name>MultipartEncodeFilter</display-name>
14	  <description></description>
15	  <filter-class>corepatterns.filters.encodefilter.
16	      MultipartEncodeFilter</filter-class>
17	  <init-param>
18	    <param-name>UploadFolder</param-name>
19	    <param-value>/home/files</param-value>
20	  </init-param>
21	</filter>
22	.
23	.
24	.
25	<filter-mapping>
26	  <filter-name>StandardEncodeFilter</filter-name>
27	  <url-pattern>/EncodeTestServlet</url-pattern>
28	</filter-mapping>
29	<filter-mapping>
30	  <filter-name>MultipartEncodeFilter</filter-name>
31	  <url-pattern>/EncodeTestServlet</url-pattern>
32	</filter-mapping>
33	.
34	.
35	.

The sequence diagram for this example is shown in Figure 6.3.

The StandardEncodeFilter and the MultiPartEncodeFilter intercept control when a client makes a request to the controller servlet. The container fulfills the role of filter manager, and directs control to these filters by invoking their doFilter methods. After completing its processing, each filter passes control to its containing FilterChain. The filter instructs its FilterChain to execute the next filter. Once both filters have received and subsequently relinquished control, the next component to receive control is the actual target resource, in this case the controller servlet.

Filters, as supported in version 2.3 of the servlet specification, also support wrapping the request and response objects. This feature lets you build a much more powerful mechanism than could be built using the custom implementation suggested by the Custom Filter strategy. Of course, you can custom build a hybrid approach combining the two strategies but this approach would still lack the power of the Standard Filter strategy, as supported by the servlet specification.

Figure 6.3 Intercepting Filter, Standard Filter Strategy – Encoding Conversion Example

Custom Filter Strategy

Implement the Filter with your own custom strategy. This is less flexible and less powerful than the preferred Standard Filter strategy that is available in containers supporting the 2.3 servlet specification and later. This Custom Filter strategy is less powerful because it doesn’t support wrapping request and response objects in a standard and portable way. Additionally, the request object cannot be modified, and you must introduce some sort of buffering mechanism if filters are to control the output stream.

To implement the Custom Filter strategy, you could use the Decorator pattern [GoF] to wrap filters around the core request-processing logic. For example, apply a debugging filter that wraps an authentication filter.

Example 6.5 and Example 6.6 show how you could create this mechanism programmatically.

Example 6.5 Implementing a Filter – Debugging Filter

1	public class DebuggingFilter implements Processor {
2	  private Processor nextProcessor;
3	
4	  public DebuggingFilter(Processor nextProcessor) {
5	    this.nextProcessor = nextProcessor;
6	  }
7	
8	  public void execute(ServletRequest request, 
9	      ServletResponse response)
10	      throws IOException, ServletException {
11	    // Do some filter processing here, such as 
12	    // displaying request parameters
13	    
14	    nextProcessor.execute(request, response);
15	  }
16	}

Example 6.6 Handling Requests

1	public void processRequest(ServletRequest req, ServletResponse res) 
2	    throws IOException, ServletException {
3	  Processor processors = new DebuggingFilter(
4	      new AuthenticationFilter(new CoreProcessor()));
5	  processors.execute(req, res);
6	
7	  //Then dispatch to next resource, which is probably 
8	  // the View to display
9	  dispatcher.dispatch(req, res);
10	}
11	

In the servlet controller, delegate to a method called ProcessRequest to handle incoming requests, as shown in Example 6.7.

Example 6.7 Implementing a Filter – Core Processor

1	public class CoreProcessor implements Processor {
2	
3	  public CoreProcessor() { }
4	
5	  public void execute(ServletRequest req, ServletResponse res)
6	      throws IOException, ServletException {
7	    //Do core processing here
8	  }
9	}

For example purposes only, imagine that each processing component writes to standard output when it is executed. Example 6.8 shows the possible execution output.

Example 6.8 Messages Written to Standard Output

1	Debugging filter preprocessing completed...
2	Authentication filter processing completed...
3	Core processing completed...
4	Debugging filter post-processing completed...

Example 6.8 shows standard output when a chain of processors is executed in order. Each processor, except for the last one in the chain, is considered a filter. The final processor component is where you encapsulate the core processing you want to complete for each request. Given this design, you will need to change the code in the CoreProcessor class, as well as in any filter classes, when you want to modify how you handle requests.

Figure 6.4 is a sequence diagram describing the flow of control for the filter code of Example 6.5, Example 6.6, and Example 6.8.

Notice that with a Decorator implementation, each filter invokes on the next filter directly, though using a generic interface. You could implement this strategy a different way using a FilterManager and FilterChain. In this case, these two components coordinate and manage filter processing, and the individual filters do not communicate with one another directly.

Figure 6.4 Sequence Diagram for Custom Filter Strategy, Decorator Implementation

This design approximates a servlet 2.3-compliant implementation, though it is still a custom strategy. Example 6.9 is just such a FilterManager class, which creates a FilterChain; the FilterChain is shown in Example 6.10. The FilterChain adds filters to the chain in the appropriate order, processes the filters, and finally processes the target resource. (For the sake of brevity, adding filters to the chain is done in the FilterChain constructor, but would normally be done in place of the comment.)

Figure 6.5 is a sequence diagram for this code.

Example 6.9 FilterManager – Custom Filter Strategy

1	public class FilterManager {
2	  public void processFilter(Filter target, 
3	      javax.servlet.http.HttpServletRequest request, 
4	          javax.servlet.http.HttpServletResponse response) 
5	              throws javax.servlet.ServletException, 
6	                  java.io.IOException {
7	
8	    FilterChain filterChain = new FilterChain();
9	    // The filter manager builds the filter chain here if necessary
10	    // Pipe request through Filter Chain
11	    filterChain.processFilter(request, response);
12	
13	    //process target resource
14	    target.execute(request, response);
15	  }
16	}

Figure 6.5 Sequence Diagram for Custom Filter Strategy, Nondecorator Implementation

Example 6.10 FilterChain – Custom Filter Strategy

1	public class FilterChain {
2	  // filter chain 
3	  private List myFilters = new ArrayList();
4	 
5	  // Creates new FilterChain 
6	  public FilterChain() {
7	    // plug-in default filter services for example 
8	    // only. This would typically be done in the 
9	    // FilterManager, but is done here for example 
10	    // purposes
11	    addFilter(new DebugFilter());
12	    addFilter(new LoginFilter());
13	    addFilter(new AuditFilter());
14	  }
15	
16	  public void processFilter( 
17	      javax.servlet.http.HttpServletRequest request,
18	          javax.servlet.http.HttpServletResponse response)
19	              throws javax.servlet.ServletException,
20	                  java.io.IOException {
21	
22	    Filter filter;
23	    // apply filters
24	    Iterator filters = myFilters.iterator();
25	    while (filters.hasNext()) {
26	      filter = (Filter)filters.next();
27	      // pass request & response through various 
28	      // filters
29	      filter.execute(request, response);
30	    }
31	  }
32	
33	  public void addFilter(Filter filter) {
34	    myFilters.add(filter);
35	  }
36	}

You can’t create very flexible or powerful filters with this strategy. Instead, use the Standard Filter strategy where possible. Filters are added and removed programmatically. While you could write a proprietary mechanism for handling adding and removing filters via a configuration file, you still would have no way of wrapping the request and response objects. Additionally, without a sophisticated buffering mechanism, this strategy does not provide flexible postprocessing.

The Standard Filter strategy provides solutions to these issues, leveraging features of the 2.3 servlet specification

Base Filter Strategy

A base filter serves as a common superclass for all filters. Common features can be encapsulated in the base filter and shared among all filters. For example, a base filter is a good place to include default behavior for the container callback methods in the Standard Filter strategy. Example 6.11 shows one way to do this.

Example 6.11 Base Filter Strategy

1	public class BaseEncodeFilter implements javax.servlet.Filter {
2	  private javax.servlet.FilterConfig filterConfig;
3	
4	  public BaseEncodeFilter() { }
5	
6	  public void init(javax.servlet.FilterConfig filterConfig) {
7	      this.filterConfig = filterConfig;
8	  }
9	    
10	  public void doFilter(javax.servlet.ServletRequest servletRequest,
11	      javax.servlet.ServletResponse servletResponse,
12	      javax.servlet.FilterChain filterChain) 
13	      throws java.io.IOException,
14	      javax.servlet.ServletException {
15	
16	    filterChain.doFilter(servletRequest, servletResponse);
17	  }
18	    
19	  protected javax.servlet.FilterConfig getFilterConfig() {
20	    return filterConfig;
21	  }
22	}

Template Filter Strategy

A key benefit of using this strategy is that it abstracts away the details of the underlying servlet API and focuses on implementing preprocessing and postprocessing logic. This means you no longer need to deal with the semantics of method invocations such as chain.doFilter(req, res), but rather simply with method invocations such as doPreProcessing(req, res), which are much more intuitive.

This strategy builds on the Base Filter strategy, which simply describes using a base class to encapsulate all the details of the filter API (see Base Filter Strategy on page 158). The Template Filter strategy uses this base class to provide Template Method [Gof] functionality. In this case, the base filter dictates the general steps that every filter must perform, while leaving the specifics of how to complete that step to each filter subclass. This approach provides the inversion of control that is common in frameworks, meaning that the superclass (or base class) dictates the flow of control to its subclasses. Typically, the methods of the superclass are coarsely defined, basic methods that simply impose a limited structure on each template.

You can combine this strategy with any other filter strategy. Example 6.12 and Example 6.13 show how to use this strategy with the Declared Filter strategy.

Example 6.12 shows a base filter called TemplateFilter, as follows.

Example 6.12 Using a Template Filter Strategy

1	public abstract class TemplateFilter implements javax.servlet.Filter {
2	  private FilterConfig filterConfig;
3	  public void init(FilterConfig filterConfig) throws ServletException {
4	    this.filterConfig = filterConfig;
5	  }
6	
7	  protected FilterConfig getFilterConfig() 	{ 
8	    return filterConfig; 
9	  }
10	
11	  public void doFilter(ServletRequest request, 
12	      ServletResponse response, FilterChain chain)
13	      throws IOException, ServletException {
14	
15	    // Preprocessing for each filter 
16	    doPreProcessing(request, response);
17	
18	    // Pass control to the next filter in the chain or 
19	    // to the target resource. This method invocation is what logically
20	    // demarcates preprocessing from postprocessing.
21	    chain.doFilter(request, response);
22	
23	    // Post-processing for each filter
24	    doPostProcessing(request, response);
25	  }
26	  public abstract void doPreProcessing(ServletRequest request, 
27	      ServletResponse response) { }
28	
29	  public abstract void doPostProcessing(ServletRequest request, 
30	      ServletResponse response) { }
31	
32	  public void destroy() { }
33	}

Given this class definition for TemplateFilter, each filter is implemented as a subclass that implements only the doPreProcessing and doPostProcessing methods. These subclasses have the option, though, of implementing all three methods. Example 6.13 is an example of a filter subclass that implements the two mandatory methods (dictated by the superclass template filter).

Example 6.13 Logging Filter

1	public class LoggingFilter extends TemplateFilter {
2	  public void doPreProcessing(ServletRequest req, ServletResponse res) {
3	    //do some preprocessing here, such as logging some information about
4	    // the request before it’s been handled.
5	  }
6	
7	  public void doPostProcessing(ServletRequest req, ServletResponse res){
8	    // do some post-processing here, such as logging some information
9	    // about the request and response after the request has been handled
10	    // and the response generated.
11	  }
12	}

In the sequence diagram in Figure 6.6, filter subclasses, such as LoggingFilter, define specific processing by overriding the abstract doPreProcessing and doPostProcessing methods. As a result, the template filter imposes a flow of control upon each filter and focuses filter developers on the semantics of writing pre and postprocessing logic. Finally, since it is a base filter, it also provides a place for encapsulating code that is common to every filter.

A sequence diagram for this strategy is shown in Figure 6.6.

Figure 6.6 Intercepting Filter, Template Filter Strategy Sequence Diagram

Web Service Message-Handling Strategies

While using Intercepting Filter is common in the presentation tier, certain Intercepting Filter strategies are relevant in other tiers, as well. The Custom SOAP Filter and JAX-RPC Filter message-handling strategies are examples of filters used in the client, presentation, and integration tiers to handle pre and postprocessing of web service requests.

When loosely coupled, these chained filters are used to handle and manipulate web service requests and are often referred to as message handlers. These filters intercept incoming messages and perform pre and postprocessing on information in the message.

Similarly, the filters act on outgoing responses. For example, a message handler might validate a digital signature, sign a message, or log information about a message. Messages must be serialized from XML to Java and vice versa, as each message enters and leaves the handler mechanism.

The SOAP With Attachments API for Java, or SAAJ [SAAJ], allows developers to work with SOAP messages and provides support for building pre and postprocessing filters. Use SOAP message handlers judiciously; when you do use them, they provide a powerful processing mechanism. For more coverage of web services, see Application Controller (205) and Web Service Broker (557).

Custom SOAP Filter Strategy Web Service

This strategy is typically invoked as part of Application Controller’s (205) Custom SOAP Message-Handling strategy (230). A Context Object (181) is used to share details of the SOAP message between handlers, since one handler does not directly reference another.

The key differentiator between this strategy, shown in Figure 6.7 and Figure 6.8, and the JAX-RPC Filter strategy in Figure 6.9, is that in this strategy you write a custom handler to fulfill the participant responsibilities, using a SOAP library, such as SAAJ.

Figure 6.7 Custom SOAP Filter Strategy Class Diagram

Figure 6.8 Custom SOAP Filter Strategy Sequence Diagram

JAX-RPC Filter Strategy Web Service

This strategy is typically invoked as part of Application Controller’s (205) JAX-RPC Message-Handling strategy (235). A Context Object (181) is used to share details of the SOAP message between handlers, since one handler does not directly reference another.

The key differentiator between this strategy and the Custom SOAP Filter strategy is that in this strategy most of the participant responsibilities are performed by the JAX-RPC runtime engine. The handlers are implemented either on the client side of the RPC invocation, on the server side of the RPC invocation, or on both sides. Thus, you can insert handlers on either side of the network connection. You build message handlers with JAX-RPC using SAAJ, which offers powerful processing capabilities when used judiciously.

Figure 6.9 JAX-RPC Filter Strategy Sequence Diagram

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