Use MutationObserver to Track DOM Changes in Java

MutationObserver monitors changes made to a DOM tree and delivers matching mutation records to a callback. In Aspose.HTML for Java, it can be used while processing an HTMLDocument to detect added or removed nodes, attribute changes, and changes to text nodes.

To observe DOM changes in Java, create a MutationObserver with a callback, configure a MutationObserverInit, and call observe(target, options). Changes made to the selected target are then reported through MutationRecord objects.

What Is MutationObserver?

Mutation Observer is a DOM mechanism for observing changes to a document tree. It lets an application monitor selected nodes and run custom logic after matching changes occur. The observer can report changes to child nodes, descendants, attributes, or character data, depending on its configuration.

In Aspose.HTML for Java, this mechanism is represented by the MutationObserver class. It observes changes made to the DOM of the loaded document; it does not continuously monitor the source file or a remote webpage for external updates.

How to Observe DOM Changes in Java

The following Java example observes the <body> element and its descendants. It then appends a paragraph and a text node. The callback iterates through the resulting mutation records and prints each added node.

  1. Create an HTMLDocument.
  2. Create a MutationObserver and pass it a MutationCallback that processes mutation records.
  3. Create a MutationObserverInit object and enable the required mutation types and observation scope.
  4. Call observe() with the document body and the observer configuration.
  5. Modify the DOM by creating a paragraph, appending it to the body, and adding a text node to the paragraph.
  6. Read the added nodes from each MutationRecord in the callback.
  7. Keep the process running long enough for the queued observer callback to execute.

The example configures these options:

OptionEffect
ChildListReports nodes added to or removed from an observed node.
SubtreeExtends observation from the target node to its descendants.
CharacterDataReports changes to the data of text and other character-data nodes.

For the node additions performed by this example, ChildList detects the changes and Subtree allows the observer on <body> to detect the text node added inside the new paragraph. Although CharacterData is enabled in the code, it becomes relevant when the data of an existing text node is changed.

 1// Monitor DOM tree changes using MutationObserver API in Aspose.HTML for Java
 2
 3// Create an empty HTML document
 4try (HTMLDocument document = new HTMLDocument()) {
 5
 6    // Create an instance of the MutationObserver class
 7    MutationObserver observer = new MutationObserver(new MutationCallback() {
 8
 9        @Override
10        public void invoke(com.aspose.html.utils.collections.generic.IGenericList<MutationRecord> mutations, MutationObserver mutationObserver) {
11            for (int i = 0; i < mutations.size(); i++) {
12                MutationRecord record = mutations.get_Item(i);
13                for (Node node : record.getAddedNodes().toArray()) {
14                    System.out.println("The '" + node + "' node was added to the document.");
15                }
16            }
17        }
18    });
19
20    // Configure options for the MutationObserver
21    MutationObserverInit config = new MutationObserverInit();
22    config.setChildList(true);
23    config.setSubtree(true);
24    config.setCharacterData(true);
25
26    // Pass to observer the target node to observe with the specified configuration
27    observer.observe(document.getBody(), config);
28
29    // Now, we are going to modify DOM tree to check
30    // Create a paragraph element and append it to the document body
31    Element p = document.createElement("p");
32    document.getBody().appendChild(p);
33
34    // Create a text and append it to the paragraph
35    Text text = document.createTextNode("Hello, World!");
36    p.appendChild(text);
37
38    System.out.println("Waiting for mutation. Press any key to continue...");
39    System.in.read();
40}

The callback is queued rather than called synchronously inside each DOM modification. The example waits for keyboard input so the Java process remains active while the observer receives the mutation records.

Common MutationObserver Issues

IssueCauseFix
The callback is not calledThe enabled options do not match the DOM change, or the process ends before the queued callback runs.Enable the relevant mutation type and allow the callback to execute before ending the process.
Changes inside nested elements are missedOnly the target’s direct children are being observed.Enable Subtree when descendant changes should also be reported.
Text changes are not reportedChanges to existing text-node data are not enabled.Enable CharacterData when the application modifies text-node data.
A record produces no console outputThe callback examines only addedNodes, while the record describes an attribute, character-data, or removal change.Inspect the mutation record type and the collection that corresponds to the expected change.

Recommendations

You can download the complete examples and data files from GitHub.

Related Articles