Expand my Community achievements bar.

How to use third party api in AEM

Avatar

Level 3

Hi everyone,

 

I'm new to aem and is still learning based on the training project adobe provided.

I try to create a new servlet so i can upload file to AWS s3 bucket, but it returns build error and i don't know how to solve it so really prefer some help.

 

build error message:

zonghuiliu_0-1666259654098.png

zonghuiliu_1-1666259658760.png

 

Here is what i added into the pom file.

pom.xml

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-osgi</artifactId>
    <version>1.12.322</version>
</dependency>
 
core/pom.xml
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-osgi</artifactId>
</dependency>
 
I also download the newest aws-java-sdk-osgi jar file and installed it through web console.But the status is installed and when i try to start the bundle it returns the error below.
zonghuiliu_2-1666259977345.png

 

error log:

[FelixLogListener]
LogService.org.apache.felix.http.jetty Bundles: Cannot start (org.apache.felix.log.LogException: org.osgi.framework.BundleException: Unable to resolve com.amazonaws.aws-java-sdk-osgi [586](R 586.0): missing requirement [com.amazonaws.aws-java-sdk-osgi [586](R 586.0)] osgi.wiring.package; (&(osgi.wiring.package=com.fasterxml.jackson.dataformat.cbor)(version>=2.12.0)(!(version>=3.0.0))) Unresolved requirements: [[com.amazonaws.aws-java-sdk-osgi [586](R 586.0)] osgi.wiring.package; (&(osgi.wiring.package=com.fasterxml.jackson.dataformat.cbor)(version>=2.12.0)(!(version>=3.0.0)))])
org.apache.felix.log.LogException: org.osgi.framework.BundleException: Unable to resolve com.amazonaws.aws-java-sdk-osgi [586](R 586.0): missing requirement [com.amazonaws.aws-java-sdk-osgi [586](R 586.0)] osgi.wiring.package; (&(osgi.wiring.package=com.fasterxml.jackson.dataformat.cbor)(version>=2.12.0)(!(version>=3.0.0))) Unresolved requirements: [[com.amazonaws.aws-java-sdk-osgi [586](R 586.0)] osgi.wiring.package; (&(osgi.wiring.package=com.fasterxml.jackson.dataformat.cbor)(version>=2.12.0)(!(version>=3.0.0)))]

8 Replies

Avatar

Level 4

Hi @zonghuiliu ,

 

This is caused if the package imported is not exported by any bundle. The Import-Package declarations must be satisfied by the Export-package declaration of other included bundles in the Maven project.

 

To solve this add the package in the Export tag 

If your archetype is using maven-bundle-plugin then use the below in your pom.xml 

 

<Export-Package>

com.amazonaws.aws-java-sdk-osgi.*

</Export-Package>

 

If your archetype is using bnd-maven-plugin then use the below in your pom.xml

 

Export-Package: com.amazonaws.aws-java-sdk-osgi.*

 

 

Reference:

https://myaemlearnings.blogspot.com/2021/08/embedding-third-party-dependencyosgi.html

 

 

Avatar

Level 3

Thank you for your reply.

 

I'm using bnd-maven-plugin but i still have no idea where to add the export package.

Below is how i made the change.

I'm sorry for this newbie question but could you please tell me the right place to add the export package description.

 

pom.xml

<!-- BND Maven Plugin -->
                       
        <plugin>
                             
          <groupId>biz.aQute.bnd</groupId>                  
          <artifactId>bnd-maven-plugin</artifactId>                  
          <version>${bnd.version}</version>              
          <executions>                    
            <execution>                      
              <id>bnd-process</id>                  
              <goals>                        
                <goal>bnd-process</goal>                    
              </goals>                    
              <configuration>                          
                <bnd>
                  <![CDATA[
Bundle-Category: ${componentGroupName}
Export-Package: com.amazonaws.aws-java-sdk-osgi.*

# export all versioned packages except for conditional ones (https://github.com/bndtools/bnd/issues/3721#issuecomment-579026778)
-exportcontents: ${removeall;${packages;VERSIONED};${packages;CONDITIONAL}}

-noextraheaders: true
-snapshot: SNAPSHOT

Bundle-DocURL:
-plugin org.apache.sling.caconfig.bndplugin.ConfigurationClassScannerPlugin
-plugin org.apache.sling.bnd.models.ModelsScannerPlugin
                                ]]>
                </bnd>
                                           
              </configuration>
                                     
            </execution>
                               
          </executions>
                             
          <dependencies>
                                   
            <dependency>
                                         
              <groupId>org.apache.sling</groupId>
                                         
              <artifactId>org.apache.sling.caconfig.bnd-plugin</artifactId>
                                         
              <version>1.0.2</version>
                                     
            </dependency>
                                   
            <dependency>
                                         
              <groupId>org.apache.sling</groupId>
                                         
              <artifactId>org.apache.sling.bnd.models</artifactId>
                                         
              <version>1.0.0</version>
                                     
            </dependency>
                                   
            <dependency>
                                         
              <groupId>org.apache.sling</groupId>
                                         
              <artifactId>scriptingbundle-maven-plugin</artifactId>
                                         
              <version>0.5.0</version>
                                     
            </dependency>
                               
          </dependencies>
                         
        </plugin>
 
core/pom.xml
 
<plugin>
                <groupId>biz.aQute.bnd</groupId>
                <artifactId>bnd-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>bnd-process</id>
                        <goals>
                            <goal>bnd-process</goal>
                        </goals>
                        <configuration>
                            <bnd><![CDATA[
Import-Package: javax.annotation;version=0.0.0,*
Export-Package: com.amazonaws.aws-java-sdk-osgi.*
                                ]]></bnd>
                                <instructions>
                    </instructions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Avatar

Level 3

Sorry for the late reply.

 

I've made the change to core/pom.xml and still got the same error.

I've read this tutorial Embed Third party dependency using bnd-maven-plugin (myaemlearnings.blogspot.com) but cannot find any description about export package.

 

Do i have to add the aws-java-sdk-osgi jar file into the project folder and where should i put it?Or is there anything i missed to do.

 

Thank you  for your help in advance.

 

Avatar

Level 3

Sorry for interupting you again.

 

After several changes finally the build successed.

What i've done is i deleted the in-active aws-java-sdk-osgi jar file and add the description below into the core/pom.xml file.

-conditionalpackage: com.amazonaws.aws-java-sdk-osgi.*
-includeresource: @aws-java-sdk-osgi-1.12.322.jar!/
 
Now the project is in active state but when i made the request to send the file it shows 404 error and i don't know how i can fix it.Could you help me with that?
 
Project state:
zonghuiliu_0-1666602480525.png

 

My servlet file:

package com.adobe.training.core.servlets;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.day.cq.dam.api.Asset;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.Servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_PATHS;

@Component(
  service = { Servlet.class },
  property = {
    SLING_SERVLET_PATHS + "=/bin/upload"
  }
)

public class S3FileUploaderServlet extends SlingSafeMethodsServlet {

    // Serial version UID
    private static final long serialVersionUID = 1L;
    private static final Logger LOGGER = LoggerFactory.getLogger(S3FileUploaderServlet.class);

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

        try {
            String filePath = request.getParameter("filePath");
            LOGGER.info("File path: {}", filePath);

            Resource resource = request.getResourceResolver().getResource(filePath);
            Asset asset = Objects.requireNonNull(resource).adaptTo(Asset.class);

            InputStream inputStream = Objects.requireNonNull(asset).getOriginal().getStream();
            String assetName = asset.getName();

            Regions clientRegion = Regions.AP_NORTHEAST_1;
            LOGGER.info("AWS Region: {}", clientRegion.getName());

            String S3_ACCESS_KEY = "xx";

            String S3_SECRET_KEY = "xx";

            String S3_BUCKET_NAME = "xx";

            AWSCredentials awsCredentials = new BasicAWSCredentials(S3_ACCESS_KEY, S3_SECRET_KEY);

            AmazonS3 s3Client = AmazonS3ClientBuilder
                    .standard()
                    .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                    .withRegion(clientRegion)
                    .build();

            File file = File.createTempFile("temp", null);

            try (FileOutputStream outputStream = new FileOutputStream(file)) {

                int read;
                byte[] bytes = new byte[1024];

                while ((read = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }

                PutObjectRequest putObjectRequest = new PutObjectRequest(S3_BUCKET_NAME, "test", file);
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.addUserMetadata("title", assetName);
                putObjectRequest.setMetadata(objectMetadata);
                s3Client.putObject(putObjectRequest);

                response.getWriter().println("File uploaded!!");
            }
        } catch (IOException e) {
            LOGGER.error("Exception occurred: {}", e.getMessage());
        }
    }
}
 
error message:

Resource at '/bin/upload' not found: No resource found

Cannot serve request to /bin/upload in BundledScriptServlet (/libs/sling/servlet/errorhandler/404.jsp)

Request Progress:

      0 TIMER_START{Request Processing}
      1 COMMENT timer_end format is {<elapsed microseconds>,<timer name>} <optional message>
      6 LOG Method=GET, PathInfo=null
      6 TIMER_START{handleSecurity}
   1481 TIMER_END{1472,handleSecurity} authenticator org.apache.sling.auth.core.impl.SlingAuthenticator@7000bacf returns true
   1867 TIMER_START{ResourceResolution}
   2192 TIMER_END{324,ResourceResolution} URI=/bin/upload resolves to Resource=NonExistingResource, path=/bin/upload
   2201 LOG Resource Path Info: SlingRequestPathInfo: path='/bin/upload', selectorString='null', extension='null', suffix='null'
   2201 TIMER_START{ServletResolution}
   2205 TIMER_START{resolveServlet(/bin/upload)}
   3278 LOG {0}: no servlet found
   3348 TIMER_END{1140,resolveServlet(/bin/upload)} Using servlet org.apache.sling.servlets.get.DefaultGetServlet
   3353 TIMER_END{1151,ServletResolution} URI=/bin/upload handled by Servlet=org.apache.sling.servlets.get.DefaultGetServlet
   3357 LOG Applying Requestfilters
   3363 LOG Calling filter: com.adobe.granite.resourceresolverhelper.impl.ResourceResolverHelperImpl
   3370 LOG Calling filter: org.apache.sling.security.impl.ContentDispositionFilter
   3374 LOG Calling filter: com.adobe.granite.csrf.impl.CSRFFilter
   3384 LOG Calling filter: org.apache.sling.i18n.impl.I18NFilter
   3388 LOG Calling filter: com.adobe.granite.httpcache.impl.InnerCacheFilter
   3398 LOG Calling filter: org.apache.sling.rewriter.impl.RewriterFilter
   3401 LOG Calling filter: com.adobe.cq.history.impl.HistoryRequestFilter
   3693 LOG Calling filter: com.day.cq.wcm.core.impl.WCMRequestFilter
   3709 LOG Calling filter: com.adobe.cq.wcm.core.components.internal.servlets.CoreFormHandlingServlet
   3713 LOG Calling filter: com.adobe.granite.optout.impl.OptOutFilter
   3722 LOG Calling filter: com.day.cq.wcm.foundation.forms.impl.FormsHandlingServlet
   3731 LOG Calling filter: com.day.cq.dam.core.impl.servlet.DisableLegacyServletFilter
   3739 LOG Calling filter: org.apache.sling.engine.impl.debug.RequestProgressTrackerLogFilter
   3744 LOG Calling filter: com.day.cq.wcm.mobile.core.impl.redirect.RedirectFilter
   3747 LOG Calling filter: com.day.cq.wcm.core.impl.AuthoringUIModeServiceImpl
   3949 LOG Calling filter: com.adobe.granite.rest.assets.impl.AssetContentDispositionFilter
   3961 LOG Calling filter: com.adobe.granite.requests.logging.impl.RequestLoggerImpl
   3967 LOG Calling filter: com.adobe.granite.rest.impl.servlet.ApiResourceFilter
   3971 LOG Calling filter: com.day.cq.dam.core.impl.servlet.ActivityRecordHandler
   3984 LOG Calling filter: com.day.cq.wcm.core.impl.warp.TimeWarpFilter
   3993 LOG Calling filter: com.day.cq.dam.core.impl.assetlinkshare.AdhocAssetShareAuthHandler
   4001 LOG Applying Componentfilters
   4003 LOG Calling filter: com.day.cq.personalization.impl.TargetComponentFilter
   4006 LOG Calling filter: com.day.cq.wcm.core.impl.page.PageLockFilter
   4010 LOG Calling filter: com.day.cq.wcm.core.impl.WCMComponentFilter
   4036 LOG Calling filter: com.adobe.granite.metrics.knownerrors.impl.ErrorLoggingComponentFilter
   4040 LOG Calling filter: com.day.cq.wcm.core.impl.WCMDebugFilter
   4051 TIMER_START{org.apache.sling.servlets.get.DefaultGetServlet#0}
   4244 TIMER_END{186,org.apache.sling.servlets.get.DefaultGetServlet#0}
   4443 LOG Filter timing: filter=com.day.cq.wcm.core.impl.WCMDebugFilter, inner=207, total=212, outer=5
   4451 LOG Filter timing: filter=com.adobe.granite.metrics.knownerrors.impl.ErrorLoggingComponentFilter, inner=212, total=368, outer=156
   4461 LOG Filter timing: filter=com.day.cq.wcm.core.impl.monitoring.PageComponentRequestFilter, inner=368, total=370, outer=2
   4470 LOG Filter timing: filter=com.day.cq.wcm.core.impl.WCMComponentFilter, inner=370, total=401, outer=31
   4478 LOG Filter timing: filter=com.day.cq.wcm.core.impl.page.PageLockFilter, inner=401, total=405, outer=4
   4529 LOG Filter timing: filter=com.day.cq.dam.core.impl.assetlinkshare.AdhocAssetShareAuthHandler, inner=485, total=491, outer=6
   4539 LOG Filter timing: filter=com.adobe.cq.dtm.reactor.impl.servlets.ClientLibraryFilter, inner=491, total=493, outer=2
   4549 LOG Filter timing: filter=com.adobe.cq.dam.webdav.impl.io.DamWebdavRequestFilter, inner=493, total=494, outer=1
   4559 LOG Filter timing: filter=com.day.cq.wcm.core.impl.warp.TimeWarpFilter, inner=494, total=502, outer=8
   4569 LOG Filter timing: filter=com.day.cq.dam.core.impl.servlet.DamContentDispositionFilter, inner=502, total=503, outer=1
   4579 LOG Filter timing: filter=com.day.cq.dam.core.impl.servlet.ActivityRecordHandler, inner=503, total=516, outer=13
   4589 LOG Filter timing: filter=com.adobe.granite.rest.impl.servlet.ApiResourceFilter, inner=516, total=522, outer=6
   4600 LOG Filter timing: filter=com.adobe.granite.requests.logging.impl.RequestLoggerImpl, inner=522, total=530, outer=8
   4627 LOG Filter timing: filter=com.adobe.cq.projects.impl.servlet.ProjectContentDispositionFilter, inner=530, total=531, outer=1
   4646 LOG Filter timing: filter=com.adobe.granite.rest.assets.impl.AssetContentDispositionFilter, inner=531, total=545, outer=14
   4654 LOG Filter timing: filter=com.day.cq.wcm.core.impl.AuthoringUIModeServiceImpl, inner=545, total=746, outer=201
   4663 LOG Filter timing: filter=com.day.cq.wcm.mobile.core.impl.redirect.RedirectFilter, inner=746, total=752, outer=6
   4670 LOG Filter timing: filter=org.apache.sling.engine.impl.debug.RequestProgressTrackerLogFilter, inner=752, total=757, outer=5
   4679 LOG Filter timing: filter=org.apache.sling.distribution.servlet.DistributionAgentCreationFilter, inner=757, total=760, outer=3
   4687 LOG Filter timing: filter=com.day.cq.dam.core.impl.servlet.DisableLegacyServletFilter, inner=760, total=770, outer=10
   4696 LOG Filter timing: filter=com.adobe.cq.wcm.core.extensions.amp.internal.AmpModeForwardFilter, inner=770, total=772, outer=2
   4705 LOG Filter timing: filter=com.day.cq.wcm.foundation.forms.impl.FormsHandlingServlet, inner=772, total=780, outer=8
   4713 LOG Filter timing: filter=com.adobe.granite.optout.impl.OptOutFilter, inner=780, total=789, outer=9
   4735 LOG Filter timing: filter=com.adobe.cq.wcm.core.components.internal.servlets.CoreFormHandlingServlet, inner=789, total=800, outer=11
   4746 LOG Filter timing: filter=com.day.cq.wcm.core.impl.WCMRequestFilter, inner=800, total=815, outer=15
   4755 LOG Filter timing: filter=com.adobe.cq.history.impl.HistoryRequestFilter, inner=815, total=1104, outer=289
   4765 LOG Filter timing: filter=org.apache.sling.rewriter.impl.RewriterFilter, inner=1104, total=1110, outer=6
   4776 LOG Filter timing: filter=com.adobe.granite.httpcache.impl.InnerCacheFilter, inner=1110, total=1122, outer=12
   4786 LOG Filter timing: filter=org.apache.sling.i18n.impl.I18NFilter, inner=1122, total=1127, outer=5
   4818 LOG Filter timing: filter=com.adobe.granite.csrf.impl.CSRFFilter, inner=1127, total=1138, outer=11
   4832 LOG Filter timing: filter=org.apache.sling.security.impl.ContentDispositionFilter, inner=1138, total=1143, outer=5
   5023 LOG Applying Error filters
   5031 LOG Calling filter: org.apache.sling.i18n.impl.I18NFilter
   5037 LOG Calling filter: org.apache.sling.rewriter.impl.RewriterFilter
   5100 TIMER_START{handleError:status=404}
   5653 TIMER_END{551,handleError:status=404} Using handler BundledScriptServlet (/libs/sling/servlet/errorhandler/404.jsp)
   5895 LOG Adding bindings took 53 microseconds
   7394 LOG Found processor for post processing ProcessorConfiguration: {contentTypes=[text/html], order=-1, active=true, valid=true, processErrorResponse=true, pipeline=(generator=Config(type=htmlparser, config={}), transformers=(Config(type=linkchecker, config={}), Config(type=mobile, config=JcrPropertyMap [node=Node[NodeDelegate{tree=/libs/cq/config/rewriter/default/transformer-mobile: { jcr:primaryType = nt:unstructured, component-optional = true}}], values={jcr:primaryType=nt:unstructured, component-optional=true}]), Config(type=mobiledebug, config=JcrPropertyMap [node=Node[NodeDelegate{tree=/libs/cq/config/rewriter/default/transformer-mobiledebug: { jcr:primaryType = nt:unstructured, component-optional = true}}], values={jcr:primaryType=nt:unstructured, component-optional=true}]), Config(type=contentsync, config=JcrPropertyMap [node=Node[NodeDelegate{tree=/libs/cq/config/rewriter/default/transformer-contentsync: { jcr:primaryType = nt:unstructured, component-optional = true}}], values={jcr:primaryType=nt:unstructured, component-optional=true}]), serializer=Config(type=htmlwriter, config={}))}
   7947 TIMER_END{7945,Request Processing} Dumping SlingRequestProgressTracker Entries

Avatar

Level 4

@zonghuiliu ,

 

From the image the servlet shows its satisfied but it should be in active state. Check the below sample servlet 

 

 

import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_METHODS;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_PATHS;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletException;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.service.component.annotations.Component;

/**
* Servlet that writes some sample content into the response. 
*/

@Component(service = { Servlet.class }, property = { SLING_SERVLET_PATHS + "=/bin/upload",
SLING_SERVLET_METHODS + "= GET" })

public class SimpleServlet extends SlingSafeMethodsServlet {

private static final long serialVersionUID = 1L;

@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp)
throws ServletException, IOException {
final String resource = req.getParameter("path");
resp.setContentType("text/plain");
resp.getWriter().write("File path = " + resource);

}
}

 

 

 

SwetaB_0-1666852375325.png

 

Avatar

Level 3

Thank you for your reply!

 

I've tried your code but it returns the same error. Also all my servlets are in satisfied state and i have no idea how to turn them into active state.

 

Why does my new AEM servlet stay in satisfied stat... - Adobe Experience League Community - 453517

I've seen this post but I'am not using service in the servlet,also no unresolved dependency.

 

I'm wondering maybe something wrong with my pom file,so can you share your pom file,thank you in advance!

Avatar

Level 5

Hi @zonghuiliu 

Please have a look on the similar community discussion for further information on external dependency resolution (import, export package). Hope this helps for better understanding.

 

Solved: AEM Import and Export Bundle - Adobe Experience League Community - 364872