Expand my Community achievements bar.

SOLVED

Generate a PDF in CQ5 with an API

Avatar

Level 4

Is there an API deployed in CQ5 we can use to manipulate PDFs?  I found a bunch of bundles in the OSGi console, but saw no documentation on how to use these libraries.

 

Thank you

1 Accepted Solution

Avatar

Correct answer by
Level 10

Here is more information about this use case (some good news if you are using CQ 5.5 or lower-- Adobe CQ already has PDFBox part of the OSGi service container). This means that you can simply build your OSGi Java bundle. If you are using AEM 5.6 - you have to create an OSGi bundle fragment that contains the PDFBOX JAR and deploy to AEM 5.6.

Consider this example for a custom service. Here is the interface:
 

package com.aem.pdf.sample;

public interface PDFService {
    
    public String createPDF(String value) ; 

}

 

Here is the Implementation class that create a PDFBox PDFDocument instance:
 

package com.aem.pdf.sample;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
 
import javax.jcr.Repository; 
import javax.jcr.SimpleCredentials; 
import javax.jcr.Node; 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
  
import org.apache.jackrabbit.commons.JcrUtils;
 
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
 
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import javax.jcr.RepositoryException;
import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.jcr.api.SlingRepository;
 
import javax.jcr.Session;
import javax.jcr.Node; 

//PDFBOX 
import org.apache.pdfbox.pdmodel.PDDocument;


//This is a component so it can provide or consume services
@Component
 
@Service
public class PSFServiceImpl implements PDFService {

    
    /** Default log. */
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
         
    private Session session;
             
    @Reference
    private SlingRepository repository;
         
    public void bindRepository(SlingRepository repository) {
        this.repository = repository; 
    }
    
    
    @Override
    public String createPDF(String value) {
        // This custom AEM service creates a PDF document using PDFBOX API and stores the PDF in the AEM JCR
        
        try
        {
            //Create the PDFBOx Object
            // Create a new empty document
            PDDocument document = new PDDocument();
            
            session = this.repository.loginAdministrative(null);
            
             //DO SOMETHING WITH THE PDFBOX OBJECT
            //....
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

}

Make sure that you get this PDFBOX dependency into your Maven POM:

 <dependency>
        <groupId>org.apache.pdfbox</groupId>
        <artifactId>pdfbox</artifactId>
        <version>1.6.0</version>
    </dependency>

 

Build your OSGI using MVN:
MVN install clean

Deploy your bundle -- look at this -- the OSGi bundle that contains the PDFBOX API in an Active state:

[img]OSGi.png[/img]

So basically this is an outline of what you need to do to get PDF functionality into AEM and do something. For example -- you can create a new PDF like this:
 

// Create a document and add a page to it
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage( page );

// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.HELVETICA_BOLD;

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

// Define a text content stream using the selected font, moving the cursor and drawing the text "Hello World"
contentStream.beginText();
contentStream.setFont( font, 12 );
contentStream.moveTextPositionByAmount( 100, 700 );
contentStream.drawString( "Hello World" );
contentStream.endText();

// Make sure that the content stream is closed:
contentStream.close();

// Save the results and ensure that the document is properly closed:
document.save( "Hello World.pdf");
document.close();

Good luck! An AEM community article will be produced that contains this information very soon. See http://scottsdigitalcommunity.blogspot.ca/2013/09/creating-custom-adobe-experience.html.

 

 

 

 


 

View solution in original post

2 Replies

Avatar

Level 10

You can create a custom CQ OSGi service using a Java API such as Apache PDF BOX API to create an AEM service that is able to manipulate PDFs. I am adding this to our community list of articles to publish. Keep an eye out for this soon. This is one of the powerful features of CQ -- to create OSGi Java based custom services. 

To see an example of creating a custom service that works with a Java Excel API (similiar use case) to create a custom CQ Excel service, see this community article. 

http://scottsdigitalcommunity.blogspot.ca/2013/08/creating-custom-excel-service-for-adobe.html

HTH

Avatar

Correct answer by
Level 10

Here is more information about this use case (some good news if you are using CQ 5.5 or lower-- Adobe CQ already has PDFBox part of the OSGi service container). This means that you can simply build your OSGi Java bundle. If you are using AEM 5.6 - you have to create an OSGi bundle fragment that contains the PDFBOX JAR and deploy to AEM 5.6.

Consider this example for a custom service. Here is the interface:
 

package com.aem.pdf.sample;

public interface PDFService {
    
    public String createPDF(String value) ; 

}

 

Here is the Implementation class that create a PDFBox PDFDocument instance:
 

package com.aem.pdf.sample;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
 
import javax.jcr.Repository; 
import javax.jcr.SimpleCredentials; 
import javax.jcr.Node; 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
  
import org.apache.jackrabbit.commons.JcrUtils;
 
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
 
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import javax.jcr.RepositoryException;
import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.jcr.api.SlingRepository;
 
import javax.jcr.Session;
import javax.jcr.Node; 

//PDFBOX 
import org.apache.pdfbox.pdmodel.PDDocument;


//This is a component so it can provide or consume services
@Component
 
@Service
public class PSFServiceImpl implements PDFService {

    
    /** Default log. */
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
         
    private Session session;
             
    @Reference
    private SlingRepository repository;
         
    public void bindRepository(SlingRepository repository) {
        this.repository = repository; 
    }
    
    
    @Override
    public String createPDF(String value) {
        // This custom AEM service creates a PDF document using PDFBOX API and stores the PDF in the AEM JCR
        
        try
        {
            //Create the PDFBOx Object
            // Create a new empty document
            PDDocument document = new PDDocument();
            
            session = this.repository.loginAdministrative(null);
            
             //DO SOMETHING WITH THE PDFBOX OBJECT
            //....
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

}

Make sure that you get this PDFBOX dependency into your Maven POM:

 <dependency>
        <groupId>org.apache.pdfbox</groupId>
        <artifactId>pdfbox</artifactId>
        <version>1.6.0</version>
    </dependency>

 

Build your OSGI using MVN:
MVN install clean

Deploy your bundle -- look at this -- the OSGi bundle that contains the PDFBOX API in an Active state:

[img]OSGi.png[/img]

So basically this is an outline of what you need to do to get PDF functionality into AEM and do something. For example -- you can create a new PDF like this:
 

// Create a document and add a page to it
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage( page );

// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.HELVETICA_BOLD;

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

// Define a text content stream using the selected font, moving the cursor and drawing the text "Hello World"
contentStream.beginText();
contentStream.setFont( font, 12 );
contentStream.moveTextPositionByAmount( 100, 700 );
contentStream.drawString( "Hello World" );
contentStream.endText();

// Make sure that the content stream is closed:
contentStream.close();

// Save the results and ensure that the document is properly closed:
document.save( "Hello World.pdf");
document.close();

Good luck! An AEM community article will be produced that contains this information very soon. See http://scottsdigitalcommunity.blogspot.ca/2013/09/creating-custom-adobe-experience.html.