AmazonのDynamoDBに大きく依存するアプリケーションをテストする必要があります。テストを個別に実行できるようにしたいので、DynamoDB Local .jar
を選択しました。私は最近の更新を認識しており、外部のbashコマンドを呼び出さなくてもこれを実行できるようになっています。ただし、指定された例を実行しようとすると、 ここ 、次のスタックトレースが取得されます。
Exception in thread "main" com.amazonaws.AmazonServiceException: The request processing has failed because of an unknown error, exception or failure. (Service: AmazonDynamoDBv2; Status Code: 500; Error Code: InternalFailure; Request ID: cab7a550-aaa6-4bfe-a591-0b255481cc14)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.Java:1275)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.Java:873)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.Java:576)
at com.amazonaws.http.AmazonHttpClient.doExecute(AmazonHttpClient.Java:362)
at com.amazonaws.http.AmazonHttpClient.executeWithTimer(AmazonHttpClient.Java:328)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.Java:307)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.Java:1805)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.listTables(AmazonDynamoDBClient.Java:1223)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.listTables(AmazonDynamoDBClient.Java:1235)
これは私が実行しようとしているコードです:
public static void main( String[] args ) throws Exception
{
AmazonDynamoDB dynamodb = null;
DynamoDBProxyServer server = null;
final String[] localArgs = { "-inMemory", "-port", "13005" };
server = ServerRunner.createServerFromCommandLineArgs(localArgs);
server.start();
BasicAWSCredentials auth = new BasicAWSCredentials("key", "secret");
dynamodb = new AmazonDynamoDBClient(auth);
dynamodb.setEndpoint("http://127.0.0.1:13005");
// use the DynamoDB API over HTTP
System.out.println(dynamodb.listTables());
// Stop the DynamoDB Local endpoint
if(server != null) {
server.stop();
}
}
Javaプログラム自体から完全に実行しようとすると、例外がスローされ、指定されたポートが使用できなくなることがわかりました(このポートが次のようになっていることを示すエラーがスローされます)しかし、コマンドプロンプトからDynamoDB Localを起動し、Javaプログラムをアクセスクライアントとしてのみ使用すると、すべてが正常に実行されます。何か提案はありますか?
DynamoDBLocalには少なくとも2つの問題があります。両方を解決すると、組み込みのDynamoDBが実行されます。
まず、-port
パラメーターが正しく機能しません。そのため、Jettyは期待するポートにセットアップされていません。代わりに、ポート51205(またはランダム?)のようなものがデフォルトポートとしてJettyリスナーとして設定されます。
これは、組み込みのコマンドライン解析を回避してサーバーを起動する方法のコードです。この方法でサーバーを起動した後、 http:// localhost:19444/Shell 動作するので、桟橋は大丈夫です。ただし、Sqlite4Javaで別の問題が発生する可能性があります(コードブロックの後を参照)。
注:コードはKotlinですが、Javaは非常に似ています。また、SLF4jを構成し、ServerRunner
クラスがログを中断しないようにしているので、これはサーバーを起動するための2倍良い方法であり、ServerRunner
が内部で行うことです。
class TestAccountManager {
companion object {
private val localDbPort = 19444
private lateinit var localDb: DynamoDBProxyServer
private lateinit var dbClient: AmazonDynamoDBClient
@BeforeClass @JvmStatic fun setup() {
System.setProperty("org.Eclipse.jetty.util.log.class", "org.Eclipse.jetty.util.log.Slf4jLog")
localDb = DynamoDBProxyServer(localDbPort, LocalDynamoDBServerHandler(
LocalDynamoDBRequestHandler(0, true, null, true, true), null)
)
localDb.start()
val auth = BasicAWSCredentials("fakeKey", "fakeSecret")
dbClient = AmazonDynamoDBClient(auth)
dbClient.signerRegionOverride = "us-east-1"
dbClient.setEndpoint("http://localhost:$localDbPort")
}
@AfterClass @JvmStatic fun teardown() {
localDb.stop()
}
}
@Test fun testSomething() {
dbClient.listTables().tableNames.forEach {
println(it)
}
}
}
このコードを取得すると、期待されるポートで実行されます。
これで、Sqlite4Javaがプラットフォームに適したバイナリを見つけられないなど、2番目のエラーが発生する可能性があります。 Mac OSXの一部のバージョンでは、実際には存在しないバイナリファイル名が生成されます。また、DynamoDBLocalは、すべてのSqlite4Javaログを強制的に非表示にするため(オーバーライドできません)、表示されません。
Sqliteライブラリをテストするには、 ディストリビューションをダウンロード 、解凍してから実行します。
Java -jar sqlite4Java-1.0.392.jar -d
そして、何をロードしようとしたか、どのように失敗したかを報告します。 Gradle、Maven、または配置した場所から、システム上でそのJARを見つける必要があります。エラーのある出力は次のとおりです。
sqlite4Java 392
160212:002049.833 FINE [sqlite] Internal: loading library
160212:002049.834 FINE [sqlite] Internal: Java.library.path=/Users/jminard/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/Java:.
160212:002049.834 FINE [sqlite] Internal: sqlite4Java.library.path=null
160212:002049.834 FINE [sqlite] Internal: cwd=/Users/jminard/DEV/Collokia/repos/collokia-web-back/.
160212:002049.834 FINE [sqlite] Internal: default path=/Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d
160212:002049.834 FINE [sqlite] Internal: forced path=null
160212:002049.834 FINE [sqlite] Internal: os.name=mac os x; os=osx
160212:002049.835 FINE [sqlite] Internal: os.Arch=x86_64
160212:002049.835 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-x86_64-1.0.392.dylib
160212:002049.835 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-AMD64-1.0.392.dylib
160212:002049.835 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-1.0.392.dylib
160212:002049.835 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-1.0.392.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-x86_64-d-1.0.392.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-AMD64-d-1.0.392.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-d-1.0.392.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-d-1.0.392.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-x86_64.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-AMD64.dylib
160212:002049.836 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx.dylib
160212:002049.837 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java.dylib
160212:002049.837 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-x86_64-d.dylib
160212:002049.837 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-AMD64-d.dylib
160212:002049.837 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-osx-d.dylib
160212:002049.837 FINE [sqlite] Internal: checking /Users/jminard/.gradle/caches/modules-2/files-2.1/com.almworks.sqlite4Java/sqlite4Java/1.0.392/d6234e08ff4e1607ff5321da2579571f05ff778d/libsqlite4Java-d.dylib
160212:002049.837 FINE [sqlite] Internal: trying to load sqlite4Java-osx-x86_64-1.0.392
160212:002049.838 FINE [sqlite] Internal: cannot load sqlite4Java-osx-x86_64-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-x86_64-1.0.392 in Java.library.path
160212:002049.838 FINE [sqlite] Internal: trying to load sqlite4Java-osx-AMD64-1.0.392
160212:002049.839 FINE [sqlite] Internal: cannot load sqlite4Java-osx-AMD64-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-AMD64-1.0.392 in Java.library.path
160212:002049.839 FINE [sqlite] Internal: trying to load sqlite4Java-osx-1.0.392
160212:002049.840 FINE [sqlite] Internal: cannot load sqlite4Java-osx-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-1.0.392 in Java.library.path
160212:002049.840 FINE [sqlite] Internal: trying to load sqlite4Java-1.0.392
160212:002049.841 FINE [sqlite] Internal: cannot load sqlite4Java-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-1.0.392 in Java.library.path
160212:002049.841 FINE [sqlite] Internal: trying to load sqlite4Java-osx-x86_64-d-1.0.392
160212:002049.842 FINE [sqlite] Internal: cannot load sqlite4Java-osx-x86_64-d-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-x86_64-d-1.0.392 in Java.library.path
160212:002049.842 FINE [sqlite] Internal: trying to load sqlite4Java-osx-AMD64-d-1.0.392
160212:002049.842 FINE [sqlite] Internal: cannot load sqlite4Java-osx-AMD64-d-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-AMD64-d-1.0.392 in Java.library.path
160212:002049.843 FINE [sqlite] Internal: trying to load sqlite4Java-osx-d-1.0.392
160212:002049.843 FINE [sqlite] Internal: cannot load sqlite4Java-osx-d-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-d-1.0.392 in Java.library.path
160212:002049.843 FINE [sqlite] Internal: trying to load sqlite4Java-d-1.0.392
160212:002049.844 FINE [sqlite] Internal: cannot load sqlite4Java-d-1.0.392: Java.lang.UnsatisfiedLinkError: no sqlite4Java-d-1.0.392 in Java.library.path
160212:002049.844 FINE [sqlite] Internal: trying to load sqlite4Java-osx-x86_64
160212:002049.845 FINE [sqlite] Internal: cannot load sqlite4Java-osx-x86_64: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-x86_64 in Java.library.path
160212:002049.845 FINE [sqlite] Internal: trying to load sqlite4Java-osx-AMD64
160212:002049.845 FINE [sqlite] Internal: cannot load sqlite4Java-osx-AMD64: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-AMD64 in Java.library.path
160212:002049.845 FINE [sqlite] Internal: trying to load sqlite4Java-osx
160212:002049.846 FINE [sqlite] Internal: cannot load sqlite4Java-osx: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx in Java.library.path
160212:002049.846 FINE [sqlite] Internal: trying to load sqlite4Java
160212:002049.847 FINE [sqlite] Internal: cannot load sqlite4Java: Java.lang.UnsatisfiedLinkError: no sqlite4Java in Java.library.path
160212:002049.847 FINE [sqlite] Internal: trying to load sqlite4Java-osx-x86_64-d
160212:002049.848 FINE [sqlite] Internal: cannot load sqlite4Java-osx-x86_64-d: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-x86_64-d in Java.library.path
160212:002049.848 FINE [sqlite] Internal: trying to load sqlite4Java-osx-AMD64-d
160212:002049.849 FINE [sqlite] Internal: cannot load sqlite4Java-osx-AMD64-d: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-AMD64-d in Java.library.path
160212:002049.849 FINE [sqlite] Internal: trying to load sqlite4Java-osx-d
160212:002049.849 FINE [sqlite] Internal: cannot load sqlite4Java-osx-d: Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-d in Java.library.path
160212:002049.850 FINE [sqlite] Internal: trying to load sqlite4Java-d
160212:002049.850 FINE [sqlite] Internal: cannot load sqlite4Java-d: Java.lang.UnsatisfiedLinkError: no sqlite4Java-d in Java.library.path
Error: cannot load SQLite
Java.lang.UnsatisfiedLinkError: no sqlite4Java-osx-x86_64-1.0.392 in Java.library.path
at Java.lang.ClassLoader.loadLibrary(ClassLoader.Java:1864)
at Java.lang.Runtime.loadLibrary0(Runtime.Java:870)
at Java.lang.System.loadLibrary(System.Java:1122)
at com.almworks.sqlite4Java.Internal.tryLoadFromSystemPath(Internal.Java:352)
at com.almworks.sqlite4Java.Internal.loadLibraryX(Internal.Java:124)
at com.almworks.sqlite4Java.SQLite.main(SQLite.Java:368)
ダイナミックライブラリのロードについてエラーが発生した場合は、以下を読んで解決方法を確認してください。
確実に機能すると思われる唯一の答えは、次のいずれかです。
Java.library.path
/Library/Java/Extensions
にライブラリを追加します(macOSのみ)これらのうち、私は最初のオプションのようなことを行い、ライブラリをプロジェクトに追加し、ビルドがダイナミックライブラリが解凍される場所に-Djava.library.path=./lib/sqlite4Java
を追加することを確認します。より回復力のあるテストのために、このトリックを使用してコードにプログラムでJava.library.path
を設定できます(そうでない場合、コードで設定すると無視されます): http://blog.cedarsoft.com/2010/11/setting -Java-library-path-programmatically /
DynamoDBLocalがすべてのSqliteエラーを非表示にするのは悪いことなので、サイレントエラーを見つけるにはデバッグする必要があります。ライブラリには、ログレベルを調整し、エラーを確認する機能が損なわれるため、デバッグが困難になるものがたくさんあります。たとえば、SqlLiteファイルが開かれるたびに(クラスSQLiteDBAccess
):
LocalDBUtils.setLog4jToUtilsLogging("com.almworks.sqlite4Java");
LocalDBUtils.setLog4jToUtilsLogging("com.almworks.sqlite4Java.Internal");
Java.util.logging.Logger.getLogger("com.almworks.sqlite4Java").setLevel(Level.OFF);
Java.util.logging.Logger.getLogger("com.almworks.sqlite4Java.Internal").setLevel(Level.OFF);
クロージングノート:私は代替案を検討していますが、これはDynamoDbLocalのコードとそのために行われた決定を見て、地球上で最もよく構築されたものは、私にほとんど自信を与えません。 オルタネーター または Jcabi --Dynamo Mock が私のリストの次です。
2018年8月 Amazonが発表 新しい Dockerイメージ Amazon DynamoDBLocalをオンボードで。 JARをダウンロードして実行したり、サードパーティのOS固有のバイナリを使用して追加したりする必要はありません(私はsqlite4Java
について話しています)。
テストの前にDockerコンテナを起動するのと同じくらい簡単です。
docker run -p 8000:8000 Amazon/dynamodb-local
上記のように、ローカル開発のために手動で行うことができます。 IDEは通常、タスクを実行する前に任意のコマンドを実行する方法を提供するため、 make IDE でコンテナを起動できます。
または、CIパイプラインで使用できます。多くのCIサービスは、パイプライン中に追加のコンテナーを開始する機能を提供し、テストの依存関係を提供できます。 Gitlab CI/CDの例を次に示します。
test:
stage: test
image: openjdk:8-Alpine
services:
- name: Amazon/dynamodb-local
alias: dynamodb-local
script:
- DYNAMODB_LOCAL_URL=http://dynamodb-local:8000 ./gradlew clean test
またはBitbucketパイプライン:
definitions:
services:
dynamodb-local:
image: Amazon/dynamodb-local
…
step:
name: test
image:
name: openjdk:8-Alpine
services:
- dynamodb-local
script:
- DYNAMODB_LOCAL_URL=http://localhost:8000 ./gradlew clean test