Jon Carmignani
Jon Carmignani

Reputation: 23

How to add a custom/dynamic target to a hyperlink

I am using jasperreports-6.14.0. As far as I can tell, there is only one way to add a custom hyperlink target to anything that allows hyperlinks. Please tell me there is a better way (other than putting javascript into my reference expression).

  1. Implement the net.sf.jasperreports.engine.export.JRHyperlinkTargetProducer interface, looking in the hyperlink parameters for a specific, named parameter to return as your target string.
  2. Extend net.sf.jasperreports.engine.export.HtmlExporter and set its targetProducerFactory protected field as an instance of your new custom hyperlink target producer.

It looks like this is the only option, but it just feels like there should be a way to skip step 2 by just setting the targetProducerFactory. It's almost like the Jasper devs started to do exactly that and thought "Nah, I just don't feel right about that. Let's take it out."

I am going to do the above unless some kind soul can show me a better way.

Upvotes: 0

Views: 267

Answers (1)

dada67
dada67

Reputation: 5083

Custom target producers are loaded as extensions by the HTML exporter. You can register extensions either programmatically by creating the HTML exporter using your own JasperReportsContext instance, or package the extension in a jar and have it autodetected by the exporter.

If you control the HTML exporter creation you can pass the extension programmatically:

JRHyperlinkTargetProducer targetProducer = new JRHyperlinkTargetProducer() {            
    @Override
    public String getHyperlinkTarget(JRPrintHyperlink hyperlink) {
        return "foo";
    }
};
JRHyperlinkTargetProducerMapFactory targetProducerFactory = new JRHyperlinkTargetProducerMapFactory();
targetProducerFactory.addProducer("mycustomtarget", targetProducer);

SimpleJasperReportsContext jasperReportsContext = new SimpleJasperReportsContext();
jasperReportsContext.setExtensions(JRHyperlinkTargetProducerFactory.class, 
        Collections.singletonList(targetProducerFactory));

HtmlExporter htmlExporter = new HtmlExporter(jasperReportsContext);

If you want to have the extension autodected you need to create a jar that contains a class like this:

public class CustomTargetProducerExtension implements ExtensionsRegistryFactory {
    @Override
    public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties) {
        JRHyperlinkTargetProducer targetProducer = new JRHyperlinkTargetProducer() {            
            @Override
            public String getHyperlinkTarget(JRPrintHyperlink hyperlink) {
                return "bar";
            }
        };
        JRHyperlinkTargetProducerMapFactory targetProducerFactory = new JRHyperlinkTargetProducerMapFactory();
        targetProducerFactory.addProducer("mycustomtarget", targetProducer);
        
        return new SingletonExtensionRegistry<>(JRHyperlinkTargetProducerFactory.class, targetProducerFactory);
    }
}

And put a jasperreports_extension.properties resource in the root of the jar containing the line:

net.sf.jasperreports.extension.registry.factory.my.custom.target.producer=<package>.CustomTargetProducerExtension

Then your custom target producer would be automatically detected for elements that have hyperlinkTarget="mycustomtarget"

Upvotes: 1

Related Questions