Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

Issues with PDF Viewer

Avatar

Level 4

Hello All - We have extended the PDF viewer core component into our app : /apps/app-name/ by following the below medium article and also created the "Content Aware configuration" under /conf/app-name/ and added the property "sling:configRef" that points to Context Aware Config path under /content/site/.

 

https://medium.com/adobetech/pdfs-in-aem-embed-pdfs-into-your-pages-with-pdf-viewer-7115c60b3c34

 

After we made all the requirement changes and specify the PDF path in the dialog, the component is not rendering the PDF. The component is not editable and we are able to open the dialog only from Side Panel -> Content Tree. Please see the attached screenshot. Can someone tell me what could be the issue?

 

aemninja_0-1618974019534.png

 

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @aemninja,

One of the possible cause would be the clientId used in sling:configs. Can you confirm if it is the valid one generated for your application. 

If yes, you can cross check directly by placing the markup(code snippet available in below link) in any component or in base page component. (by hardcoding the clientId and specific document instead of via PDF viewer component. Based on this result, we can narrow down the issue)

More details related to this in this documentation - https://medium.com/adobetech/easily-embed-pdf-into-your-website-using-adobe-document-cloud-view-sdk-...

 

View solution in original post

22 Replies

Avatar

Correct answer by
Community Advisor

Hi @aemninja,

One of the possible cause would be the clientId used in sling:configs. Can you confirm if it is the valid one generated for your application. 

If yes, you can cross check directly by placing the markup(code snippet available in below link) in any component or in base page component. (by hardcoding the clientId and specific document instead of via PDF viewer component. Based on this result, we can narrow down the issue)

More details related to this in this documentation - https://medium.com/adobetech/easily-embed-pdf-into-your-website-using-adobe-document-cloud-view-sdk-...

 

Avatar

Level 4
@Vijayalakshmi_S - Thanks for your inputs. The clientId is the valid one. Will check again by hardcoding the clientId and check. Can you please tell me on how can we handle the clientId config i.e Context Aware Configuration for Publish & Site Domain ?

Avatar

Community Advisor

Hi @aemninja,

In general, content aware configuration(CA-config) are specific to paths or tenants and not specific to run modes. 

Since PDF viewer component works based on CA-config, there exist an open issue highlighting this concern. 

https://github.com/adobe/aem-core-wcm-components/issues/1144

The workaround suggested there is to use "Apache Sling Context-Aware Configuration - Override"

Details about this from Sling docs - https://sling.apache.org/documentation/bundles/context-aware-configuration/context-aware-configurati...

Example :

One of the ways for override is to use OSGI Factory configuration (as mentioned in above Sling doc)

Create OSGI Factory config specific to run mode and override the CA-config accordingly. 

Vijayalakshmi_S_0-1619018231614.png

Avatar

Level 4

@Vijayalakshmi_S- I have created a new runmode for author and override the configuration but it is not picking it up. Screenshot attached. is there an issue with the syntax? if I specify the configs directly under /conf/ it is working but I wanted to specify different clientId based on runmodes. Can you advise/

 

aemninja_0-1619040300009.png

 

Avatar

Community Advisor

@aemninja 

Yes, the value for "overrides" is incorrect.(it is a string property so no need to enclose within quotes explicitly) Please use like the below and make sure enabled[Boolean] is set to true

 

Vijayalakshmi_S_0-1619059288683.png

 

For how many ever environments/runmodes you have different clientId, create this OSGI factory config for respective runmode and override clientId accordingly as above.

You can cross verify which clientId/CA-config value is picked in an environment by navigating to OSGI console -> Sling -> Context-Aware Configuration (http://localhost:4502/system/console/slingcaconfig) of that instance -> fulfil the fields and hit "Resolve".

Avatar

Level 4

@Vijayalakshimi_S - I have added the below said entry in author run mode but it is still not working. I am not sure why it is still failing.

 

aemninja_0-1619065542759.png

 

If I put back the configs in /conf/site, it is working and if I remove the entries, it stopped working. Basically I don't want to keep the configs under conf. We have different environments and wanted to keep different clientIds for different instances.

 

If I verify it under "/system/console/slingcaconfig", it is pointing to /conf/ setup only. Can you advise?

Avatar

Community Advisor

@aemninja,

There is still a small typo in your overrides value.(You have added "/" before config class name - before com.adobe...) I have attached your screenshot highlighting the same. Please remove that and check, It should work. 

Vijayalakshmi_S_0-1619096909493.png

Attaching my working screenshot for reference:

Vijayalakshmi_S_1-1619097008888.png

Vijayalakshmi_S_2-1619097073211.png

Avatar

Level 4
@Vijayalakshmi_S - It is working. Thank you so much for your inputs. Appreciate it. Just a question, we need to generate the clientId for each environment, i.e author, publish & site.com. for the website, where should be keep the clientId (As we keep the publish clientId in config.publish and will be picked up if we access the publish url (aem publish instance). Not sure where it will be picked up (run mode) for site.com.

Avatar

Community Advisor

@aemninja,

Thanks for the confirmation.

  • If you have OOTB runmodes alone like author and publish
    • config.publish should point to clientId of actual PROD domain (In which case, testing from being in AEM publish instance application server might not work)
  • If you have custom runmodes in the name of environment types like dev, stage and prod,
    • config.publish.prod can point to clientId of actual PROD domain (Rest all can have its own clientId. Here again testing from application server might not work just that testing from publish application server will be assured from pre prod/stage environment)

Avatar

Level 4
@Vijayalakshmi_S - Thanks again. We have two domains and the same content is served for both the domains. In this case, I need to generate two clientIds for the domains. is there any mechanism to specify two clientIds for the PDF viewer to support both the domains. I tried by keeping the another sling:OsgiConfig with different suffix in config.publish folder but it is not working. is there a way to handle this usecase?

Avatar

Community Advisor

Hi, @aemninja,

With the existing OOTB implementation of PDFViewer core component, clientID from CA-Config is picked from com.adobe.cq.wcm.core.components.internal.services.pdfviewer.PdfViewerCaConfig and given that overriding this config value is feasible via OSGI config(that works based on run modes), we can't restrict things specific to domains here. 

 

However, getClientId() method in PDFViewer core component can be overridden (custom implementation of Core PDFViewer component can be written using Sling Model Delegation Pattern) considering your project specific use case. 

Avatar

Level 4

@Vijayalakshmi_S- Thank you so much for your suggestion. I was trying to override getClientId() method by using sling model delegation pattern. I am getting any error with the bundle activation. Can you advise what could be the issue?

<core.wcm.components.version>2.10.0</core.wcm.components.version>

aemninja_0-1619525522687.png

---------------------

import com.adobe.cq.wcm.core.components.internal.services.pdfviewer.PdfViewerCaConfig;
import com.adobe.cq.wcm.core.components.models.PdfViewer;
import lombok.experimental.Delegate;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.caconfig.ConfigurationBuilder;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.via.ResourceSuperType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

@Model(
adaptables = {Resource.class, SlingHttpServletRequest.class},
adapters = PdfViewer.class,
resourceType = "test/components/content/pdfviewer",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)

public class CustomPdfViewer implements PdfViewer {

private static final Logger LOG = LoggerFactory.getLogger(CustomPdfViewer.class);

@Self
@Via(type = ResourceSuperType.class)
@Delegate(excludes = DelegationExclusion.class)
private PdfViewer delegate;

@Inject
private Resource resource;

private PdfViewerCaConfig caConfig;

@PostConstruct
protected void initModel() {
ConfigurationBuilder cb = (ConfigurationBuilder)this.resource.adaptTo(ConfigurationBuilder.class);
if (cb != null)
this.caConfig = (PdfViewerCaConfig)cb.as(PdfViewerCaConfig.class);
}

@Override
public String getClientId() {
LOG.info("~~~~~~~~~~~~~ CustomPdfViewer ~~~~~~~~~~~~~");
return this.caConfig.clientId();
}
private interface DelegationExclusion {
String getClientId();
}
}

 

 

 

 

Avatar

Community Advisor

Hi @aemninja,

Let me quickly reproduce this in my local and update this thread. 

Avatar

Level 4
@Vijayalakshmi_S - I am not sure if this is related to "bnd-maven-plugin". should I need to add the core components as <Embed-Dependency>?

Avatar

Community Advisor

Hi @aemninja,

Cross check the core component bundle in your instance, it should be 2.10.0 (PDF viewer component is introduced in 2.10.0. Perhaps your instance core bundle is referring to old version of core and hence PDFViewer related class is not resolvable)

You can also cross check the ui.apps package from being in Package Manager -> Expand the package -> Dependencies section should have 2.10.0

From the code base standpoint, If you are using Adobe Maven Archetype project, then below should be suffice. 

  • Updating the core components version to 2.10.0 in <properties> entry of main pom.xml file 
    • <core.wcm.components.version>2.10.0</core.wcm.components.version>
  • dependency entry for core components should have the version to be 2.10.0 in main pom.xml file
    • <dependency>
      <groupId>com.adobe.cq</groupId>
      <artifactId>core.wcm.components.core</artifactId>
      <version>2.10.0</version>
      <scope>provided</scope>
      </dependency>

 

Avatar

Level 4

@Vijayalakshmi_S- I have already tried those steps. The installed bundle (core bundle) is also 2.10.0. Also the dependency entry is also same as what you have given below. Not sure why it is still not resolvable?

 

27.04.2021 08:28:19.710 *ERROR* [qtp439185624-5343] org.apache.felix.http.jetty %bundles.pluginTitle: Cannot start (org.osgi.framework.BundleException: Unable to resolve portfolio-content-bundle [641](R 641.11): missing requirement [test-content-bundle [641](R 641.11)] osgi.wiring.package; (osgi.wiring.package=com.adobe.cq.wcm.core.components.internal.services.pdfviewer) Unresolved requirements: [[test-content-bundle [641](R 641.11)] osgi.wiring.package; (osgi.wiring.package=com.adobe.cq.wcm.core.components.internal.services.pdfviewer)])
org.osgi.framework.BundleException: Unable to resolve test-content-bundle [641](R 641.11): missing requirement [test-content-bundle [641](R 641.11)] osgi.wiring.package; (osgi.wiring.package=com.adobe.cq.wcm.core.components.internal.services.pdfviewer) Unresolved requirements: [[test-content-bundle [641](R 641.11)] osgi.wiring.package; (osgi.wiring.package=com.adobe.cq.wcm.core.components.internal.services.pdfviewer)]

Avatar

Community Advisor

@aemninja,

Got the issue. In the code snippet you have pasted, you are using "com.adobe.cq.wcm.core.components.internal.services.pdfviewer.PdfViewerCaConfig"  which is internal to Core Bundle and is not available for use by our bundle or custom project.

Only the PdfViewer Model interface (com.adobe.cq.wcm.core.components.models.PdfViewer is exposed or available for us to provide custom implementation). Remove the usage of the same(PdfViewerCaConfig) completely from your custom model and build project -> Your bundle should be active. 

 

If you are to follow CA-config approach, you can create your own config and use the same in your custom model Or if you are following OSGI approach, create your own OSGI config/Service and use the same to retrieve ClientId.

Avatar

Level 4
@Vijayalakshmi_S - Thank you so much for pointing the issue. The bundle is now active. I am going to keep the different clientIds for different production domains (two domains) as a separate OSGI config (run modes) and planning to use it in the custom model and return the respective clientId for the specific domain for my use-case. Can you please let me know if this approach is correct.

Avatar

Community Advisor

@aemninja 

You can create OSGI Factory Config (with config having properties like clientId and site specific identifier, say hostname or header value or any related from request Object) and in the custom model, you need to retrieve this factory config(all instances of factory config while referencing it) and fetch clientId based on the sitespecific identifier.

I have sample implementation for OSGI factory config in my blog. Check if you need for reference - https://myaemlearnings.blogspot.com/2020/04/osgi-factory-configuration.html

Avatar

Level 4

@Vijayalakshmi_S- Thank you for the information. I have followed he blog and created the OSGi config for my usecase and fetching the config details in custom model for the pdf viewer. For some reason, the configmap value is coming as Null, even though I have created the sling:OsgiConfig for the required runmodes for the relevant PID. Can you shed some light on this please?

 

package com.test.proj.aem.core.models;

import com.adobe.cq.wcm.core.components.models.PdfViewer;
import lombok.experimental.Delegate;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.caconfig.ConfigurationBuilder;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.Via;
import org.apache.sling.models.annotations.injectorspecific.RequestAttribute;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.apache.sling.models.annotations.via.ResourceSuperType;
import org.jsoup.helper.StringUtil;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import com.test.proj.aem.core.services.OSGIFactoryConfigPDFViewer;
import com.test.proj.aem.core.servicesconfig.OSGIFactoryConfigPDFViewerOCD;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Model(
adaptables = {Resource.class, SlingHttpServletRequest.class},
adapters = PdfViewer.class,
resourceType = "test/components/content/pdfviewer",
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)

public class CustomPdfViewer implements PdfViewer {

private static final Logger LOG = LoggerFactory.getLogger(CustomPdfViewer.class);

@Inject
private Resource resource;

@Optional
@Inject
private String resourcePath;

@Reference(target="(testName=TEST)")
private OSGIFactoryConfigPDFViewer osgiPDFViewer;

private Map<String,OSGIFactoryConfigPDFViewer> configMap;

@Self
@Via(type = ResourceSuperType.class)
@Delegate(excludes = DelegationExclusion.class)
private PdfViewer delegate;

String environmentKey;

@Reference(name = "configurationFactory", cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
protected synchronized void bindConfigurationFactory(final OSGIFactoryConfigPDFViewer config) {
if (configMap == null) {
configMap = new HashMap<>();
}
configMap.put(config.getApiEnvironmentName(), config);
}

protected synchronized void unbindConfigurationFactory(final OSGIFactoryConfigPDFViewer config) {
configMap.remove(config.getApiEnvironmentName());
}

@PostConstruct
protected void initModel() {
environmentKey = "TESTABC";
}

@Override
public String getClientId() {
try {
if(configMap.containsKey(environmentKey)) {
OSGIFactoryConfigPDFViewer configValues = configMap.get(environmentKey);
String apiId = configValues.getAPIId();
String apiTestId = configValues.getTestId();
String apiCertId = configValues.getCertId();

LOG.info("Config values ====>{} {} {}", apiID, apiTestId, apiCertId);
}
} catch (Exception e) {
LOG.error("Exception occurred in getClientId()");
}
return "262c9f22f289633c8499";
}

private interface DelegationExclusion {
String getClientId();
}
}