avatar
generate PDF from AEM through code implementation AEM

• Be assumption that there is existed event in Call to action (AEM)

export default class <Call To Action> extends Component {
    private memberSelector = '<prefix defined for Servlet detect>';

    private $component;

    constructor(cmp: HTMLElement) {
        super(cmp);

        this.$component = $(cmp);
        this.generatePDFasFormat();
    }

    private generatePDFasFormat = () => {
        const <Call to Action> = this.$cmp;
        const button = <Call to Action>.querySelector('.btn-generate-membership') as HTMLElement;
        button.addEventListener('click', (event) => {
            this.generateMembershipInfo(event);
        });
    };  

    private generateMembershipInfo = (event: MouseEvent): void => {  
        const targetElement = event.target as HTMLElement;
        const resource = this.$component.data('resource') as string;
        const endpoint = `${resource}.${this.memberSelector}.json`;

        targetElement.classList.add('disabled');
        const pdfWindow = window.open('', '_blank');

        if (pdfWindow) {
            pdfWindow.document.write('<p>Please wait while we retrieve your document...</p>');
            $.get(endpoint)
              .done((data: string): void => {
                  const servletUrl = `/bin/pdf/pdf-statement?path=${data}`;
                  pdfWindow.location = servletUrl.replace(/"/g, ""); // eslint-disable-line
                  targetElement.classList.remove('disabled');
              })
              .catch((err): void => {
                  pdfWindow.document.body.innerHTML = '';
                  pdfWindow.document.write('<p>We were unable to retrieve your document.</p>');
                  logger.error(err);
              })
        }
    };
}

• Sling Servlets in AEM

@Component(immediate = true, service = Servlet.class,
        property = {
                SERVICE_DESCRIPTION + <Component Name>Servlet.SERVLET_SERVICE_DESCRIPTION,
                SLING_SERVLET_RESOURCE_TYPES + <Component Name>Servlet.RESOURCE_TYPE,
                SLING_SERVLET_METHODS + "=" + HttpConstants.METHOD_GET,
                SLING_SERVLET_SELECTORS + <Component Name>Servlet.SELECTOR,
                SLING_SERVLET_EXTENSIONS + "=" + Constants.EXTENSION_JSON
        })
public class <Component Name>Servlet extends SlingSafeMethodsServlet {
    public static final String SERVLET_SERVICE_DESCRIPTION = "<Description for Servlets>";
public static final String RESOURCE_TYPE = "=flagtick/components/content/<Component Name (root name)>";
    public static final String SELECTOR = "=<prefix defined for Servlet detect>";

    private static final long serialVersionUID = 1L;

    @Reference
    private transient FlagtickInformationService flagtickInformationService;

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
        throws IOException {

        if (flagtickInformationService == null) {
            response.setStatus(HTTP_UNAVAILABLE);
            response.getWriter().write("Service unavailable");
            return;
        }

        final String userID = CookieUtils.getCookieValue(request,        Constants.USER_ID_PARAMETER);
        if (StringUtils.isBlank(personID)) {
            String errorMsg = "No user ID found for the request";
            response.getWriter().append(errorMsg);
            response.setStatus(HTTP_BAD_REQUEST);
            return;
        }

        final String userStatus = CookieUtils.getCookieValue(request,  Constants.USER_STATUS_COOKIE_NAME);
        if (StringUtils.isBlank(userStatus)) {
           String errorMsg = "No User Status Token found for the request";
           response.getWriter().append(errorMsg);
           response.setStatus(HTTP_BAD_REQUEST);
           return;
        }

        final String token = CookieUtils.getCookieValue(request,  Constants.TOKEN_COOKIE_NAME);
        if (StringUtils.isBlank(token)) {
           String errorMsg = "No JWT Token found for the request";
           response.getWriter().append(errorMsg);
           response.setStatus(HTTP_BAD_REQUEST);
           return;
        }

        Map<String, String> params = new HashMap<>();
        params.put(Constants.USER_ID_PARAMETER, userID);
        params.put(Constants.USER_STATUS_COOKIE_NAME, userStatus);
        String documentUrl = flagtickInformationService.saveDocumentInDAM(params, token);

        // if requested parameters don't exist or an invalid combination was requested
        if (StringUtils.isEmpty(documentUrl)) {
           response.setStatus(HTTP_BAD_REQUEST);
           response.getWriter().write("Invalid request parameters");
           return;
        }
        
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.writeValue(response.getWriter(), documentUrl);
    }
}

• Create Interface in Java as named FlagtickInformationService

public interface FlagtickInformationService {
    String saveDocumentInDAM(Map<String, String> params, String token);
    void deleteDocumentInDAM(String personId);
}

• Integrate FlagtickInformationServiceImpl based interface named FlagtickInformationService as below:

@Component(service = FlagtickInformationService.class, immediate = true)
public class FlagtickInformationServiceImpl implements FlagtickInformationService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(MembershipInformationServiceImpl.class);
    private static final String ROOT_PATH = "/content/dam/flagtick/<prefix defined for Servlet detect>";

    @Reference
    private ResourceResolverService resourceResolverService;

    @Reference
    private FlagtickIntegrationService flagtickIntegrationService;

    @Reference
    private QueryBuilder builder; 

    @Override
    public String saveDocumentInDAM(Map<String, String> params, String token) {
        Binary binary = null;
        String pdfPath = StringUtils.EMPTY;   
        try (ResourceResolver resourceResolver = resourceResolverService.getResourceResolver()) {
            final Session session = resourceResolver.adaptTo(Session.class);
            final AssetManager assetManager = resourceResolver.adaptTo(AssetManager.class);
            if (null != session && null != assetManager) {
                final Node rootFolder = JcrUtils.getOrCreateByPath(ROOT_PATH, NT_SLING_FOLDER, session);
                byte[] bytes = flagtickIntegrationService.generateServicePDF(params, token);
                binary = new BinaryImpl(bytes);
                final Asset pdfAsset = assetManager.createOrUpdateAsset(
                        rootFolder.getPath() + SLASH + getDocumentName(params.get(USER_ID_PARAMETER)),
                        binary, "application/pdf", true);
                if (null != pdfAsset) {
                    pdfPath = pdfAsset.getPath();
                }
                session.save();
            }
        } catch (LoginException | RepositoryException e) {
            e.printStackTrace();
            LOGGER.error("Exception occurred: {}", e.getMessage());
        } finally {
            if (binary != null) {
                binary.dispose();
            }
        }
        return pdfPath;
    }

    public void deleteDocumentInDAM(String userId) {
        try (ResourceResolver resourceResolver = resourceResolverService.getResourceResolver()) {
            final Session session = resourceResolver.adaptTo(Session.class);
            if (session != null){
                Map<String, String> map = new HashMap<>();
                map.put("path", ROOT_PATH);
                map.put("type", "dam:Asset");
                map.put("nodename","*"+userId+"*");
                map.put("nodename.operation","like");
                map.put("relativedaterange.property","jcr:created");
                map.put("relativedaterange.upperBound","-1d");
                map.put("p.limit","-1");
                Query query = builder.createQuery(PredicateGroup.create(map),session);
                SearchResult searchResult = query.getResult();
                for(Hit hit : searchResult.getHits()) {
                    String path = hit.getPath();
                    session.removeItem(path);
                    if (session.hasPendingChanges()) {
                        session.save();
                    }
                }
            }
        } catch (LoginException | RepositoryException e) {
            e.printStackTrace();
            LOGGER.error("Exception occurred: {}", e.getMessage());
        }
    }

    private String getDocumentName(final String userId) {
        return UUID.randomUUID() + DASH_CHARACTER + userId + ".pdf";
    }
}  

• Integrate FlagtickIntegrationService.java

public interface FlagtickIntegrationService {
    byte[] generateServicePDF(Map<String, String> params, String token);
}

• Integrate FlagtickIntegrationServiceImpl.java

@Component(
        immediate = true,
        service = FlagtickIntegrationService.class
)
@Designate(ocd = FlagtickIntegrationServiceImpl.Config.class)
public class FlagtickIntegrationServiceImpl implements FlagtickIntegrationService {

    public static final String BEARER = "Bearer ";
    public static final String CLIENT_PROTOCOL_EXCEPTION = "Client protocol exception";
    public static final String ERROR_WHILE_PARSING_THE_RESPONSE = "Error while parsing the response";
    public static final String UNABLE_TO_CREATE_URI = "Unable to create URI";


    public static final String IN_OUT_EXCEPTION = "In out exception";
    private static final Logger LOGGER = LoggerFactory.getLogger(FlagtickIntegrationServiceImpl.class);
    private static final String BAD_REQUEST_ERROR_MSG = "Bad Request - Incorrect or invalid parameters";
    private static final String BAD_GATEWAY_ERROR_MSG = "Bad Gateway - Internal server error";

    private String servicePDFEndpoint;
    private String apiKey;

    @Activate
    protected void activate(Config config) {
        servicePDFEndpoint = config.servicePDFEndpoint();
        apiKey = config.apiKey();
    }

    @Override
    public byte[] generateServicePDF(Map<String, String> params, String userToken) {
        URI uri;
        try {
            uri = buildParameterizedUri(servicePDFEndpoint, params);
        } catch (URISyntaxException e) {
            LOGGER.error(UNABLE_TO_CREATE_URI, e);
            return new byte[0];
        }
        HttpGet request = createAuthenticatedGetRequest(apiKey, uri);
        request.addHeader(HttpHeaders.AUTHORIZATION, BEARER + userToken);

        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(request)) {
            if (response.getStatusLine().getStatusCode() == HTTP_BAD_REQUEST) {
                LOGGER.error(BAD_REQUEST_ERROR_MSG);
                return new byte[0];
            }
            if (response.getStatusLine().getStatusCode() == HTTP_BAD_GATEWAY) {
                LOGGER.error(BAD_GATEWAY_ERROR_MSG);
                return new byte[0];
            }

            if (response.getStatusLine().getStatusCode() == HTTP_INTERNAL_ERROR) {
                LOGGER.error("Internal Server Error");
                return new byte[0];
            }

            HttpEntity entity = response.getEntity();

            if (entity != null) {
                return EntityUtils.toByteArray(entity);
            }
        } catch (ClientProtocolException e) {
            LOGGER.error(CLIENT_PROTOCOL_EXCEPTION, e);
        } catch (IOException e) {
            LOGGER.error(ERROR_WHILE_PARSING_THE_RESPONSE, e);
        }
        return new byte[0];
    }

    private HttpGet createAuthenticatedGetRequest(String apiKey, URI uri) {
        HttpGet request = new HttpGet(uri);
        request.addHeader(Constants.HEADER_CONTENT_TYPE, Constants.CONTENT_TYPE_JSON);
        request.addHeader(Constants.X_API_KEY, apiKey);
        return request;
    }

    private HttpPost createAuthenticatedPostRequest(String apiKey, URI uri) {
        HttpPost request = new HttpPost(uri);
        request.addHeader(Constants.HEADER_CONTENT_TYPE, Constants.CONTENT_TYPE_JSON);
        request.addHeader(Constants.X_API_KEY, apiKey);
        return request;
    }

    private URI buildParameterizedUri(String endpoint, Map<String, String> paramMap) throws URISyntaxException {
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        paramMap.entrySet()
                .forEach(entry -> list.add(
                        new BasicNameValuePair(entry.getKey(), entry.getValue()
                        )));
        URI uri = new URIBuilder(endpoint)
                .add Parameters(list)
                .build();
        return uri;
    }

    @ObjectClassDefinition(
            name = "FLAGTICK - Flagtick Service Configurations",
            description = "Flagtick Service Configurations"
    )
    protected @interface Config {
        @AttributeDefinition(
                name = "Service PDF Endpoint",
                description = "URL endpoint for service pdf endpoint",
                type = AttributeType.STRING
        )
        String servicePDFEndpoint();

        @AttributeDefinition(
                name = "API key",
                description = "API key for Flagtick",
                type = AttributeType.STRING
        )
        String apiKey();
    }
}   

• Reference link Creating your custom OSGi Configuration

{
  "generatePDFEndpoint": "https://<UUID.randomUUID()>.execute-api.us-west-2.amazonaws.com/dev/membershipInformationPDF",
  "apiKey":"<API Key Generate Random String - UUID.randomUUID()>"
}

• Update API Gateway as named <UUID.randomUUID()>

• Create Endpoint

• Setup Lambda function and link to API Gateway

Note: Please click checkbox as named Use Lambda Proxy Integration

• Generate PDF Resource with Root Path (/)

• Double Click Method Request

+ API Key Required (false => true)

+ URL Query String Parameters

• Deploy API (The steps should be run again after whatever changes for Resources tab)

• Testing API Gateway First

• Create Lambda function as Java 8 on Amazon Linux 1

+ Runtime Java 8 on Amazon Linux 1

+ Handler example.Hello::handleRequest

+ Architecture x86_64

• Check connection with API Gateway from Dashboard Lambda flagtickInfoPDF function

• Create AWS Serverless Application from Intellij IDE

• Create Self Template from Soft named ...

• Create Template by Apache PDFBox

mvn archetype:generate -DgroupId=com.ap.pdfboxgenerate -DartifactId=pdf-box-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

• Configure Pdfbox Library

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.7</maven.compiler.source>
  <maven.compiler.target>1.7</maven.compiler.target>
  <pdfbox.version>3.0.0-alpha2</pdfbox.version>
</properties>

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>${pdfbox.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>fontbox</artifactId>
    <version>${pdfbox.version}</version>
</dependency>

Note: Run mvn clean install to install dependencies as above. Then, Right Click => Maven => Reload Project.

• Establish Main Function to Generate PDF Template: Reference link here.

You need to login to do this manipulation!