Spring BootをAWS Lambdaで動かす – (2)HanderクラスをApplication Contextとして指定する
はじめに
前回、Spring BootをAWS Lambdaで動かす方法について書きました。今回も同じテーマなのですが「@Autowired」アノテーションを使用してComponentのインスタンスを取得する、よりSpring Bootらしい実装ができたので、それについて書きたいと思います。
実装について - 今回変わったところ
「@Autowired」アノテーションなどSpringの機能を使用するため、今回はLambdaのHandlerを実装するクラスをSpringのApplication Contextとして指定しました。以下に、今回変更があったクラスについて記述します。
1.RequestHandler
Lambdaのエントリーポイントとなるhanderを実装するクラスです。先にも書いたように、このクラスをApplication Contextとして指定します。
LambdaFunctionHandler.java
package com.example; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import lombok.Setter; @SpringBootApplication public class LambdaFunctionHandler implements RequestHandler<Object, Object>{ @Autowired private SampleBean sampleBean; @Autowired private ConfigReader configReader; @Setter private Object input; @Setter private Context context; @Override public Object handleRequest(Object input, Context context) { context.getLogger().log("-----start.-----"); String args[] = new String[0]; try (ConfigurableApplicationContext ctx = SpringApplication.run(LambdaFunctionHandler.class, args)) { LambdaFunctionHandler app = ctx.getBean(LambdaFunctionHandler.class); app.setInput(input); app.setContext(context); app.run(args); context.getLogger().log("-----end.-----"); return "success."; } catch (Exception e) { e.printStackTrace(); context.getLogger().log("error.\n"); return "error."; } } public void run(String... args) throws Exception { String inputValue = sampleBean.sampleMethod(input.toString()); context.getLogger().log(inputValue); context.getLogger().log("Region = " + configReader.getRegion()); context.getLogger().log("Bucket = " + configReader.getBucket()); context.getLogger().log("file = " + configReader.getFile()); } }
handlerを持つクラスに対して、13行目で「@SpringBootApplication」アノテーションを付与してSpring Bootとして開始できるようにしています。32・33行目でこのクラスをApplication Contextとし、36行目でrunメソッドを呼び出しています。行いたい主な処理は、このrunメソッド内に記述することになります。
またrunメソッド内でLambdaのhandlerが取得する2つの変数「input」「context」を使用するため、34・35行目でSetterを呼び出してセットしています。なお「input」「context」にはlombokの「@Setter」アノテーションを付与することで、Setterを自動的に生成しています。
runメソッド内で使用したい2つのCompornent「SampleBean」「ConfigReader」は、16・19行目で「@Autowired」アノテーションを付与して宣言しています。これにより、Springにより自動的にインスタンスが作成されることになります。
2.Applicationクラス
前回はApplicationクラス内に、Beanを取得するメソッドを用意しました。今回は「@Autowired」アノテーションでBeanのインスタンスは取得するため、そのメソッドは削除します。実際は上記のhanderより起動するため、Lambdaでの実行だけを考慮すれば必要ないクラスかもしれません。
Application.java
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
3.ConfigReaderクラス
前回はConfigReaderクラス内でComponentのインスタンスを取得するため、先に削除したApplicationクラスのBeanを取得するメソッドを呼び出していました。今回は「@Autowired」アノテーションでComponentのインスタンスを取得します。以下のソースの9行目がその箇所です。
ConfigReader.java
package com.example; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ConfigReader { @Autowired private Settings settings; public String getRegion(){ return settings.getRegion(); } public String getBucket(){ Map<String, String> map = settings.getS3(); return map.get("bucket"); } public String getFile(){ Map<String, String> map = settings.getS3(); return map.get("file"); } }
まとめ
handerを実装するクラスをApplication ContextとしてSpringを起動することで、「@Autowired」アノテーションを使用することができました。なお、残りのソースについては前回を参照してください。