せてぃーずノート

Javaのイベント参加レポートとかを書いたりします。

SpringSNSのチュートリアルを試してみた

なんか変な感じに忙しい日々が続いてちょっと間隔あいちゃったけど、今日はこれを試してみた。

Getting Started · Accessing Twitter Data

試す前にTwitter側のセットアップを済ませておく必要がある。
OAuth認証も利用するので、コールバックURLの設定もしておく。

アプリケーションの動きとしては、こんな感じ。 起動してhttp://localhost:8080/にアクセスすると、Twitterへのコネクションがあるかを判定する。
最初にアクセスした時はコネクションがないので、/connect/twitterにリダイレクトする。

if (connectionRepository.findPrimaryConnection(Twitter.class) == null) {
    return "redirect:/connect/twitter";
}

この時のViewはtemplateフォルダにある"connect/{provider ID}Connect"が呼び出される。
twitterなら"connect/twitterConnect"、facebookなら"connect/facebookConnect"になる。

twitterConnect.htmlには/connect/twitterをPOSTで呼び出す処理を書く。
/connect/twitterを呼び出すと、SpringSNSはOAuth認証のページに遷移してくれる。
OAuth認証が終わると、これまた自動的に"connect/{provider ID}Connected"のページが呼び出される。
あとはhttp://localhost:8080/に再び遷移することで、TwitterAPIを利用できるようになる。

気になる点としてはtwitter4Jとの使い分け。
APIの使い勝手とかconsumer keyなどの指定は個人的な好みの部分もあるので、好きな方を使えばいいとは思う。
使ってみた感想としては、OAuth認証がSpringSNSの方が楽なのと、様々なSNSを利用する場合にAPIごとに使い方を覚える必要がないのがいいと思う。

Springのチュートリアル〜第1回 SpringMVCその1

今日はServing Web Content with Spring MVCを動かしてみます。

ダウンロードは↓から。

Getting Started · Serving Web Content with Spring MVC

作るコードもリンク先にあるので、ここには書いたりしません。

ソースの作成

このチュートリアルは3つのクラスを作ります。
コピペすれば一瞬ですが、量も大したことないので全部打ち込んで試してみることをおすすめします。

  • 実行するmainメソッドを持つクラス
  • Controllerクラス
  • ビューであるテンプレートファイル(html)

まずはControllerクラスです。
@Controllerアノテーションを付ける。
URLとの紐付けは@RequestMapping("/greeting")で行う。
Spring3.2とあまり違いはなさそう。

ビューとなる部分は、JSPじゃなくてThymeleafというテンプレートエンジンを使います。
ネームスペースに

<html xmlns:th="http://www.thymeleaf.org">

と書いて、置換する部分は

<p th:text="'Hello, ' + ${name} + '!'" />

と書くだけでOKです。

実行

実行する方法は2つあります。

  • WARを作って配備する
  • mainメソッドを呼び出す

今回の推奨は当然後者です。 mainメソッドを呼び出すとこんなロゴが出てSpringBootが起動します。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::             (v0.5.0.M6)

起動が完了するとhttp://localhost:8080/greeting/にアクセスして作成したアプリケーションが呼び出されます。
動いているのはSpringBootに内蔵されたTomcatです。
http://localhost:8080/にアクセスすれば、Tomcatの404画面が出てきます。

Executable Jarの作成

build.gradleを修正することで、実行可能なJarファイルを作れます。
java -jarで実行すると、mainメソッドを実行した時と同じようにTomcatが起動します。
Jarファイルの大きさは10MB程度。
TomcatやSpringのlibraryがぎっしり入っています。

Manifestファイルはこんなかんじです。

Manifest-Version: 1.0
Start-Class: hello.Application
Spring-Boot-Version: 1.0.0.RC1
Main-Class: org.springframework.boot.loader.JarLauncher

JarLauncherクラスについては別の機会に見ていこうと思います。

制約?

mainメソッドを持つApplicationクラスは@ComponentScanアノテーションが付加されています。
このアノテーションが付いている場合、Springは同一パッケージを検索してコンポーネントを探し出します
今回作成したControllerクラスとApplicationクラスのパッケージを変えてみると、Tomcatは起動しますがコンポーネントはパッケージが違うのでロードされません。
なので、http://localhost:8080/greeting/にアクセスしても404になります。

Applicationクラスで違うパッケージのControllerを指定できるといいのになぁ。

出来ました。
@ComponentScanにパッケージを指定できます。

@ComponentScan(basePackages="hello.component")

クラスのフィルターなどもできるので、起動が遅い場合は指定してみるとかできますね。

まとめ

SpringBootを使うことで、面倒な環境設定をせずにWebアプリケーションを作成することができます。
NetBeansGlassfishに比べれば学習にかかるコストは小さいと思います。

ただ「本番はWebLogicを使う開発」みたいなものにはあまり利点を生かせないかも。
アプリケーションサーバを使用する開発はJava EE、Herokuなどクラウド環境で動かす場合はSpringというように、住み分けができると面白いかも。

Springのチュートリアルをやっていくよ!〜第0回事前準備

JJUGナイトセミナーで「チュートリアルが豊富なので試してみてね」ということなので一つ一つ試していこうと思います。
とりあえず今日は環境設定。

インストールするもの

基本的な流れ

「サンプルダウンロード→eclipseに取り込み→コード追加→実行」の繰り返しです。

サンプルは空のJavaファイルが入っています。
空のファイルに対して解説のページのコードを埋め込んでいけば、動くものが完成するわけです。
編集するのはeclipseでやりたいのですが、そのままだとインポートできません。
そこで、gradleでeclipseプロジェクトに変換してインポートします。

具体的には

  1. ダウンロードしたzipファイルを解凍する
  2. 解凍してできたinitialディレクトリに移動

    cd /Users/sety/Downloads/gs-serving-web-content-master/initial

  3. gradle eclipseコマンドを実行

うまくいけば.classpathやら.projectといったeclipseがプロジェクトとして認識するためのファイルが出来上がります。
あとはeclipse上からプロジェクトをインポートすればチュートリアルを実行する準備は完了です。

JJUG ナイトセミナ 「Spring Framework 特集」のまとめ

色々とサイトが出てきたのでリンク集。

Springプロジェクト

Spring

スライド

再入門!RESTとSpringMVC

Spring4とSpring Bootで作る次世代Springアプリケーション #jjug #jsug

デモ

http://spring-boot-demo.herokuapp.com/

Twelve-Factor App

The Twelve-Factor App(日本語訳)

SaaSを提供するときの方法論。

Java 7 Update 51でJavaDBが起動しなくなった場合の対応

Java SEをアップデートすると以下の例外が出てJavaDBが起動しなくなる。

java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")

これを何とかするためには、java.policyを修正をする必要がある。

Macの場合、以下の場所にある。
編集前に必ずバックアップしておく。

/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/security/java.policy

Windowsの場合はC:¥Program Files¥Javaにインストールされてるはず。

java.policyに対して、以下の定義を追加します。

grant codeBase "file:/Applications/NetBeans/glassfish-4.0/javadb/lib/*" {
    permission java.net.SocketPermission "localhost:1527", "listen,resolve";
};

自分の場合はNetBeansからGlassFishを起動する場合でしか使用しないため、NetBeansの下にあるlibを指定しています。
Java SE付属のJavaDBを使用する場合は、file://の後を変更すること。

元ネタはstackoverflow先生です。

http://stackoverflow.com/questions/21154400/unable-to-start-derby-database-from-netbeans-7-4

チェック例外はコンパイルをすり抜ければOK

チェック例外でもコンパイルさえ誤魔化せばなんとでもなる。
その証明をしてみます。

こんなメソッドがあって

public class Employee {   
    public String getMessage(){
        throw new RuntimeException();
    }
}

こんな呼び出しメソッド(別クラス)があります。

public class EmpMain {
    public static void main(String[] args) {
        Employee employee = new Employee();
        employee.getMessage();
    }
}

コンパイルエラーは当然ありません。
実行したら正常に終了します。

ここで、最初のEmployeeクラスを以下のように修正します。

public class Employee {   
    public String getMessage() throws Exception {
        throw new Exception();
    }
}

当然、呼び出し側のメソッドはコンパイルエラーになります。
でもEmployeeクラス自体はコンパイル可能です。
じゃあ新しいEmployeeクラスを古いバイトコードから呼び出したらどうなるか。

> java EmpMain
Exception in thread "main" java.lang.Exception
    at byteread.Employee.getMessage(Employee.java:9)
    at byteread.EmpMain.main(EmpMain.java:8)

正常に実行できました。
ソースではコンパイルエラーになりますが、バイトコードでは問題がないことがわかりますね。

ちなみに逆のパターンだとどうでしょう。
employee.getMessage();がIOExceptionをスローしてくるのであれば、コンパイルは正常に終了します。

public class EmpMain {
    public static void main(String[] args) {
        Employee employee = new Employee();
        try {
            employee.getMessage();
            System.out.println("正常終了");
        } catch (IOException e) {
            System.out.println("IOEcxeption発生!");
        }
    }
}

しかし、Employeeクラスが修正され、getMessageメソッドがスローしなくなります。 そうするとソースコードはコンパイルエラーですが、バイトコードだけなら正常に実行できます。

ソースコード互換≠バイトコード互換ということです。

Lombokの生成したバイトコードを見てみる

2013年にブレークしたLombok。 詳しくは

http://d.hatena.ne.jp/nowokay/20130730

を参照で。
まずはgetter/setter。

import lombok.Data;

@Data
public class Employee {

    private String empCd;

    private String name;

    private int age;

}

上のようなソースから生成されたバイトコード

public void setEmpCd(java.lang.String empCd);
0  aload_0 [this]
1  aload_1 [empCd]
2  putfield byteread.Employee.empCd : java.lang.String [13]
5  return

のようにsetterがきちんと生成されてる。
すばらし~。
下手に人間が書くよりミスが少なくていいと思います。

あとはチェック例外でもスローできちゃうSneakyThrows。
発生することがない上に、キャッチしてもあまり意味が無いチェック例外を綺麗に無視できるのでとても便利です。

@SneakyThrows
public String getMessage(){
    throw new Exception();
}

このソースのバイトコードはこんな感じ。
例外のインスタンスを生成し、スローしているだけの処理に見えます。

 public java.lang.String getMessage();
 0  new java.lang.Exception [13]
 3  dup
 4  invokespecial java.lang.Exception() [15]
 7  athrow
 8  astore_1 [$ex]
 9  aload_1 [$ex]
10  athrow

比較のために以下のソースのバイトコードも並べてみます。

public String getMessage(){
    throw new RuntimeException();
}

バイトコードは例外のクラス名が違う以外はほぼ同じでした。

public java.lang.String getMessage();
0  new java.lang.RuntimeException [13]
3  dup
4  invokespecial java.lang.RuntimeException() [15]
7  athrow

これを見るとチェック例外もランタイム例外も実行においては関係ないっていうことです。たぶん。
要はコンパイラのチェックさえ通してしまえばいいんです。