2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 |
2013-05-03
■[ソフトウェア技術][Java]続・JavaでさくさくWebアプリ開発
たぶん前回のエントリ見た人の半分は気がついてると思うけどクラスパスとかいろいろとスキャンしたりするようなApplicationを継承したクラスはいくつも用意されている。
探し方
Application app = new
と入力した状態でCTRL+SPACEを押すとApplicationを継承したクラスがいくつも出てくるのでそれであたりをつける。
単純な置き換え系
HogeApplication app = new HogeApplication(Hoge.class);
を
ClassNamesResourceConfig app = new ClassNamesResourceConfig(Hoge.class);
にかえてもよい。こちらはClassを引数に取るほかにもクラスの名前を文字列で渡したりすることもできる。
いちいち自分で作ることもないのだ。
クラスパスから検索
ClasspathResourceConfig app = new ClasspathResourceConfig();
ただし、なにもしぼらないとクラスパスすべて見に行くため起動に時間がかかるようになる。
ライブラリが増えれば増えるほど遅くなる。
実測でこれ以外はすべて650msくらいで起動するが、これだけはなんと1.1秒に!全然さくさくじゃない!
パッケージ指定
たぶんこれが一番使いやすい。
PackagesResourceConfig app = new PackagesResourceConfig("");
からの文字列でも十分高速で速度は全然変わらなかった。
これによってサーバーの起動時間はかわらない。
パッケージは省略できるけど、ファイルが増えてきたらできるだけ絞ったほうがいいのかもね。起動が1秒を超えるかもしれないし。
というわけで、1つだけ1秒切ることはなかったけど、忍耐力が高い人ならたぶん大丈夫。
2013-04-29
■[ソフトウェア技術][Java]JavaでさくさくWebアプリ開発
かなり久々の技術エントリ。
運用はお堅い重いサーバーを使ったとしても開発は軽いほうがいい。当たり前ですね。
というわけでさくさく開発する方法を書いてみる。DIコンテナはCDIやGuice、Springなど好きなものでよいが、今回は省く。軽いこともあって開発中はGuiceを使うことをお勧めしたい。注入は@Injectを使うため、開発中と運用中でコードが変わるってのは少ないはずだ。
まずはJAX-RS
まず、アクションベースのWebアプリはJAX-RSを使うこと。これが基本。サーブレットAPIを使わずに開発することについては今までも書いてきた。サーブレットAPIを触らないことにより開発効率とテストのしやすさを両立できる。
こんな感じ。
@Path("/") public class Hoge { @GET @Path("add/{a}/{b}") public Response add(@PathParam("a")int a, @PathParam("b")int b){ String text = a + "+" + b + "=" + (a+b); return Response.ok(text , "text/plain").build(); } }
okはわざわざこんなことやらなくてもいいけど、JavaやJAX-RSよくわからん人でもなんとなく動きはわかるようにしてみた。これがJAX-RS。
書き方は結構自由なので、同じ動きをいろんなかきかたができる。いろんなかきかたができるといってもわかりにくいということではなく、柔軟にstatusコードとかmimeとか数値や文字列だったり定数クラスだったり指定することができる。
return Response.ok(entity , "text/plain").build();
return Response.ok().entity(text).type("text/plain").build();
return Response.ok(text).type("text/plain").build();
return Response.status(200).entity(text).type("text/plain").build();
return Response.status(Response.Status.OK).entity(text).type(MediaType.TEXT_PLAIN_TYPE).build();
もちろんOK以外もいくつかメソッドで用意されている。こんな感じ。
return Response.seeOther(new URI("http://example.com")).build();
return Response.serverError().entity("ごめんちゃい").build();
すでに枯れた標準APIなのでJava使いなら大抵誰でも知ってるはず。もうすぐ次のバージョンが出るけど、互換性があって基本部分に変更はないので大丈夫。あくまでもさらに便利になるフィルタやクライアント(今までは実装依存だった)の標準化をしたに過ぎない。
POJOなのでこういうテストを書いてもいい。
@Test
public void testAdd() {
System.out.println("add");
int a = 12;
int b = 3;
Hoge instance = new Hoge();
Response result = instance.add(a, b);
assertEquals(200, result.getStatus());
assertEquals("12+3=15", result.getEntity().toString());
}
そのほか実際にスタンドアロンサーバーで通信するテストを書いてもいい。サーブレットコンテナはいらないのでJavaSEで開発ができる。さくさくである。この場合テンプレートにJSPは利用できないので他のテンプレートエンジンを利用することになる。基本クライアントサイドで組み立てたほうがいいと思うけどね。サーバーとはデータのみやり取りするように。
jax-rsのライブラリはRIのjerseyから落としてくるとよい。
https://jersey.java.net/nonav/documentation/latest/chapter_deps.html
このあたりを。
それでもサーブレットコンテナがほしい
それでも特定のサーブレットやJSPを利用したいこともあるかもしれない。自分のアプリの都合ではなく、ライブラリなどの都合でフィルターが使いたいとかで。完全新規ならフィルターはJerseyのフィルタを使えばいいがそうではない場合もあるだろう。そうなるとTomcatなどが必要になってきて開発はどんどん重くなる。
軽いコンテナは?と聞いたらすぐに帰ってくるのがJetty。
そう、Jettyのembeddedを利用する。
jetty-all-[version].jarというのをクラスパスに追加する。servlet-api-3.0.jarもいれておく。
jetty-allはこのへんから。
http://mvnrepository.com/artifact/org.eclipse.jetty.aggregate
servlet-api-3.0.jarはjetty-distribution-[version].zipとかをjettyの公式サイトのトップから落としてそこから拾うとよい。
public class ServerMain { public static void main(String[] args) throws Exception { //サーバー起動 Server server = new Server(8080); server.start(); } }
これで起動する。サーバーが起動しているかどうかブラウザで404がかえるのを確認する。
JerseyServletを設定する
リソースを列挙するクラスを用意。コンストラクタで列挙できるようにしてある。
public class HogeApplication extends Application{ final Set<Class<?>> classes = new HashSet<>(); public HogeApplication(Class<?>... classArray) { classes.addAll(Arrays.asList(classArray)); } @Override public Set<Class<?>> getClasses() { return classes; } }
クラスパスとかをスキャンしたりして自動登録してもいい。
public static void main(String[] args) throws Exception {
ServletContextHandler ctx = new ServletContextHandler();
ctx.setContextPath("/test");
//Jersey設定
//リソースクラスの一覧を列挙
HogeApplication app = new HogeApplication(Hoge.class);
ServletContainer sc = new ServletContainer(app);
ctx.addServlet(new ServletHolder(sc), "/res/*");
//サーバー起動
Server server = new Server(8080);
server.setHandler(ctx);
server.start();
}
これで以下のURLで動くようになった。
http://localhost:8080/test/res/add/12/3
でもこれではスタンドアロンサーバーの状態のままに近い。一応サーブレットとして動いているので好きなようにフィルタ付けたりいろいろとできることはできるけど、JSPとかは動かない。
JSPとか動かす
ライブラリが足りないのでJSPを動かすのに必要なライブラリをクラスパスに通す。
jetty-distribution-[version]からlib/jsp以下のjarをもってくる。
mainクラスは以下のように修正。
public static void main(String[] args) throws Exception {
ServletContextHandler ctx = new ServletContextHandler(ServletContextHandler.SESSIONS);
ctx.setClassLoader(Thread.currentThread().getContextClassLoader());
ctx.setSessionHandler(new SessionHandler());
ctx.setContextPath("/test");
//Jersey設定
//リソースクラスの一覧を列挙
HogeApplication app = new HogeApplication(Hoge.class);
ServletContainer sc = new ServletContainer(app);
ctx.addServlet(new ServletHolder(sc), "/res/*");
//JSP設定
ctx.setResourceBase("webapp");
ctx.addServlet(DefaultServlet.class, "/");
ServletHolder jsp = ctx.addServlet(JspServlet.class, "*.jsp");
jsp.setInitParameter("classpath", ctx.getClassPath());
//サーバー起動
Server server = new Server(8080);
server.setHandler(ctx);
server.start();
これで準備完了。
カレントディレクトリにwebappというディレクトリを作ってJSPを置いて動作確認しよう。
一瞬でサーバーが起動して動作が確認できるだろう。
JSPが動くということはViewableが動くということ。ViewableはJSPへフォワードしてくれる仕組み。
先ほどのリソースクラスに追加してみる。
@Path("/") public class Hoge { @GET @Path("add/{a}/{b}") public Response add(@PathParam("a")int a, @PathParam("b")int b){ String text = a + "+" + b + "=" + (a+b); return Response.ok(text , "text/plain").build(); } //--------------------------------------------------------------- //ここから下が追加分 @GET public Viewable get(@QueryParam("a")int a, @QueryParam("b")int b ){ HashMap<String, Object> params = new HashMap<>(); params.put("a", a); params.put("b", b); params.put("c", a + b); return new Viewable("/hoge.jsp", params); } }
JSPはitという名前でアクセスすることができる。たとえばこんな感じ。
<%@page pageEncoding="UTF-8" contentType="text/plain" %> ${it.a} + ${it.b} = ${it.c}
http://localhost:8080/test/res/?a=12&b=3
続きかいた
2012-04-25
■[NetBeans][ソフトウェア][Java]NetBeans 7.2の新機能 TestNGと履歴の強化
NetBeans 7.1までは「JUnit」というカテゴリが存在していたが、それが「Unit Tests」という項目になっている。つまり、単体テストはJUnitだけではないということだ。具体的にはTestNGが追加された。
もちろん、頻繁に使うこちらのダイアログ(CTRL+SHIFT+U)でも選択肢が追加されていた。
ただ、TestNGの動作はまだ完成していないようでうまく動かなかった。ライブラリ等は設定されてはいたが。
今後他のテストフレームワークが追加されるのかもしれない。
続いて履歴。
以前紹介したのはローカル履歴だけだったが、バージョン管理システムを有効にしている場合はこうなる。今回はMercurialで。
つまり、ローカルだろうが、どっかのリポジトリだろうが関係なく横断的に検索ということが可能になる。もちろん、フィルタでどっちかだけとか絞ることも可能ではあるが、これはなかなか面白い。
・・・だけど、今のところMercurialの比較動作にバグがある模様。デフォルトキャラクタセットを利用しようとする。デフォルトのキャラクタセットを使ってよいか?とわざわざダイアログで表示しているのに、キャンセルをすると表示すらされない。
このバグは6.x系に長く存在していた。今回もエンバグしたようだ。マルチバイト系のバグは放置される癖があるので直らないかもしれない。
2012-04-24
■[Java][NetBeans]NetBeans 7.2の強化されたJPAサポート
NetBeans 7.2紹介シリーズ第3弾。
NetBeansはもともと古くからJPAをいち早くサポートしていたがさらに強化された。まぁ今回紹介するのは微妙なところだけど。
名前付クエリで補間がきくようになった。
構文がおかしいと知らせてくれる。
これはベタ書きした場合でも有効。ただし、いったん変数に入れたりすると有効ではないのであんまり意味がないけど。作成後利ファクタする、って感じがいいのかな。
名前付クエリ名の補間とそのJPQL表示が見ることが出来るってのが一番いいところなのかな。これも別の変数に入れるとダメだけど。
JPAはRDBを利用する場合、いまやJavaでもっともスタンダードなO/Rマッパだ。
他の代替肢はなくなったというくらい駆逐され、圧倒的なシェアをもつ。実装としてHibernate(EntityManager)を利用することは多いとは思うが、基本的にJPAで行える範囲内はJPAで実装、足りない部分を実装固有のものを利用するというのが一般的だ。最初からHibernateのAPIというのもだいぶなくなったと思う。
というわけで、JPAをどんどん使おう。DIコンテナやWebフレームワークと違い圧倒的な一強で、新しく出来たライブラリ等でも違う点を説明する際にもJPAと比較、拡張しているのがほとんどのため一般教養に等しい存在になっている。どのDIコンテナ、どのWebフレームワークを利用してもDBアクセスはみんなJPAなのだ。現代のJDBCといってよい。
2012-04-21
■[NetBeans][Java]NetBeans 7.2ではじめるAmazonのクラウド
NetBeans 7.2の新機能紹介シリーズ。
おや、サービスウインドウに見慣れないものがあるぞ。
クラウドの選択・・・だと?
AWSの接続情報を入力する。
追加された。
次にプロジェクトの新規作成で、Webプロジェクトを作る。
その際にTomcatやGlassfishなど選択できるが、そこでサーバーの新規追加を選ぶと…やつ(Beanstalk)が選択できる。
コンテナタイプを選択できる。PHPも選べるが、PHPプロジェクトも対応しているかはわからない。テンプレートという項目もあるが選べない模様。
追加された。
AWSの管理ツールを開くとこの時点でデプロイされているのがわかる。
リンクをクリックすると確かにデフォルトで起動していた。
こういうwarファイルらしい。
で、F6を押してプロジェクトの実行。F6をオスとメインプロジェクトのコンパイル、warアーカイブ、デプロイ、ブラウザ起動と順に実行される。そして表示された。これはNetBeansのWebプロジェクトの新規作成をスルト標準ではいっているJSPファイルだ。
バージョン管理されているのがわかる。このwarファイルはS3に作られる。
と、このようにTomcatやGlassfishなどと同じようにAWSのクラウド(Beanstalk)にデプロイできる。
ただ、現状基本的な動きは問題はないものの、細かいところでバグはあるようで、コンボボックスの選択がおかしかったり、追加したサーバーの情報が消せなかったりする。現時点でここまで動いているので、リリースまでは問題なく実装されそうだ。
Beanstalkで起動されるインスタンスはマイクロインスタンス。マイクロでも500MBはメモリ確保できると思うのであんまり問題にはならないとは思うが、変えたいときはAWSの管理コンソール画面で修正するのがいいのだろう。
BanstalkのJava版はLinux + JavaSE 6 + Tomcat 6/7で実装されているため、Javaのコードを書いてwarをアップロードするだけで、バージョン管理されてサーバーが完成する。好きなバージョンに戻すことも可能だ。ロードバランサも設定され、デフォルトでは1インスタンス、負荷が増えるとインスタンス数が自動で増えて最大4つまで生成されるようになっている。つまり、サーバーの管理はしたくない、アプリだけ作ってあとは全部おまかせができるということだ。
GoogleのクラウドであるAppEngine/Javaとの違いは普通のWebアプリがデプロイできるというところだ。GAEはJavaSEのかなりの部分が実行できないようになっているため、Javaの一般的なWebアプリで利用する既存のライブラリ等がほとんど動かないと思ってよい。
そのため、何もしなくてもそのまま動く、AWSのBeanstalkはクラウド入門によい。そしてNetBeans 7.2はそのためのアクセスを標準で用意した。JavaEE 7ではクラウドがキーワードとなっているため、今後こういった方向は大事になっていくのだろう。今後に期待である。























