【问题标题】:Eclipse Spring Boot Problems With AWS DynamoDBAWS DynamoDB 的 Eclipse Spring Boot 问题
【发布时间】:2017-11-09 10:01:48
【问题描述】:

我是第一次试用 AWS DynamoDB。我下载了 AWS SDK 并安装在 Eclipse 中。我设置了 AWS 提供的示例 Java DynamoDB“存储和查询”项目。我在 Eclipse 上将它作为一个简单的 java 应用程序运行,它执行没有问题。我创建了一个新的 Spring-Boot 项目并复制粘贴了应用程序并添加了必要的 Spring-Boot 参数。 Spring-Boot 版本在 main() 代码的第一行出现“java.lang.ClassNotFoundException”失败。在 init() 中执行 AmazoneDynamoDBClientBuilder 期间发生 java.lang.ClassNotFoundException。具体来说,它在 init() 方法的 AmazonDynamoDBClientBuilder 类中失败。代码是干净的并且构建没有错误。我会说我很难从 Maven Central 中选择正确的 jar。 DynamoDB 代码对拥有最新的 jar 版本非常挑剔。

附上代码清单,

package com.belcan;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.HashMap;
import java.util.Map;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.PutItemResult;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.model.ScanRequest;
import com.amazonaws.services.dynamodbv2.model.ScanResult;
import com.amazonaws.services.dynamodbv2.model.TableDescription;
import com.amazonaws.services.dynamodbv2.util.TableUtils;

@SpringBootApplication
public class DynamoTest1Application {

    /*
     * Before running the code:
     *      Fill in your AWS access credentials in the provided credentials
     *      file template, and be sure to move the file to the default location
     *      (C:\\Users\\Stephen\\.aws\\credentials) where the sample code will load the
     *      credentials from.
     *      https://console.aws.amazon.com/iam/home?#security_credential
     *
     * WARNING:
     *      To avoid accidental leakage of your credentials, DO NOT keep
     *      the credentials file in your source directory.
     */

    static AmazonDynamoDB dynamoDB;

    /**
     * The only information needed to create a client are security credentials
     * consisting of the AWS Access Key ID and Secret Access Key. All other
     * configuration, such as the service endpoints, are performed
     * automatically. Client parameters, such as proxies, can be specified in an
     * optional ClientConfiguration object when constructing a client.
     *
     * @see com.amazonaws.auth.BasicAWSCredentials
     * @see com.amazonaws.auth.ProfilesConfigFile
     * @see com.amazonaws.ClientConfiguration
     */

    private static void init() throws Exception {
        /*
         * The ProfileCredentialsProvider will return your [default]
         * credential profile by reading from the credentials file located at
         * (C:\\Users\\Stephen\\.aws\\credentials).
         */
        System.out.println("Starting Init()");

        ProfileCredentialsProvider credentialsProvider = new ProfileCredentialsProvider();

        try {
            credentialsProvider.getCredentials();
        } catch (Exception e) {
            throw new AmazonClientException(
                    "Init()-1: Cannot load the credentials from the credential profiles file. " +
                    "Please make sure that your credentials file is at the correct " +
                    "location (C:\\Users\\Stephen\\.aws\\credentials), and is in valid format.",
                    e);
        }

        System.out.println("Init()-1 Complete");

        try {

        /****** Fails Right Here!!  Line 86 is ".withCredentials(credentialsProvider)" *****/
        dynamoDB = AmazonDynamoDBClientBuilder.standard()
            .withCredentials(credentialsProvider)
            .build();
        } catch (Exception e) {
            throw new AmazonClientException(
                    "Init()-2: Cannot build client", e);
        }

        System.out.println("Init()-2 Complete");
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(DynamoTest1Application.class, args);

        /***** This is line 98 ****/
        init();

        try {
            String tableName = "my-favorite-movies-table";

            // Create a table with a primary hash key named 'name', which holds a string
            CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName)
                .withKeySchema(new KeySchemaElement().withAttributeName("name").withKeyType(KeyType.HASH))
                .withAttributeDefinitions(new AttributeDefinition().withAttributeName("name").withAttributeType(ScalarAttributeType.S))
                .withProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(1L).withWriteCapacityUnits(1L));

            // Create table if it does not exist yet
            TableUtils.createTableIfNotExists(dynamoDB, createTableRequest);
            // wait for the table to move into ACTIVE state
            TableUtils.waitUntilActive(dynamoDB, tableName);

            // Describe our new table
            DescribeTableRequest describeTableRequest = new DescribeTableRequest().withTableName(tableName);
            TableDescription tableDescription = dynamoDB.describeTable(describeTableRequest).getTable();
            System.out.println("Table Description: " + tableDescription);

            // Add an item
            Map<String, AttributeValue> item = newItem("Bill & Ted's Excellent Adventure", 1989, "****", "James", "Sara");
            PutItemRequest putItemRequest = new PutItemRequest(tableName, item);
            PutItemResult putItemResult = dynamoDB.putItem(putItemRequest);
            System.out.println("Result: " + putItemResult);

            // Add another item
            item = newItem("Airplane", 1980, "*****", "James", "Billy Bob");
            putItemRequest = new PutItemRequest(tableName, item);
            putItemResult = dynamoDB.putItem(putItemRequest);
            System.out.println("Result: " + putItemResult);

            // Scan items for movies with a year attribute greater than 1985
            HashMap<String, Condition> scanFilter = new HashMap<String, Condition>();
            Condition condition = new Condition()
                .withComparisonOperator(ComparisonOperator.GT.toString())
                .withAttributeValueList(new AttributeValue().withN("1985"));
            scanFilter.put("year", condition);
            ScanRequest scanRequest = new ScanRequest(tableName).withScanFilter(scanFilter);
            ScanResult scanResult = dynamoDB.scan(scanRequest);
            System.out.println("Result: " + scanResult);

        } catch (AmazonServiceException ase) {
            System.out.println("Caught an AmazonServiceException, which means your request made it "
                    + "to AWS, but was rejected with an error response for some reason.");
            System.out.println("Error Message:    " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code:   " + ase.getErrorCode());
            System.out.println("Error Type:       " + ase.getErrorType());
            System.out.println("Request ID:       " + ase.getRequestId());
        } catch (AmazonClientException ace) {
            System.out.println("Caught an AmazonClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with AWS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message: " + ace.getMessage());
        }
    }

    private static Map<String, AttributeValue> newItem(String name, int year, String rating, String... fans) {
        Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
        item.put("name", new AttributeValue(name));
        item.put("year", new AttributeValue().withN(Integer.toString(year)));
        item.put("rating", new AttributeValue(rating));
        item.put("fans", new AttributeValue().withSS(fans));

        return item;
    }

}

我收到以下错误,

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.8.RELEASE)

2017-11-08 13:44:58.450  INFO 21012 --- [           main] com.belcan.DynamoTest1Application        : Starting DynamoTest1Application on skmi5-7000 with PID 21012 (C:\Users\Stephen\Desktop\BCN\Projects\360Yield\swdev\360yield\360examples\DynamoTest1\bin started by Stephen in C:\Users\Stephen\Desktop\BCN\Projects\360Yield\swdev\360yield\360examples\DynamoTest1)
2017-11-08 13:44:58.456  INFO 21012 --- [           main] com.belcan.DynamoTest1Application        : No active profile set, falling back to default profiles: default
2017-11-08 13:44:58.544  INFO 21012 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@59717824: startup date [Wed Nov 08 13:44:58 EST 2017]; root of context hierarchy
2017-11-08 13:44:59.089  INFO 21012 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-11-08 13:44:59.104  INFO 21012 --- [           main] com.belcan.DynamoTest1Application        : Started DynamoTest1Application in 1.185 seconds (JVM running for 2.316)
Starting Init()
Init()-1 Complete
Exception in thread "main" java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper
    at com.amazonaws.internal.config.InternalConfig.<clinit>(InternalConfig.java:43)
    at com.amazonaws.internal.config.InternalConfig$Factory.<clinit>(InternalConfig.java:304)
    at com.amazonaws.util.VersionInfoUtils.userAgent(VersionInfoUtils.java:142)
    at com.amazonaws.util.VersionInfoUtils.initializeUserAgent(VersionInfoUtils.java:137)
    at com.amazonaws.util.VersionInfoUtils.getUserAgent(VersionInfoUtils.java:100)
    at com.amazonaws.ClientConfiguration.<clinit>(ClientConfiguration.java:65)
    at com.amazonaws.ClientConfigurationFactory.getDefaultConfig(ClientConfigurationFactory.java:46)
    at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientConfigurationFactory.getDefaultConfig(AmazonDynamoDBClientConfigurationFactory.java:31)
    at com.amazonaws.ClientConfigurationFactory.getConfig(ClientConfigurationFactory.java:36)
    at com.amazonaws.client.builder.AwsClientBuilder.resolveClientConfiguration(AwsClientBuilder.java:163)
    at com.amazonaws.client.builder.AwsClientBuilder.access$000(AwsClientBuilder.java:52)
    at com.amazonaws.client.builder.AwsClientBuilder$SyncBuilderParams.<init>(AwsClientBuilder.java:411)
    at com.amazonaws.client.builder.AwsClientBuilder.getSyncClientParams(AwsClientBuilder.java:354)
    at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
    at com.belcan.DynamoTest1Application.init(DynamoTest1Application.java:86)
    at com.belcan.DynamoTest1Application.main(DynamoTest1Application.java:98)
Caused by: java.lang.ClassNotFoundException: com.fasterxml.jackson.databind.ObjectMapper
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 16 more
2017-11-08 13:44:59.130  INFO 21012 --- [       Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@59717824: startup date [Wed Nov 08 13:44:58 EST 2017]; root of context hierarchy
2017-11-08 13:44:59.133  INFO 21012 --- [       Thread-2] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

您真的不必挖得很远就能看到错误。失败发生在 main() 的第一行代码,init() 方法。 你可以看到我在方法中放了几个 println 来看看我能走多远。我通过了 init() 的第一部分,即凭证检索。我在 init() 的第二部分失败,即构建 DynamoDB 客户端的 AmazonDynamoDBClientBuilder。罐子里似乎发生了一些奇怪的事情。原始 AWS Java 代码是为 maven 编写的。我正在为 Spring Boot 使用 Gradle。我查看了原始的 AWS pom.xml 文件,发现它引用了 2 个依赖项,

aws-java-sdk-1.11.225
aws-kinesis-client-1.2.1

我将这两个包含在我的 gradle 构建中。以下是我正在使用的罐子。

amazon-kinesis-client-1.8.7.jar
aws-java-sdk-1.11.225 (1).jar
aws-java-sdk-core-1.11.226 (1).jar
aws-java-sdk-dynamodb-1.11.226 (2).jar

对正在发生的事情有任何想法吗?看起来我缺少一个罐子或没有附上正确的罐子。已经工作了2天,没有运气。任何帮助都会很棒。

【问题讨论】:

    标签: java eclipse spring-boot amazon-dynamodb


    【解决方案1】:

    将此添加到您的 gradle.build:

    compile("com.fasterxml.jackson.core:jackson-databind:2.9.2")
    

    【讨论】:

    • 这并没有完全解决我的问题。我添加了上面突出显示的依赖项 AlexGera,但我刚刚为不同的 jar 获得了另一个“ClassNotFoundException”。但是,它使我意识到了实际问题。 AWS 提供对 POJO 的支持,而不是 Spring Boot。 AWS 构建的 POJO 项目包含一组相当大的 Maven 依赖项,这些依赖项不在 Eclipse Spring Boot 构建中。我必须弄清楚如何在我的 Eclipse Gradle Spring Boot 项目中获取所有这些依赖项。任何人都知道如何轻松解决此问题,而无需输入 30 或 40 个 Gradle 依赖项?
    • AWS 既不为 Spring 也不为 POJO 提供任何支持(顺便说一句,这是什么意思?)。您在这里所要做的只是添加正确的库作为正确构建阶段的依赖项。例如,在您的原始错误中,DynamoDB 配置尝试从 XML 中读取并且找不到要使用的编组器库。如果需要,您可以发布下一个错误
    • 另外关于“原始 AWS Java 代码是为 maven 编写的。我正在使用 Gradle 进行 Spring Boot。” - 没关系。无法为 Maven、Gradle 或 Ivy 编写代码。 Gradle 使用 Maven 作为场景下的工件存储库(如果没有指定其他)。 Gradle 是一个构建框架并包装了 Maven 的工件存储库
    • Alex,感谢您的 cmets,我同意您对 Maven/Gradle 的回复。我有两个问题,现在问题已解决。首先,正如你所建议的,我错过了几个杰克逊罐子。第二个问题是我没有使用最新版本的 jars。我在最新版本级别添加了所有必要的 jar,现在项目可以正常构建和运行。
    • 没问题。干得好!
    猜你喜欢
    • 1970-01-01
    • 2019-05-29
    • 2023-01-09
    • 2021-10-20
    • 2020-12-04
    • 1970-01-01
    • 2016-12-05
    • 2022-12-25
    • 1970-01-01
    相关资源
    最近更新 更多