Expand my Community achievements bar.

Radically easy to access on brand approved content for distribution and omnichannel performant delivery. AEM Assets Content Hub and Dynamic Media with OpenAPI capabilities is now GA.
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.