I am attempting to create an AWS Lambda function via the serverless framework and using Java8 runtime. Every time I try to invoke the only lambda function locally with serverless invoke local --function flyway
, I keep getting the following error:
Serverless: In order to get human-readable output, please implement "toString()" method of your "ApiGatewayResponse" object.
org.flywaydb.core.api.FlywayException: Unable to instantiate JDBC driver: org.postgresql.Driver => Check whether the jar file is present
at org.flywaydb.core.internal.jdbc.DriverDataSource.<init>(DriverDataSource.java:180)
at org.flywaydb.core.internal.jdbc.DriverDataSource.<init>(DriverDataSource.java:144)
at org.flywaydb.core.api.configuration.ClassicConfiguration.setDataSource(ClassicConfiguration.java:1341)
at org.flywaydb.core.api.configuration.FluentConfiguration.dataSource(FluentConfiguration.java:803)
at com.serverless.FlywayMigrations.<init>(FlywayMigrations.java:12)
at com.serverless.Handler.<init>(Handler.java:16)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.lang.Class.newInstance(Class.java:584)
at com.serverless.InvokeBridge.getInstance(InvokeBridge.java:71)
at com.serverless.InvokeBridge.<init>(InvokeBridge.java:37)
at com.serverless.InvokeBridge.main(InvokeBridge.java:150)
Caused by: org.flywaydb.core.api.FlywayException: Unable to instantiate class org.postgresql.Driver : org.postgresql.Driver
at org.flywaydb.core.internal.util.ClassUtils.instantiate(ClassUtils.java:59)
at org.flywaydb.core.internal.jdbc.DriverDataSource.<init>(DriverDataSource.java:176)
... 13 more
Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at org.flywaydb.core.internal.util.ClassUtils.instantiate(ClassUtils.java:57)
... 14 more
Not sure why this is. Here is my pom.xml file:
<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>
<groupId>com.serverless</groupId>
<artifactId>hello</artifactId>
<packaging>jar</packaging>
<version>dev</version>
<name>hello</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j2</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.10</version>
</dependency>
<!-- Added by me -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>6.4.3</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!-- End added by me -->
</dependencies>
<build>
<plugins>
<!--
Using the Apache Maven Shade plugin to package the jar
"This plugin provides the capability to package the artifact
in an uber-jar, including its dependencies and to shade - i.e. rename -
the packages of some of the dependencies."
Link: https://maven.apache.org/plugins/maven-shade-plugin/
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer">
</transformer>
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.github.edwgiz</groupId>
<artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
The serverless.yml file:
service: flyway
# app and org for use with dashboard.serverless.com
#app: your-app-name
#org: your-org-name
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"
provider:
name: aws
runtime: java8
package:
artifact: target/hello-dev.jar
functions:
flyway:
handler: com.serverless.Handler
The Handler.java class :
package com.serverless;
import java.util.Collections;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class Handler implements RequestHandler<Map<String, Object>, ApiGatewayResponse> {
private static final Logger LOG = LogManager.getLogger(Handler.class);
FlywayMigrations flyway = new FlywayMigrations();
@Override
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
flyway.migrate();
LOG.info("received: {}", input);
Response responseBody = new Response("Go Serverless v1.x! Your function executed successfully!", input);
return ApiGatewayResponse.builder()
.setStatusCode(200)
.setObjectBody(responseBody)
.setHeaders(Collections.singletonMap("X-Powered-By", "AWS Lambda & serverless"))
.build();
}
}
And finally the custom created class, FlywayMigrations.java :
package com.serverless;
import org.flywaydb.core.Flyway;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
class FlywayMigrations {
private final String jdbcURL = "jdbc:postgresql://127.0.0.1:5432/flyway_test";
private final String dbUser = null;
private final String dbPass = null;
private final Flyway flyway = Flyway.configure().dataSource(jdbcURL, dbUser, dbPass).load();
private static final Logger LOG = LogManager.getLogger(FlywayMigrations.class);
protected void migrate() {
LOG.info("Starting Flyway migrations.");
flyway.migrate();
LOG.info("Flyway migrations completed.");
}
}