This is a more advanced example of using the Apache PDFBox library. It demonstrates how to add some effects (called annotations in PDF terms) to text, namely highlighting, underlining, squiggly underlining and strikethrough. It's a bit tricky because these can't be applied to text as it is added to the document, but must be added later after a page is otherwise complete. (Note that the squiggly underline effect only works with the as-yet-unreleased PDFBox 3.)

If you're new to PDFBox, start with the PdfBox example rather than this one.

For highlighting, also see

import java.util.List;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationTextMarkup;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;

public class SimpleAnnotation {

    // the text we want to highlight (or annotate, as the PDF lingo calls it)
    final static String[] texts = { "Underline""Strikeout""Squiggly""Highlight""Strikeout Underline" };
    // the effects we have - so the last phrase in the above line will have two effects applied
    final static String[] annotations = { "Underline""Strikeout""Squiggly""Highlight" };

    public static void main (String[] args) throws Exception {
        String outputFileName = "SimpleAnnotation.pdf";
        if (args.length > 0)
            outputFileName = args[0];

        // Create a document and add a page to it
        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
            // PDRectangle.LETTER and others are also possible
        PDRectangle rect = page.getMediaBox();
            // rect can be used to get the page width and height

        // Start a new content stream which will "hold" the to be created content
        PDPageContentStream cos = new PDPageContentStream(document, page);

        // Define a text content stream using the selected font, move the cursor and draw some text
        cos.setFont(PDType1Font.HELVETICA, 14);

        int line = 0;

        for (String str : texts) {
            cos.newLineAtOffset(100, rect.getHeight() - 50*(++line));

        // Make sure that the content stream is closed

        // some ornamental extras for some of the text: highlighting, strikethrough, underline and squiggly underline
        PDFTextStripper stripper = new MyAnnotator();
        Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());
        stripper.writeText(document, dummy);

        // Save the results and ensure that the document is properly closed;

    private static class MyAnnotator extends PDFTextStripper {

        public MyAnnotator() throws IOException {

        protected void writeString (String string, List<TextPosition> textPositions) throws IOException {
            float posXInit = 0, posXEnd = 0, posYInit = 0, posYEnd = 0, width = 0, height = 0, fontHeight = 0;

            for (String anno : annotations) {
                if (string.contains(anno)) {
                    posXInit = textPositions.get(0).getXDirAdj();
                    posXEnd  = textPositions.get(textPositions.size() - 1).getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidth();
                    posYInit = textPositions.get(0).getPageHeight() - textPositions.get(0).getYDirAdj();
                    posYEnd  = textPositions.get(0).getPageHeight() - textPositions.get(textPositions.size() - 1).getYDirAdj();
                    width    = textPositions.get(0).getWidthDirAdj();
                    height   = textPositions.get(0).getHeightDir();

                    List<PDAnnotation> annotationsInPage = document.getPage(this.getCurrentPageNo() - 1).getAnnotations();
                    PDAnnotationTextMarkup markup = null;
                    // choose any color you want, they can be different for each annotation
                    PDColor color = new PDColor(new float[]{ 11 / 255F1 }, PDDeviceRGB.INSTANCE);
                    switch (anno) {
                        case "Underline":
                            markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_UNDERLINE);
                        case "Strikeout":
                            markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_STRIKEOUT);
                        case "Squiggly":
                            markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_SQUIGGLY);
                        case "Highlight":
                            markup = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);

                    PDRectangle position = new PDRectangle();
                    position.setUpperRightY(posYEnd + height);

                    float quadPoints[] = {posXInit, posYEnd + height + 2, posXEnd, posYEnd + height + 2, posXInit, posYInit - 2, posXEnd, posYEnd - 2};