[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
SlideShare a Scribd company logo
エンタープライズJava開発はこれからが面白い!10年の歳月を経て、JavaEEプラットフォームは実践的な開発プラットフォームへと進化した2011/8/10浅井 良
自己紹介名前 浅井 良現職 株式会社オージス総研 アドバンストモデリングソリューション部アーキテクトチーム所属去年から達人プログラマーを目指してのブログを書いています。http://d.hatena.ne.jp/ryoasai/TwitterIDryoasai74Googleアカウント ryoasai74
そうです、ワタシがJavaEEおじさんです。
本日のアジェンダJavaEEの進化の歴史の振り返り(15分)JavaEE6アプリケーション開発で必要な主要開発技術の紹介(25分)JSF2.0EJB3.1JPA2.0CDI今後のエンタープライズJavaEE開発(10分)一般的なSIの開発案件で使えそうな組み合わせ
JavaEEの進化の歴史を振り返る
エンタープライズアプリケーションの形態の変化ホストコンピューター+ダム端末(80年代)C/S構成のシステム(90年代~)Webアプリケーション(90年代後半~)Web2.0、SaaS、クラウド(2000年代~)80年代90年代現在
エンタープライズシステムの特徴複雑
コンポーネントがあれば幸せになれる!?
J2EEの当初の目標は分散コンポーネント開発基盤の標準化ミドルウェアに対する標準API関係データベースへのアクセス(JDBC)ネーミング・ディレクトリサービスへのアクセス(JNDI)分散トランザクション(JTA、JTS)通信基盤(RMI/IIOP、Webサービス、JMS)標準プログラミングモデルJSP・サーブレットEJB
J2EEの複雑なプログラミングモデル分散コンポーネントモデル各機能単位にモジュールが別々のプロセスに分散現在のSOAの考え方と似ている状態を持ったオブジェクトがプロセスをまたいでメッセージをやり取りするオブジェクトの位置等価性重たい面倒高コスト
初期のEJBでHelloWorldを作ると①リモートコンポーネントインターフェースを定義する決まった親インターフェースを継承public interface Hello extends EJBObject {  String sayHello(String name) throws RemoteException; }全メソッドでRemoteException送出を宣言
②ホームインターフェースを定義する決まった親インターフェースを継承public interface HelloHome extends EJBHome { Hello create()     throws CreateException, RemoteException; }業務と無関係な例外送出を宣言
③EJB実装クラスを定義する実装するのはHelloではない!public class HelloBean implements SessionBean { private SessionContext context;public void setSessionContext(SessionContextaContext) {        context = aContext;}public void ejbActivate() {}public void ejbPassivate() {}public void ejbRemove() {}  public void ejbCreate() {}public String sayHello(String name) {return “こんにちは " + name;}}業務的に意味のあるのはこの部分だけ
④XMLデプロイメント記述子を作成する<?xml version="1.0" encoding="UTF-8"?><ejb-jar version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">    <display-name>EJB2App-ejb</display-name>    <enterprise-beans>        <session>            <display-name>HelloBeanSB</display-name>            <ejb-name>HelloBean</ejb-name>            <home>hello.ejb.HelloHome</home>            <remote>hello.ejb.Hello</remote>            <ejb-class>hello.ejb.HelloBean</ejb-class>            <session-type>Stateless</session-type>            <transaction-type>Container</transaction-type>         </session>    </enterprise-beans>    …</ejb-jar>
呼び出し側も大変だった①JNDIからホームオブジェクトをルックアップpublic static HelloHomelookupHelloHome() {Context context = null;  try {    context = new InitialContext();return (HelloHome) PortableRemoteObject.narrow(context.lookup("java:global/EJB2App/EJB2App-ejb/HelloBean!hello.ejb.HelloHome"), HelloHome.class);  } catch (NamingException ex) {    throw new RuntimeException(ex);  } finally {    if (context != null) {      try {context.close();      } catch (NamingException ex) {        throw new RuntimeException(ex);      }    }  }}
②ホームオブジェクトからEJBオブジェクトを作成して呼び出すHello hello = null;try {  hello = helloHome.create(); return hello.sayHello(name); } catch (CreateException ex) {  throw new RuntimeException(ex);} catch (RemoteException ex) {  throw new RuntimeException(ex);} finally {  if (hello != null) {    try {hello.remove();    } catch (RemoteException ex) {      throw new RuntimeException(ex);    } catch (RemoveException ex) {      throw new RuntimeException(ex);    }  }}業務的に意味のあるのはこの行だけ
重量Javaのせいで多くのプロジェクトが失敗した
J2EE関連のデザインパターンの登場プロジェクトの失敗は仕様自体の問題ではなく、アプリケーションの設計が不十分なため?パターンによりJ2EE開発のベストプラクティスを学ぼうという雰囲気があった。18EJBデザインパターンFloyd Marinescu (著) J2EEパターン 第2版Deepak Alur (監修), John Crupi (著), Dan Malks (著)
軽量Javaフレームワークへのパラダイムシフト(2003年~)Springを作ったRodJohnsonの「ハゲ本」開発生産性で不満のたまった優秀な開発者の間から、J2EE仕様自体の問題点が公に議論されるようになった。POJOEoD軽量Javaexpert one-on-oneJ2EE Developmentwithout EJBRod Johnson(著)
JavaEE5標準に対する軽量Javaの考え方の導入2006年にようやく登場のJavaEE5標準では開発簡易化(EoD)が重視されたEJBをPOJOとして開発一部にDI・AOPの考え方を導入アノテーションの利用によるxmlファイルの削減
EJB3でHelloWorldを作ると①ビジネスインターフェースを定義する@Remotepublic interface Hello {   String sayHello(String name) ; }
②ビジネスインターフェースの実装クラスを定義するアノテーションだけでEJBとして登録される。XMLファイルの設定は不要。普通にビジネスインターフェースを実装@Statelesspublic class HelloBean implements Hello {   public String sayHello(String name) {    return “こんにちは " + name;  }}
③インジェクションして普通に呼び出す@EJBprivate Hello hello; public void someMethod() {...    String message = hello.sayHello("Test");...}アノテーションを使ってインジェクションする。普通にメソッドを呼び出す。
見かけは簡単になったけどEE5対応のAPサーバは以前よりさらに巨大で重たくなった気がする動作確認するにはearファイルにパッケージ化する必要がある結合試験の自動化が意外に困難DIやAOPが使えるのは一部の重量コンポーネント(EJB、サーブレットなど)に限られるプレゼン層とビジネス層のコンポーネントモデルがまったく異なる肝心の互換性が少ない結局JavaEEは使えないんじゃ?
そして、JavaEE6の時代へEE5から3年半たって2009年12月に策定開発をさらに簡易化させるアイデアが多数盛り込まれているSeamやFaceletsなどEE5の弱点を補足するフレームワークのしくみを導入OSSの開発コミュニティが主導で、本当に便利で必要な機能が追加されている余分な機能の削除によるさらなる軽量化WebプロファイルPruning(使われなくなった仕様の間引き)
なによりも本当に軽量なJavaEE6サーバーが登場
でも、JavaEE6で本当にまともに開発できるの?
JavaEE6開発の主要技術の紹介
JavaEE6だけでWebアプリケーションを作るとどうなるか?JavaEE6は便利になったと言われるが、フルスタックのサンプルがなかなか見当たらない画面ビジネスロジックデータアクセス試験そこで、JsfScrumToyというJSFのサンプルをリファクタリングしてどこまで簡単にできるかPOCを実施
実際に組み合わせを検証したJavaEE6の技術Webプレゼンテーション -> JSF2.0トランザクション管理 -> EJB3.1データアクセス -> JPA2.0DI、コンポーネント管理 -> CDI試験 -> JUnit、埋め込みGlassfish
Webアプリケーションとは?WebアプリC/Sやホストのプレゼンテーションをブラウザ上で実行するもの
本質的にステートフル狭義のWebアプリJSFWebサイト一部に動的なコンテンツを含むWebサイトサーブレット・JSPWebサービス他のシステムに対してデータやロジックを提供する
基本的にステートレスJAX-WS、JAX-RS
Webフレームワークの分類アクションベースVSコンポーネントベース
主要Webフレームワークの位置づけS2StrutsStruts1設定簡易化アクションベースStruts2SAStruts会話状態サポートSpring MVCSpring WebFlowWeb MVCFWSpring FacesJSF会話状態サポートコンポーネントベースSeamTapestry設定簡易化TeedaWicketClick
アクションベースFWHTTPリクエストHTTPリクエスト解析アクション業務ロジックHTTPレスポンスHTTPレスポンス生成
UIコンポーネントツリーと管理BeanUIコンポーネントツリーUIViewRoot管理Bean管理BeanUIForm値取得UIOutputText値設定UIInputText管理BeanUICommandButtonアクション起動
コンポーネントベースFWの存在意義リッチな画面部品(カレンダーなど)の再利用が容易VBのように、部品さえ用意すれば、簡単にロジックを呼び出せるボタンや入力項目が大量についている画面が大量にあるようなアプリには適する社内C/SアプリのWeb化に適する
以前はいまいちだったけど、JSF2は前バージョンから大幅に改良されている!
38Faceletsを使った画面テンプレート化ほとんどのWeb画面では、メニューバーやサイドバー、フッターなどがパターン化されている画面が増えてくると、毎回同様のxhtmlファイルを作成するのは面倒JSF2.0ではFaceletsを採用することで、テンプレート化が簡単に行えるようになった
画面テンプレートの定義例<html …><head>…<ui:insert name="head"/>  </head>  <body>…    <div class="body"><ui:insert name="body"/>    </div>  </body></html>template.xhtml
個別画面の定義例hello.xhtml<html …><ui:composition template="/layout/template.xhtml"><ui:define name="body">    <h1>こんにちは世界!</h1></ui:define></ui:composition></html>
コンポジットコンポーネント画面中で繰り返し出現するパターンを抜き出して「タグリブ化」することが可能部品定義をxtmlで通常の画面と同様に作成し、以下のフォルダに格納するだけでよいWebアプリルート/resourcesJSP2.0のタグファイルに近い方法で気軽に画面部品を作成できるようになった
コンポジットコンポーネントの定義例link.xhtml<html …> <composite:interface>    <composite:attribute name="value“ />    <composite:attribute name="outcome"/>  </composite:interface><composite:implementation>    <h:link      outcome="#{cc.attrs.outcome}" value="#{cc.attrs.value}">      <f:param name="cid“        value="#{javax.enterprise.context.conversation.id}"/>    </h:link></composite:implementation></html>パラメーターを宣言部品の中身を定義
コンポジットコンポーネントの利用例create.xhtml<html ...      xmlns:scrum="http://java.sun.com/jsf/composite/components">...<scrum:link  outcome="/project/show"  value="プロジェクト一覧" />...</html>
JSF1.2までの画面遷移定義JSF1.2まではすべての画面遷移ルールをxmlで定義する必要があった<navigation-rule>    <description>        sprint navigation rules    </description>    <from-view-id>/sprint/show.xhtml</from-view-id>    <navigation-case>        <from-outcome>showStories</from-outcome>        <to-view-id>/story/show.xhtml</to-view-id>    </navigation-case>    <navigation-case>        <from-outcome>showDashboard</from-outcome>        <to-view-id>/dashboard/show.xhtml</to-view-id>    </navigation-case></navigation-rule>faces-config.xml
暗黙ナビゲーションJSF2.0ではほとんどの場合遷移先のビュー名を直接記述した方が便利SprintAction.javapublic String showSprints(Project project) {selectCurrentEntity(project);  return "/sprint/show?faces-redirect=true";}拡張子は省略可?faces-redirect=trueを付けるとHTTPリダイレクトする
BeanValidation(JSR303)public class Task extends AbstractEntity implements Serializable{…    @NotNull    @Size(min=0, max=128)    private String name;アノテーションを付けるだけで単項目のバリデーションが行われる。
Ajax機能を簡単に利用<h:panelGroup>  <h:inputText id=“endDate” value=“#{currentProject.endDate}”>  <f:convertDateTime pattern=“yyyy/MM/dd" /><f:ajax event="blur" render="endDateError" /></h:inputText>  </h:panelGroup><h:message id="endDateError" for="endDate" styleClass="errorMessage" />このように書くとblur、つまり、フォーカスが外れた段階でAjaxリクエストが送信され、結果がエラーメッセージに反映される。
その他細かい改良点が多数Enumのリストを直接選択項目としてバインドできるようになった以前はわざわざSelectItemのリストに変換する必要ありPOJOのリストを直接テーブルに表示できるようになった以前はDataModelに変換する必要があり選択行は直接アクションメソッドのパラメータとして簡単に受け取れる
EJB3.1=ちょっと特殊な能力を持ったPOJO以前はEJB=ビジネスコンポーネント=面倒最新のEJB3.1はちょっと特殊な能力を持ったPOJOに過ぎないトランザクションリモート呼び出し同時実行タイマー実行非同期実行
さらに、EJB3.1ではインターフェースはオプションWarファイル中に格納可能Earファイルは単純なWebアプリでは不要
EJB3.1を使った非同期実行呼び出し側のスレッドをブロックせずに時間のかかる処理を実行@Stateless public class OrderProcessBean {@Asyncronous   public void registerOrder(Order order) {    ...   }}戻り値の型はvoidかFuture型
EJB3.1を使ったタイマー実行EJB3.1で新登場のシングルトンBean@Singletonpublic class LogCleanUpBean {@Schedule(minute="1", hour="*")    public void cleanUpOldLogs() {    ...   }}CRON的な宣言で簡単に定期実行可能
JPAを使ったデータアクセスJPA = Java Persistence APIO/Rマッピングの標準化
JPAを使うと何がよいのか?静的なインピーダンスミスマッチの解決継承などを駆使した複雑なドメインモデルをテーブルにマッピングできる動的なインピーダンスミスマッチの解決エンティティの状態変更を適切なタイミングと粒度でテーブル更新に変換してくれるエンティティに複雑な状態変更などの振る舞いを持たせられるDDDと相性がよい!※DDD=DomainDrivenDevelopment
ドメイン駆動型設計(DDD)流通、販売など業務固有の処理こそが最も大切で複雑な部分コアの業務ドメインに優秀な開発者を割り当てて時間をかけてあるべきモデルに進化させていく
StoryTaskID=nullID=nullTask永続コンテキストID=nullStoryProjectID=3ID=101TaskSprintID=9StoryID=11ID=10ProjectID=101DB永続コンテキスト中のエンティティの状態はDBと自動的に同期される。
JPA2.0の新機能JPA2では細かい改良と機能追加が行われているキャッシュの標準化悲観ロックの標準化クライテリアクエリAPIの標準化より柔軟なドメインモデルのマッピングStringなど値コレクションのマッピングMapを使ったマッピング方式の拡張
JavaEEでちょっと複雑な「Bean」についてJavaEE仕様の中ではBeanという言葉が様々な仕様で使われているEnterpriseJava Bean(EJB)JSFの管理Bean(@javax.faces.bean.ManagedBeanで定義)JSR250で新たに登場した管理Bean( @javax.annotation.ManagedBeanで定義)意味が不統一なだけでなく、お互いに連携させるのも困難
一方で、SpringやSeamではレイヤーに関係なく、ほぼすべてのPOJOをBeanとしてコンテナに登録できるBean同士はお互いに統一された方法で連携させることができるやはり、Java EE6はイマイチなのか?
JavaEE6でBeanを統一的に扱う切り札となるCDICDI=Contextsand Dependency Injectionbeans.xmlファイル(空でもよい)をモジュール内に格納することでCDI機能が有効になるCDIを有効にすると、ほとんどのPOJO・EJBをすべて統一的にBeanとして扱うことができるようになる
CDIのBeanの例Beanの有効なスコープを定義JSFのビューから参照する名前を定義一定の条件を満たせば自動的にCDIのBean@Named @ConversationScopedpublic class SprintAction implements Serializable {      @InjectScrumManagerscrumManager;@InjectSprintRepositorysprintRepository;…}任意のBeanは@Injectで注入
CDIのBeanのスコープCDIのBeanはスコープを持てる@RequestScoped@SessionScoped@ApplicationScoped@ConversationScopedSingleton、Dependent疑似スコープ独自のスコープを定義して拡張することも可能
JavaEE6と試験自動化Java EE6のコンポーネントは大部分POJO従って、JUnitとモックオブジェクトを使って容易に単体試験可能加えて、軽量な埋め込みコンテナを利用することで、トランザクションやDB接続を行う結合試験の自動化もできるJeeUnitやArquillianなどを利用すると、CDIによりいっそう楽になる
今後のエンタープライズJava開発
ところで、日本のSI業界ではJavaEEの技術(プログラミングモデルの部分)は主に海外で利用され、発展してきたそもそも、日本のSI業界の事情は違うのではそもそも、コンポーネント化や多層分散アーキテクチャのシステムはほとんどなかったのでは?大規模だが、モノリシックなアーキテクチャを強制するフレームワークが蔓延
SI業界の残念な実情FN1002Commandのようなレガシーなクラス名の規約10000行を超えるクラスがあってもリファクタリングしない(できない)業務ロジックはexecute()メソッド内に記述、勝手にメソッドを分割できない今でも新規案件をJDK1.4で開発
海外はオーバーエンジニアリング海外だと、アーキテクトの権限が強いことが多く、過剰な設計となりがちだった?過剰なレイヤ、ティア分割、分散化面倒だけど頑張ってコンポーネント化、ドメインモデリングしていた?(Sessionファサードパターン)
日本はアーキテクチャ軽視日本だと、適切なアーキテクチャが施行されていないケースも多い1機能1クラス(コマンドパターン)Excelから全クラスと設定を自動生成箱はたくさん分かれているが、論理的なレイヤー構造やコンポーネント構造はなし
開発簡易化(EoD)の真の意味従来の大変だけれどつまらない単純作業から開発者が解放される単純な値の詰め替え冗長な設定ファイルの記述サービスの粒度などを自由に設計できるドメイン駆動型設計など複雑な業務ドメインをモデル化つまり「頭を使う必要がある」ということ
EoDと生産性の関係生産性・保守性SOA、 TDD、ドメイン駆動型アジャイルの開発日本のSI業界的な労働集約型、ウォーターフォールコピペ中心の開発EoD技術の進化

More Related Content

Glassfish勉強会(JavaEE6について)