In Maven, including dependency via <dependency> OR importing the package inside <Import-Package>. Which one of the two should be used? - maven

In my project core pom.xml, there is Import-Package javax.inject;version=0.0.0 and also following maven dependency. I am not clear why both are being used? I mean, if we are already including the dependency via below-mentioned method, then why do we need to use the same inside Import-Package?
<configuration>
<instructions>
<Import-Package>
javax.inject;version=0.0.0,
org.xbc.web.core.service;version=0.0.0,
*
</Import-Package>
<Sling-Model-Packages>
org.xbc.core
</Sling-Model-Packages>
</instructions>
</configuration>
Above mentioned packages are duplicated in below dependencies
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.xbc.web</groupId>
<artifactId>fullton-project.core</artifactId>
<scope>provided</scope>
</dependency>
The same scenario is happening in my project. My project A is dependent on project B, there also I have noticed that package path has been added in Import-Package and dependency has been added for project B in core/pom.xml of Project A. why both? Somebody, please clarify this.

Related

Not able to connect Google Cloud Datastore with AEM 6.5 : Bundle has resolved dependencies

I have a requirement to connect google cloud datastore from AEM. I have added the dependencies in main pom and core pom.
MAIN POM
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>16.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>de here
Core POM
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-datastore</artifactId>
</dependency>
When I deploy my bundle is in insatlled state and has the following errors
com.google.auth -- Cannot be resolved
com.google.auth.oauth2 -- Cannot be resolved
com.google.cloud -- Cannot be resolved
com.google.cloud.datastore -- Cannot be resolved
try adding those libs to the embed-dependencies in the POM. Also check that your libs are inside the .jar file generated.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<!-- <Embed-Dependency> artifactId1, artifactId2;inline=true </Embed-Dependency> -->
<Export-Package>we.retail.core.model*</Export-Package>
<Private-Package>we.retail.core*</Private-Package>
<Sling-Model-Packages>
we.retail.core.model
</Sling-Model-Packages>
</instructions>
</configuration>
</plugin>
In the embed you can try something like: google-cloud-datastore
Also take care with the import type that you're using.
Link to Maven
Hope you can find the answer
If you do not need those, exclude them from the <Import-Packages>:
<Import-Package>
!com.google.auth.*,
*
</Import-Package>

Using a 3rd party dependency within a Maven OSGi bundle

After feeling like I had a grasp on how OSGi is utilized, I tried to go about adding a 3rd party dependency, specifically log4j2, to my application that is utilizing apache felix and bundling with the maven-bundle-plugin. Unfortunately, it seems as if I am stuck in dependency hell.
I have tried using numerous maven-bundle tactics like Import-Package, Embed-Dependency, wrapImportPackage, Embed-Transitive, and setting specific version numbers just to name a few. Below is what my pom looks like for this plugin:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ParentId</artifactId>
<groupId>ParentGroupId</groupId>
<version>x.x.x</version>
</parent>
<groupId>ParentGroupId.ParentId</groupId>
<artifactId>thisModule</artifactId>
<packaging>bundle</packaging>
<name>thisModule</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>AM</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Bundle-Activator>moduleActivator</Bundle-Activator>
<Embed-Dependency>
AM,
gson,
log4j-api,
log4j-core
</Embed-Dependency>
</instructions>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
The most progress I feel like I have had is with the above pom, where I am embedding the log4j api and core directly into the bundle, but it seems as if OSGi is incapable of downloading and bundling the compile dependencies that the log4j api and core are dependent on. It successfully builds using maven but then when I deploy the EAR and JAR I get this error at runtime (when the plugin is trying to boot up):
Caused By: org.osgi.framework.BundleException: Unresolved constraint in bundle thisModule [2]: Unable to resolve 2.0: missing requirement [2.0] package; (package=com.conversantmedia.util.concurrent)
error that will name a specific dependency that log4j needs. What I DON'T want to do is include every single dependency and their mother inside the Embed-Dependency tag.
What am I doing wrong here?
Also note: Due to constraints, my only option here is to use apache felix and OSGi.
Below are other examples of modifications I made to the above POM and their resulting outputs:
Removing both log4j-api and log4j-core from Embed-Dependency and adding in a <wrapImportPackage>;</wrapImportPackage> tag. Doing so resulted in this output, which is extremely common and happens whenever I try to import:
Caused By: org.osgi.framework.BundleException: Unresolved constraint in bundle thisModule [2]: Unable to resolve 2.0: missing requirement [2.0] package; (&(package=org.apache.logging.log4j)(version>=2.12.0)(!(version>=3.0.0)))
Adding * to Embed-Dependency as well as adding <Embed-Transitive>true</Embed-Transitive>:
Caused By: org.osgi.framework.BundleException: Unresolved constraint in bundle thisModule [2]: Unable to resolve 2.0: missing requirement [2.0] package; (package=android.dalvik)
Embedding a logging libary is a bad idea. After all you want to configure the logging in a central place which is very hard when each bundle embeds a logging framework.
In most cases the safe bet is to simple keep the maven-bundle-plugin config empty and let it do its thing.
I personally always use slf4j for logging in OSGi. You simply depend on the slf4j-api. The maven-bundle-plugin creates the import package statements automatically.
Then at runtime you simply deploy a logging framework that supports the logging api you want.
For apache karaf this is already the case by default. If you use bndtools or your own application assembly based on plain felix then check out my osgi best practices example.
It shows how to use slf4j-api in your own bundles and also how to configure the log system in karaf and bndtools based applications.

Transitive Dependency: Using Elasticsearch Rest High Client problem in AEM

I am trying to use Java High Level Rest Client in Adobe Experience Manager to finish project of comparison between Lucene, Solr and Elasticsearch search engines.
I am having some problems with elasticsearh implementation.
Here is the code:
Dependency in the parent pom.xml (the same is defined in core pom.xml)
<!-- Elasticseach dependencies -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.0</version>
</dependency>
The only line of code that I am using that is from dependencies above
try (RestHighLevelClient client = new
RestHighLevelClient(RestClient.builder(new HttpHost(server, port,
protocol),
new HttpHost(server, secondPort, protocol)));)
{
}
catch (ElasticsearchException e)
{
LOG.error("Exception: " + e);
}
protocol = "http", server = "localhost", port = 9200, secondPort =
9201
Error
Dependencies from IntelliJ
I know that there is usually problem with dependencies versions, but all are 7.4.0 in this case. Also elasticsearch 7.4.0v is running locally on 3 nodes.
This project is done on We.Retail project so it is easy to replicate. Also all the code with this error is available here:
https://github.com/tadijam64/search-engines-comparison-on-we-retail/tree/elasticsearch-integration
AEM 6.4v.
Any info or idea is appreciated.
UPDATE
I tried with adding the following to embed these dependencies externally since they are not OSGi dependencies:
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Embed-Dependency>org.apache.servicemix.bundles.solr-solrj, log4j, noggit, zookeeper,
elasticsearch-rest-high-level-client
</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Export-Package>we.retail.core.model*</Export-Package>
<Import-Package>
*;resolution:=optional
</Import-Package>
<Private-Package>we.retail.core*</Private-Package>
<Sling-Model-Packages>
we.retail.core.model
</Sling-Model-Packages>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
The error remains. I also tried adding it to the "export-package", but nothing helps.
And by Elasticsearch documentation, all I need to use Elasticsearch is
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.0</version>
</dependency>
but then NoClassDefFoundErrors occurs. It seems like a problem with transitive dependencies maybe. Not sure, but any idea is appreciated.
Some other suggestions can be found here: https://forums.adobe.com/thread/2653586
I have also tried adding it's transitive dependencies like org.elasticsearch and org.elasticsearch.client, but it does not work. The same error, just other class.
AEM version 6.4, Java version: jdk1.8.0_191.jdk
So my guess was right, transitive dependencies were not included altho <Embed-Transitive>true</Embed-Transitive> exists.
The following is necessary when running elasticsearch as a search engine on AEM the problem:
I have added all transitive dependencies in pom.xml (versions are defined in parent/pom.xml):
<!-- Elasticsearch -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-x-content</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>rank-eval-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>lang-mustache-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
</dependency>
It is important to add all third-party dependencies as <Embed-Dependency> inside maven-bundle-plugin like this:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Embed-Dependency>org.apache.servicemix.bundles.solr-solrj, noggit,
elasticsearch-rest-high-level-client,
elasticsearch,
elasticsearch-rest-client,
elasticsearch-x-content,
elasticsearch-core,
rank-eval-client,
lang-mustache-client,
httpasyncclient;
</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Export-Package>we.retail.core.model*</Export-Package>
<Import-Package>
*;resolution:=optional
</Import-Package>
<Private-Package>
we.retail.core*
</Private-Package>
<Sling-Model-Packages>
we.retail.core.model
</Sling-Model-Packages>
<_fixupmessages>"Classes found in the wrong directory";is:=warning</_fixupmessages>
</instructions>
</configuration>
</plugin>
Important to notice:
All third-party dependencies (the ones outside of OSGi) must be included in the "Embed-Dependency"
"Embed-Transitive" must be set to true to include transitive dependencies
"Import-Package" must include "*;resolution:=optional" to exclude all dependencies that could not be resolved so that the program can run
normally
For some reason, there was an error in compile time when "elasticsearch" dependency was added which is not important for this
task, so I've decided to ignore it this way:
<_fixupmessages>"Classes found in the wrong directory";is:=warning</_fixupmessages>
Though challenging, I finally resolved it. There are many similar or the same problems on Google, so I hope this will help someone. Thanks to everyone that tried to help.

Using mvn aem-project-archetype in AEM 6.2 does not resolve the core bundle - javax.inject cannot be resolved

I'm trying to build a new project using mvn aem-project-archetype (https://github.com/Adobe-Marketing-Cloud/aem-project-archetype) and on deploy the core bundle shows status as "Installed" but cannot be Active showing the error
javax.inject, version=[0.0,1) -- Cannot be resolved
I tried to add the dependencies as suggested here (https://github.com/Adobe-Marketing-Cloud/aem-project-archetype/issues/59)
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
and also tried all solutions as listed here (http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manager.topic.html/forum__fikl-ive_just_updatedfro.html) but they did not resolve.
Appreciate any help here.
Add Import-Package tag for "javax.inject" with version "0.0.0,*" under "org.apache.felix" plugin tag like below:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<!-- <Embed-Dependency>
artifactId1,artifactId2;inline=true
</Embed-Dependency> -->
<!-- Import any version of javax.inject, to allow running on multiple versions of AEM -->
<Import-Package>javax.inject;version=0.0.0,*</Import-Package>
<Sling-Model-Packages>com.xyz.sample_test_impl.core</Sling-Model-Packages>
</instructions>
</configuration>
</plugin>
After some research here's some solutions for the above:
Comment "#Inject" in HelloWorldModel.java . This may not be ideal, but if you are not planning on using Sling Models, then this will work.
#Model(adaptables=Resource.class)
public class HelloWorldModel {
//#Inject
private SlingSettingsService settings;
//#Inject #Named("sling:resourceType") #Default(values="No resourceType")
protected String resourceType;
Use ACS's Lazybones AEM Template instead of Archetype 10 if you will be using AEM 6.1 or higher. This is the recommended template to use with AEM whihc is more sophisticated and up-to-date.
Try to sync your dependencies list with the following official sample project. In fact, it helped for me just after adding
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
to general pom.xml and
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
to its child ../core/pom.xml

How to exclude a dependency for a specific scope only?

I have two dependencies in my pom called A and B. Both A and B have a transitive dependency on an artifact C (cassandra-all). A and B use difference versions of C. Dependency A is the artifact astyanax.
I want to keep the Version of C that comes with B. I accomplished by adding an exclusion in A (Astyanax) for C.
Unfortunately, I want the scope of B to be 'test'. This means that with the exclusion in A, C will not be included outside of the test scope.
How can I resolve this? Can an exclusion be for a specific scope only? Alternatively, can I specify which version to use for a transitive dependency?
Example:
Here is what my pom looks like:
Artifact A (astyanax) with exclusion of dependency on Artifact C (called cassandra-all)
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax</artifactId>
<version>1.0.4</version>
<exclusions>
<exclusion>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit</artifactId>
<version>1.1.1.1</version>
<scope>test</scope>
</dependency>
So concretely: how can I include cassandra-all when I run code outside of the test scope and still keep the scope of cassandraunit test only?
I apologize if my question wasn't as clear as it could have been. The way I resolved this wasn't hard at all:
I added a separate dependency for C in my pom
I kept the exclusion of C in A
Concretely here, I just added:
<dependency>
<groupId>org.apache.cassandra</groupId>
<artifactId>cassandra-all</artifactId>
<version>1.1.5</version>
</dependency>
and also the following dependency that was missing at runtime otherwise.
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
I am not sure I understood everything, but, in any case, you should be able to achieve this with profiles.
In your pom, create a profile A in which you add your dependency A with exclusion of B and a profile B in which you'll have a dependency with exclusion of A.
On runtime, depending on which of the profile you have selected you'll include one or the other.
HIH
So concretely: how can I include cassandra-all when I run code outside of the test scope and still keep the scope of cassandraunit test only?
Use Maven POM to configure surefire-maven-plugin and change your classpath.
If what you want is only that the cassandra-all dependency be removed from the classpath while running your tests, then the following POM snippet would make the tricky:
<build>
<!-- ... -->
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<classpathDependencyExcludes>
<classpathDependencyExcludes>
org.apache.cassandra:cassandra-all
</classpathDependencyExcludes>
</classpathDependencyExcludes>
</configuration>
</plugin>
</plugins>
</build>

Resources