Spring bootの練習日記:2日目

プロジェクトはできたので、ひとまず Building an Application with Spring Boot を読んでみることにした。

Gradleでビルド

gradleでビルドするときには、gradleのspring-bootプラグインがあるようだ。これを使うと、Spring Boot用のtaskが追加され、gradle bootRunでSpring Bootが起動クラスを探して起動してくれるようだ。
また、プラグインはeclipseやideaもあるようだ。これを使うとそれぞれのIDE用のプロジェクトファイルを作ってくれるらしい。自分が使うかどうかはわからない。今のところ、使いどころがいまいちわからない。twitterで話した感じだと、昔はIDEでpom.xmlやbuild.gradleをプロジェクトとして直接読み込めなかったからじゃないか?という結論に至った。

jarブロックで、jarファイル名やバージョン名を指定できるようである。jarブロックで指定できることはかなりあるようだ。

Gradle: DSL jar

buildscriptブロック

毎回コピペするだけで、いまいちよくわかっていなかったのだけれど、buildscriptブロックを書くことで、外部ライブラリをビルドスクリプトとして使う事ができるそうだ。dependenciesブロックで、利用するライブラリのクラスパスとしてspring-boot-gradle-pluginを指定すると、このプラグインで設定されているビルド設定が利用できるので、わざわざ自分でビルド設定を書かなくてもいい、というふうに解釈した。

とりあえず修正してみたのがこれ。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'spring-boot-practice'
    version = '0.1.0'
}

sourceCompatibility = 1.8
version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE")
    testCompile("org.springframework.boot:spring-boot-starter-test:1.2.1.RELEASE")
}

sourceSets {
    main {
        java
    }
    test {
        java
    }
}

gradle buildでビルドはできたし、gradle bootRunで作成中のアプリも起動したし、よしとする。

「Spring Bootで何ができるのかを学ぼう」を読む

ざっと読んだ感じ、Spring Bootは、よりビジネス要件にフォーカスし、インフラストラクチャを気にしないでもよくすると書いてあると解釈した。
例えば、

  • Spring MVCを内包していて、それ単体だとコンテナーが必要だけれど、Spring Bootは組み込みTomcatで動くよ
  • Tomcatが嫌な人はJettyでも動かせるよ
  • Thymeleafが使いたければ、追加するだけで使えるよ(Thymeleafはテンプレートエンジンらしい)

Spring Bootは、automatic configurationで、設定を自動的に読み込むのでThymeleafにパスを通してあれば、自動的にSpringBootTemplateEngineとして使うが、もし独自にSpringBootTemplateEngineに値が設定されていれば、読み込まないらしい。

「シンプルなWebアプリケーションを作ってみる」を読む

このサンプルコードを読むと、Rest用のControllerとApplication起動用のクラスに分けて作ってある。前回作ったのは、起動とレスポンスを同時に行うクラスだったので、このコードに従って分けてみる。

HelloControllerを修正してみた。@RestControllerアノテーションを使うと、@Controllerアノテーションと@ResposeBodyアノテーションを使ったのと同じになるらしい。そして、@RequestMappingアノテーションでルーティングが決まるようだ。

package sample;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/")
    String index() {
        return "Hello World!";
    }
}

Spring Bootで起動させるクラスは別にした。Applicationだ。

package sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

        System.out.println("Let's inspect the beans provided by Spring Boot:");

        String[] beanNames = context.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }
}

3つのアノテーションを使っている。が、説明によると、@SpringBootApplicationアノテーションをつけると全部やってくれるらしい。
以下は3つのアノテーションの説明を読んだ感じ。

@Configuration
アプリケーションコンテキストのbean定義を行う?なんとなくやってることはわかるがJavaの用語がわからないのでわからない。
@EnableAutoConfiguration
Spring Bootに対して、追加されたbeansを元に自動で設定する。
@ComponentScan
sampleパッケージ内のその他のコンポーネント、設定、サービスを読み取る。ここではHelloControllerが自動的に読み取られる。

あと、通常だと@EnableWebMvcも書くらしいのだが、Spring Bootなら自動で読み込んでくれるらしい。

とりあえず、@SpringBootApplicationでいいらしいのでそうしてみた。

package sample;

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

import java.util.Arrays;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

        System.out.println("Let's inspect the beans provided by Spring Boot:");

        String[] beanNames = context.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }
}

アノテーションが1つになって見やすくなった。

この状態でgradle bootRunを行い、http://localhost:8080にアクセスしたら、Hello World!が出た。

とりあえず今日はここまでとする。


Spring Bootの練習日記:1日目

WebのフレームワークはPHPのCakePHP, RubyのRuby on Railsときて、JavaのやつはSlim3以外は触ったことがなく、全くに近いほどJavaでのWeb開発についての知識が皆無です。未だによくわかってません。Javaは3文字の略語も多くて本当に私にとっては魔境でしかないのですが、それでもやってみたいという気持ちはあります。型安全ですし。
そこで、Javaで今からやるとしたらどのフレームワークがいいかなー?とFacebookに書いてみたところ、岡山Javaユーザー会 代表であり、同僚の@zephiransasさんに「今だとSpring Bootかなー?」とアドバイスを頂いたので、とりあえずSpring Bootをやってみます!

Spring Bootとは?

Spring Bootは以前からあるSpringフレームワークをポータブルに実行できる環境のようで、フレームワークというとちょっと違うっぽいです。しかし、組み込みAPサーバとしてTomcatを使い、jarを実行するだけでWebアプリケーションが立ち上がるので、非常にお手軽(らしい)。

warを作ってAPサーバにデプロイするのは最近は流行ってないようです。そういえばPlay frameworkのそういう感じらしいというのは見た事あります。

まずは導入

Spring Bootのページにありますが、Groovyで作られたCLIツールがあるようです。
gvm経由でインストールできるものがあったので、それで入れました。gvmのインストールがまだの人はgvmをインストールしてください。
ちなみに私の環境はMacなので、Mac以外の環境のことはわかりません。

GVM – the Groovy enVironment Manager

gvmから、Spring BootのCLIをインストールします。

gvm install springboot

プロジェクトを作成

IntelliJ IDEAでgradleプロジェクトを作り、build.gradleのdependenciesブロックに以下を記述しました。あと一応sourceSetsも記述。

apply plugin: 'java'

sourceCompatibility = 1.8
version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE")
    testCompile group: 'junit', name: 'junit', version: '4.11'

}
// 2015-02-24 修正。
sourceSets {
    main {
        java
    }
    test {
        java
    }
}

その後、src/main/java/sample/HelloController.javaを作成。

package sample;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@Controller
@EnableAutoConfiguration
public class HelloController {

    @RequestMapping("/")
    @ResponseBody
    String home() {
        return "Hello World!";
    }

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

}

IntelliJ上からHelloControllerを実行。http://localhost:8080にアクセスしたらHello World!が出たのでとりあえず動くところまではできました。今後はいろんなサンプルが豊富にあるらしいので、とりあえずそれを写経したりしながら、勉強していこうと思います。

練習用に作ったgithubのリポジトリを公開しておきます。
github: patorash/spring_boot_practice


gradleで依存関係の更新を行う

JVM合同勉強会に向けて、wasabiを触っていたのですが、不具合があったので前にプルリクエストを送っていました。それが取り込まれたようだったので、再び触ってみようとしていたのですが、wasabi-0.1-SNAPSHOTが更新されない…!普段はRuby, RailsばっかりやっているのでJVM関係のお作法はさっぱりです!gradleわからない!

とりあえずググったら、–refresh-dependenciesというオプションがあるようでした。

gradle build --refresh-dependencies

これで、とりあえず最新のSNAPSHOTに更新されて、私のプルリクが取り込まれたバージョンに変わっていました。ふー、JVM関連は勉強の仕方がわかりにくい…。場当たり的になってしまう。まぁ私のやり方が悪いんでしょうが。


太陽光発電の減価償却費について聞いてきた

これは自分用のメモですが、多くの人が疑問に思っているかもしれないので、確定申告コーナーで聞いてきたものをここに公開しておきます。

昨年11月に我が家が完成し、屋根の上にある太陽光発電の売電も開始となりました。
そして現在は2月中旬。確定申告の締め切りまで残り1ヶ月を切り、慌てている人もいるかと思います。
住宅ローン減税の手続きもありますので、昨年家を建てた人で、確定申告がよくわからない人は、なるべく早く行ったほうがいいでしょう。今日(2015/2/17)の時点でも200人待ちくらいになったので1時間以上待ちました。締め切りギリギリになると、もっと多くの人で行列ができてしまうでしょう…。

住宅ローン減税の手続き自体は、書類を持っていったら職員さんがテキパキと記入してくださった上で説明してくださったので、書類を揃えて突撃するのが楽だと思います。

その後、太陽光発電の減価償却について聞いてきました。
太陽光パネルも家の一部なので、売電収入は雑所得で、太陽光発電設備は住宅ローン減税側で減税されて終わりかなと思っていたのですが、一応ハウスメーカーに聞いてみたところ、減価償却できるのでしてくださいと言われました。ちなみに、家の屋根等につけている場合は、余剰買取だろうと全量買取であろうと雑所得として計上すると国税庁のサイトに書いてあります。

リンク: 自宅に設置した太陽光発電設備による余剰電力の売却収入

完全に事業としてやっている人は、事業所得になるので注意です。

自宅の太陽光発電設備は減価償却の対象

太陽光発電設備の減価償却期間は、17年と法律で決まっていて、100%償却できます。
1年に償却できる金額は、 100% / 17 = 約5.9% となります。
端数が出た場合は最後の年に100%になるように調整するらしいです。

1年分丸々償却できる場合

例えば、2014年1月に設置した場合ですと、2014年分を丸々償却できます。
なので、契約が全量買取で、太陽光発電設備が300万円だったとした場合、

300万円 * 0.059 = 177,000

が減価償却費となります。

年の途中から売電がスタートした場合

私のように、11月に完成した場合だと、11月と12月の2ヶ月分のみが、減価償却の対象となるので、

300万円 * 0.059 * 2 / 12 = 29,500

となります。

しかし、減価償却費はあくまでも収入から引ける経費という扱いなので、収入のほうが減価償却費よりも少なかったとしても、雑所得が0円になるだけで、他の所得から余った減価償却費分を引くということはできません。まぁそういうことは滅多にないとは思いますが…。

売電収入の確定タイミング問題について

私が聞きたかったはこれで、減価償却分は11月、12月の2ヶ月分。
しかし、購入電力量のお知らせの検針があったのは平成26年12月分(11月に発電した分と12月頭の数日分)で、平成27年年1月に検針した分(12月に発電した分と1月数日間発電した分)は表記上平成27年1月になってるけれども、これを2014年の雑所得の対象にしてもいいのか?というものでした。

税務署の方によると、末日であることがもちろん望ましいのだけれど、そういうわけにもいかないパターンもあるので、厳密でなくてもOKとのこと。もし税務署のほうから、「この雑所得ってどういう数値ですか?」と質問されたときに答えることができればOKだそうです。ですので、平成27年1月と書いてあるものであっても、26年の雑所得として計上してOK!ただし、翌年からもずっと「2月〜翌年1月」の12ヶ月分の資料をもとに計算して一貫性をもつこと!ということでした。(来年にど忘れして平成27年1月〜12月分とかで雑所得を計上しないように注意…)

太陽光発電設備の減価償却費についてどこに記入するか問題

これについても聞いてみました。事業所得であれば、収支計算書のほうに減価償却費の計算を行うところがあります。しかし、自宅で発電している人にとっては雑所得のため、記入するところがありません。これは記入しなくてもいいのでしょうか?と。結論からいうと、記入しなくても大丈夫です。雑所得には、以下の計算結果を記入します。

雑所得 = 売電収入 – 太陽光発電設備の減価償却費

しかし、どのくらい減価償却しているかが明確にわかるようにしておいてくださいとのことでした。

まとめ

  1. 自宅の太陽光発電の売電収入は、余剰買取・全量買取のどちらも雑所得
  2. 太陽光発電設備は減価償却できる。耐用年数17年。1年に償却できる金額は(設備の金額 * 0.059)
  3. 減価償却は導入開始した月の分から計算する(11月に導入なら2ヶ月分)
  4. 説明ができれば、2015年1月頭の検針分を2014年の所得としてもよいが、一貫性を持つこと
  5. 事業ではないので、減価償却費の記入は不要。計算結果だけを記述。でも説明できるように計算結果は資料として残しておくとよい

sucker_punchを使ってもHerokuの30秒超えはできない

まぁそうだろうとは思っていたのですが、とりあえず試してみたので書いときます。

sucker_punchとは?

sucker_punchとは非同期処理用のライブラリ(gem)で、特別なものを必要とせずに動作してくれます。メール送信程度の処理を非同期でやりたいということならば、sucker_punchで十分だと思います。

なんで使おうと思ったか

結論から書くと経費の節約のためです。私が開発しているサービスはHerokuで運用しているのですが、Herokuで非同期処理を行おうと思ったら、worker dynoを立ち上げなければなりません。worker dynoは1つでも月々$34.5するので、今の価格だと約4,140円します。これは痛い。なので、worker dynoを使わずに重たい処理をする方法はないか?と調べていたところ、sucker_punchの存在を知ったのです。

使い方(Rails4.2)

Rails4.2を使っているので、ActiveJobのqueue_adapterとしてsucker_punchを使ってみました。

まずはsucker_punchをGemfileに追加。

gem 'sucker_punch'

そしてインストール

bundle install

そして、設定のinitializersでsucker_punchをqueue_adapterに指定。

Rails.application.configure do
  config.active_job.queue_adapter = :sucker_punch
end

ジョブの作成を行います。

rails g job foo

これでJobが作成されます。

class FooJob < ActiveJob::Base
  queue_as :default

  def perform(*args)
    # Do something later
  end
end

ジョブの非同期実行は以下のようにします。コントローラーなどから呼び出します。

FooJob.perform_later()

重たい処理をHeroku上でsucker_punch経由で実行してみた

結論から言うと、Herokuの30秒ルールで強制終了して終わりました。そりゃそうだよねー(涙目)
30秒以内に収まる処理の場合は普通に実行できたので、サービス的にバックグラウンド処理が大したことない場合は、sucker_punchで代用するというのはアリだと思います。