こんにちは、久々にJavaを触った小野です。
今回は、JavaでAWS Cloud Development Kit(以下CDK)を使ってEC2をデプロイしようとしたときに詰まったことについて書いていきます。
きっかけ
サンプルコードを参考にしながら、VPCを作成しそこにEC2を1つ作成するという単純なコードを書いていたのですが、何回cdk synthコマンドを実行しても
An exception occured while executing the Java class. Error: Cannot reference across apps. Consuming and producing stacks must be defined within the same CDK app.
というエラーが発生しました。
エラー内容的にEC2を作成するあたりでエラーを吐いてるので、試しにEc2StackクラスをコメントアウトしてVpcスタックだけにした状態でcdk synthコマンドを実行すると
This app contains no stacks
となってしまいます。
エラー文をネットで調べたり、GaiXerに聞いたりしても、リージョンをまたいだリソース作成についてしか出てこなかったので途方に暮れていました。
原因
VpcStackを作成するクラスのコンストラクタで、親クラスのコンストラクタを呼び出すsuperが抜けていたのが原因でした。
スタックを作成するクラスはStackクラスを継承するのですが、そのStackクラスの引数ありコンストラクタ内に
JavaJsiiEngine.getInstance().createNewObject(this, new Object[]{scope, id, props});
という文があり、そこが実行されないためにスタックとして認識されていなかったようです。
superで明示的に親クラスのコンストラクタを呼び出さない場合は引数無しのデフォルトコンストラクタが呼ばれるのですが、そこには上のような文はありません。
そのため、Ec2Stackを作成するクラスでVpcスタックが参照できず、エラーになっていたんですね。
解決
原因で書いたように、superが抜けていただけだったのでその1行を書き足せば無事にcdk synthコマンドが通りテンプレートが作成されました。
誤
Javapublic VpcStack(final Construct scope, final String id, final StackProps props) {
this.vpc = Vpc.Builder.create(this, "VPC").build();
}
正
Javapublic VpcStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
this.vpc = Vpc.Builder.create(this, "VPC").build();
}
最後に
今まで親クラスのコンストラクタでの処理が無くて困る事態になったことが無かったので、まさかsuperが原因とは思わず原因究明にはかなり手間取りました。
親クラスを継承するときはちゃんとsuper使わないとダメですね。
ちなみに、最近よく使ってるTypeScriptだとsuperが無いとデフォルトコンストラクタを呼ぶのではなく、そもそもエラーになるのでこんな悲劇は起きずに済みます。
CDK自体がTypeScriptで書かれているので、特に理由が無ければTypeScriptを使うのが丸そうですね。