java - 将 Spring boot/cloud 与 Amazon AWS lambda 一起使用不会注入(inject)值

标签 java spring spring-boot spring-cloud aws-lambda

我有一个由 AWS 直接调用的 AWS lambda RequestHandler 类。最终我需要让它与 Spring Boot 一起工作,因为我需要它能够从 Spring Cloud 配置服务器检索数据。

问题是代码如果我在我自己的开发环境中本地运行可以工作,但在 AWS 上部署时无法注入(inject)配置值

@Configuration
@EnableAutoConfiguration
@ComponentScan("my.package")
public class MyClass implements com.amazonaws.services.lambda.runtime.RequestHandler<I, O> {
   public O handleRequest(I input, Context context) {
        ApplicationContext applicationContext = new SpringApplicationBuilder()
                .main(getClass())
                .showBanner(false)
                .web(false)
                .sources(getClass())
                .addCommandLineProperties(false)
                .build()
                .run();

        log.info(applicationContext.getBean(SomeConfigClass.class).foo);
        // prints cloud-injected value when running from local dev env
        //
        // prints "${path.to.value}" literal when running from AWS 
        //    even though Spring Boot starts successfully without errors
   }
}

@Configuration
public class SomeConfigClass {
   @Value("${path.to.value}")
   public String foo;
}

src/main/resources/bootstrap.yml:
spring:
  application:
    name: my_service
cloud:
  config:
    uri: http://my.server
    failFast: true
    profile: localdev

我尝试了什么:

  • 使用常规的 Spring MVC,但是这个 doesn't have integration with @Value injection/Spring cloud .
  • 使用 @PropertySource - 但发现它不支持 .yml 文件
  • 已验证以确保配置服务器正在为任何 IP 地址的请求提供服务(没有 IP 地址过滤)
  • 运行 curl 以确保返回值
  • 已验证以确保 .jar 在 jar 根目录中实际包含 bootstrap.yml
  • 已验证以确保 .jar 实际上包含 Spring Boot 类。 FWIW 我正在使用 Maven shade 插件,它将项目打包成一个包含所有依赖项的胖 .jar。

注意:AWS Lambda 支持环境变量,因此我不能设置像 spring.application.name 之类的东西(既不能作为环境变量也不能作为 - D 参数)。我也无法控制实际启动 MyClass 的底层类 - 这对最终用户是完全透明的。我只是打包jar并提供入口点(类名),剩下的就处理好了。

有什么我可能错过的吗?有什么办法可以更好地调试它?

最佳答案

经过一些调试,我确定问题出在使用 Maven Shade 插件上。 Spring Boot 在其自动配置 jar 中查找 META-INF/spring.factories jar see here有关这方面的一些信息。为了正确打包 Spring Boot jar,您需要使用 Spring Boot Maven Plugin并将其设置为在 Maven 重新打包阶段运行。它在本地 IDE 中工作的原因是因为您没有运行 Shade 打包的 jar。他们在他们的插件中使用了一些特殊的魔法,以便在 Shade 插件不知道的正确位置找到东西。

我能够创建一些最初没有注入(inject)值但现在我使用了正确的插件的示例代码。见 this GitHub repo看看我做了什么。

我没有将它与 Spring Cloud 连接,但现在 Spring Boot 注入(inject)的其余部分正在工作,我认为它应该很简单。

正如我在评论中提到的,您可能只想考虑一个简单的 REST 调用来获取云配置并自己注入(inject)它,以节省每次请求加载 Spring 应用程序的开销。

更新:对于 Spring Boot 1.4.x,您必须在 Spring Boot 插件中提供此配置:

            <configuration>
                <layout>MODULE</layout>
            </configuration>

如果你不这样做,那么默认情况下,插件的新行为是将所有 jar 放在 BOOT-INF 下,因为目的是让 jar 可执行并让引导进程加载它。我在为这里遇到的情况添加警告时发现了这一点。见 https://github.com/spring-projects/spring-boot/issues/5465供引用。

关于java - 将 Spring boot/cloud 与 Amazon AWS lambda 一起使用不会注入(inject)值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36081908/

相关文章:

Java String.intern() 使用 HashTable 而不是 ConcurrentHashMap

spring - 类型不匹配 - 为什么会出现此错误?

javascript - 即使操作成功,Ajax post 也返回 404

spring - 在Spring-Data-Redis中使用RedisTemplate时如何选择dbIndex?

java - JPA 存储库和 Spring Security - 更新对象使密码无效

java - 用作 websphere 8 应用程序的 -javaagent 的 openjpa jar 位于哪里?

java - Cassandra 在保存 java.util.UUID 时说 "InvalidQueryException: Invalid version for TimeUUID type"

java - 在 Linux 上哪里可以放置 .jar 文件?

java - ReloadingCombinedConfigurationBuilder 在 1 次重新加载后未重新加载

java - mockito JAX-WS 代理中的 Classcastexception