Mark Stephens Mark has been working with Java and PDF since 1999 and is a big NetBeans fan. He enjoys speaking at conferences. He has an MA in Medieval History and a passion for reading.

Allowing users to extend your Java code – Option 1 Custom listeners

1 min read

When you have an application there is a delicate balance between allowing users to tweak the application to match their needs while not making the code unmaintainable. I thought that a serious of articles on how we are trying to do this in our JPedal PDF library might be of general interest.

The balance we have tried to strike is to essentially keep the user at the top level API – so we can alter the internals at will as the code develops – but provide several ways to configure or alter this functionality. This article explains how we provide custom listeners as a means to to do this.

By specifying an Interface we can define a ‘possible’ object which the user has instance and pass into our application, It can have clear, documented behaviour and allow the user to obtain information or effect the way the code works. Let work it through with an example which involves 3 steps.

Let’s say that the developer using our application wants to know whether the page is being drawn or not.

1. We need an interface

public interface RenderChangeListener {

/**Fired when rendering starts.*/public void renderingStarted(int pageNumber);

/**Fired when rendering ends.*/public void renderingEnded(int pageNumber);

The user can now create their own version of this Interface.

2. We need to pass in the user instance

There are several ways to do this. We could add a pair of listeners along the lines of

public void addRenderChangeListener(RenderChangeListener l);

public void removeRenderChangeListener(RenderChangeListener l);

In our case, the main class (PdfDecoder) has a lot of method already and we are trying to avoid clutter. We have also added a route to pass in instances of agreed Interfaces

public void addExternalHandler(Object newHandler, int type);

where type is a static int defined in the class org.jpedal.external.Options

pdfDecoder.addExternalHandler(myRenderListener, Options.RenderChangeListener);

3. Add some calls into our code

The last step is to add some calls into our code to all this instance if present. So we need to plumb in the methods into our code. As it is tracking the paint events, we add it to the paintComponent method, which calls our painting code in threadSafePaint(g2);

public void paintComponent(Graphics g) {

if(customRenderChangeListener!=null) //call custom class if present

if (SwingUtilities.isEventDispatchThread()) {


if(customRenderChangeListener!=null) //call custom class if present

} else {
final Graphics g2 = g;
final int page=pageNumber;
final Runnable doPaintComponent = new Runnable() {
public void run() {


if(customRenderChangeListener!=null) //call custom class if present


So now we have a way that the developer can interact with our code in a controlled way. We can even add methods which return values allowing the user to replace or control functionality. And if you want to use the new Interface in our code, it will be in the JPedal February release…

Do you need to solve any of these problems in Java?

Convert PDF to HTML5
Convert PDF to HTML5
Convert PDF to SVG
Convert PDF to SVG
View Forms in the browser
View Forms in the browser
Java PDF Reader and Viewer
View PDF Documents
Convert PDF to image
Convert PDF to image
Extract Text from PDF
Extract Text from PDF
Read/Write images in Java
Read/Write images
Replace ImageIO
Replace ImageIO
Convert Image to PDF
Convert Image to PDF
Mark Stephens Mark has been working with Java and PDF since 1999 and is a big NetBeans fan. He enjoys speaking at conferences. He has an MA in Medieval History and a passion for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *

IDRsolutions Ltd 2021. All rights reserved.