How to build and test AWS Lambda code with layers - java

I'm new to AWS Lambdas. Running Java 11 and using IntelliJ.
We currently have a layer which contains a lot of dependencies so our lambdas don't have to include all of them. We now need to write a new set of lambdas which will have some additional common functionality, so I want to write another set of Common code, which also depends are our existing dependency layer. Then, all our new lambdas will include the Common code, which also includes the existing layer
In my new Common code, I reference the dependency layer like this
<dependency>
<groupId>com.xxx</groupId>
<artifactId>my-layer</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
scope=provided is specified so that the layer is not included in the Common jar, but instead will be provided by AWS at runtime.
The problem is that when I write another lambda that tries to include my Common codes as a dependency, all of the dependencies in the dependency layer are not included. I just want to be able to build and test locally. Is there a way I can specify scope=provided only when building for actual deployment, but scope=compile when testing locally? Or maybe a totally different way of doing it?

You can use Maven profiles, creating something like this
<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<id>local</id>
<dependencies>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>my-layer</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>deployment</id>
<dependencies>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>my-layer</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
So you will have default profile for local development and to use the other dependency definition you call maven in that way
mvn -P deployment

Related

Maven cannot resolve package from another module dependency

I have a multi-module Maven project structure with several layers, something like this:
root-module
module-group
war-module
pom.xml
jar-module1
pom.xml
jar-module2
pom.xml
pom.xml
another-module
pom.xml
etc
pom.xml
pom.xml
module-group, another-module and etc have root-module as their parent.
So root-module/pom.xml has this:
<packaging>pom</packaging>
<modules>
<module>module-group</module>
<module>another-module</module>
<module>etc</module>
</modules>
and each of those modules has this:
<parent>
<!-- artifact coordinates etc -->
<artifactId>root-module</artifactId>
</parent>
Then, war-module, jar-module1 and jar-module2 have module-group as their parent. Thus, module-group/pom.xml also includes:
<modules>
<module>war-module</module>
<module>jar-module1</module>
<module>jar-module2</module>
</modules>
war-module has jar-module1 in its <dependecies>, and jar-module1 depends on jar-module2. War-module has <packaging>war</packaging>, jar-* modules have jar.
So dependency chain is like war-module -> jar-module1 -> jar-module2. Versions for each artifact are defined using ${revision} (I'm using Maven3).
I was trying to introduce the dependency chain from war-module in the profiles in war-module/pom.xml:
<profiles>
<!-- this profile is for building with jar-module1 (jar-module2 is resolved transitively) -->
<profile>
<id>profile1</id>
<dependencies>
<dependency>
<artifactId>jar-module1</artifactId>
</dependency>
</dependencies>
</profile>
<!-- this profile is for building without jar-module1 (straight dependency to jar-module2) -->
<profile>
<id>profile2</id>
<dependencies>
<dependency>
<artifactId>jar-module2</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
However, when I try to build my project (or just module-group or even jar-module1) the process exits with error while packaging jar-module1:
package org.example.package.from.jarmodule2 doesn't exist.
(that package has the only Java class from jar-module2 referenced in jar-module1). However, I have the target folder in my jar-module2 with correct .jar in it. IntelliJ IDEA resolves the classes correctly, only Maven cannot build it right. What might be the problem?
Also, if I introduce the dependency without using profiles, it seems to package correctly. But I need to build different configurations all the time and would really love to not have to change pom.xml every time.

How to have maven resolve a dependency of a dependency which was created by a non-default profile for some classifier?

Given a library which has different dependencies depending on a profile, say for example
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<envClassifier>cuda-10.1</envClassifier>
</properties>
<dependencies>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>10.1.0</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>cuda-10.0</id>
<properties>
<envClassifier>cuda-10.0</envClassifier>
</properties>
<dependencies>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>10.0.0</version>
</dependency>
</dependencies>
</profile>
I am creating artefacts with different classifiers, say for example
library-1.0.0-cuda-10.0
and
library-1.0.0-cuda-10.1
(here cuda-10.0 and cuda-10.1 are the classifiers for the artefact library-1.0.0).
If another project references this library, say for example as
<dependency>
<groupId>net.finmath</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<classifier>cuda-10.0</classifier>
</dependency>
then the correct artefact is pulled (here library-1.0.0-cuda-10.0.jar) but the dependency tree (via mvn dependency:tree) shows the wrong dependencies of the dependency. In this example it shows jcuda-10.1.0 and not juda-10.0.0.
This issue is due to an artefact having a single pom.xml for all classifiers (and the default profile kicks in).
Question 1: Can you have dedicated pom.xml in the repositories for different classifiers, to reflect the correct dependencies?
Apparently the issue cannot be resolved by setting a profile (-P parameter) on the outer project, because profile selectors are not passed to the poms of the dependencies. It looks as if profiles do not walk down the dependency tree.
Question 2: Is there a way to pass a profile selector to a pom of a dependency to select the right dependencies of the dependency?
I found two options to resolve the problem, but I am not very happy with them.
The first one would be to not have a default profile with a dependency in the pom of the library. In that case the user of the library (here library-1.0.0) has to specify the correct classifier and the correct downstream dependencies. This appears to be cumbersome. Also note that in this case the build of the library would fail without specification of the profile.
It is possible to use the profile to alter the name (or version) of the artefact. Since each version or artefact comes with its own pom, this allows to specify profile specific dependencies to be resolved.
However, I believe there should be a better solution, because otherwise it looks as if the specification of dependencies in profiles makes no sense for artefacts which are libraries, that is, which are themselves dependencies of another projects.
Question 3: What is the Maven way to resolve this issue?
PS: The question arose in this project: http://finmath.net/finmath-lib-cuda-extensions/
I found a lightweight solution for the problem.
You may activate a profile though a property.
Properties may not be passed from a pom to the poms of it's dependencies, but a property which is set on the command line acts on both poms.
Hence, instead of using a profile on the command line, use a property and activate the corresponding profiles in your project's pom and the library's pom.
So in the above example, the (outer) project (which references the library) has a profile
<profile>
<id>cudaversion</id>
<activation>
<property>
<name>cuda.version</name>
</property>
</activation>
<properties>
<finmath-cuda.classifier>cuda-${cuda.version}</finmath-cuda.classifier>
</properties>
</profile>
which sets the classifier of its dependency, that is this project has a dependency to library-1.0.0
<dependency>
<groupId>net.finmath</groupId>
<artifactId>library</artifactId>
<version>1.0.0</version>
<classifier>${finmath-cuda.classifier}</classifier>
</dependency>
And the pom of library-1.0.0 has a profile which is activated by the same property as in
<profile>
<id>cuda-10.0</id>
<activation>
<property>
<name>cuda.version</name>
<value>10.0</value>
</property>
</activation>
<properties>
<envClassifier>cuda-10.0</envClassifier>
</properties>
<dependencies>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>10.0.0</version>
</dependency>
</dependencies>
</profile>
The outer project is then build with mvn -Dcuda.version=10.0 to activate both profiles.

Make Eclipse default to JUnit4 rather than JUnit5 when the class only contains JUnit4 annotations

A recent upgrade of groovy which brought with it JUnit5 has resulting in Eclipse wanting to run every test under JUnit5. I can sort of work around this by going to run configurations and tell Eclipse to use JUnit4, however this gets tedious.
Is it possible to tell Eclipse to always use JUnit4 for a particular project, including new tests?
You can specify a profile and activate it in Eclipse only.
Example (assuming your problem arose by having a dependency to groovy-all):
<profiles>
<profile>
<id>eclipse-groovy-no-junit5</id>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${groovy.groupId}</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy.version}</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>${groovy.groupId}</groupId>
<artifactId>groovy-test-junit5</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
</profile>
</profiles>
Then go to
Project -> Properties -> Maven -> Active Maven Profiles
and specify the profile name eclipse-groovy-no-junit5.
Remark: groovy.groupId is set to org.codehaus.groovy (it's a variable, because it will be replaced by org.apache.groovy in 4.x) and groovy.version is set to 3.0.8.
If you want to be a bit more verbose, you can add...
<activation>
<activeByDefault>false</activeByDefault>
</activation>
...but it's the default anyway.

Need Multiple versions for same dependency for Maven

I know its a repetitive question on Site , but I didn't find solution to my problem.
I have project specific dependency with multiple versions and I want all of them :
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>431</version>
</dependency>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>441</version>
</dependency>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>451</version>
</dependency>
PS : Doing migration from ANT to MAVEN. Thus ANT can support multiple versions for the same jar in lib folder.(textile-client-431.jar,textile-client-441.jar,textile-client-451.jar) But when migrating to MAVEN, it takes only the latest version(textile-client-451.jar). Is there any way to include all versions.
As far as I know, Maven does not allow that. Maven will only resolve one dependency and will avoid the other ones.
I do not test it, but I remember to read about two possibilities:
First, you can specify different profiles, and in each profile you can specify a dependency with a version. Something like this:
<profiles>
<profile>
<id>431</id>
<activation>
...
</activation>
<dependencies>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>431</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>431</id>
<activation>
...
</activation>
<dependencies>
<dependency>
<groupId>com.abc.textile</groupId>
<artifactId>textile-client</artifactId>
<version>431</version>
</dependency>
</dependencies>
</profile>
<profiles>
Second, I read something some time ago about OSGI, maybe it could help you to take a look. http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html

Add dependency according to the given condition in Maven

Is there a way I can set up dependancies according to a given condition when I buid the maven project.
mvn package someCondition
So if I say mvn install A it should add one dependancy and if a say mvn install B it should add another type of dependancy.
Please help. Thank You
P.S. Is there a way I can do this by creating multiple profiles?
Using profile is the most straight-forward way.
in brief, consider having something like this:
<project>
...
<profiles>
<profile>
<id>profile-a</id>
<dependencies>
<dependency>
// dependency 1
</dependency>
</dependencies>
</profile>
<profile>
<id>profile-b</id>
<dependencies>
<dependency>
// dependency 2
</dependency>
</dependencies>
</profile>
<profiles>
</project>
Then you can simply do mvn install -P profile-a which will do what you ask for.

Categories