Playでの作業の印象! フレームワーク2.1 + Java

Playとの激しい戦いの第4週がありました! フレームワーク2.1 + Java。 勝利は容赦なく近づいていましたが、完全な降伏には程遠いものでした。
Play!の開発に関するニュースを奨励した後 2.1、たとえばLinkedInでは、1つの新しいプロジェクトで試してみることにしました。 いわば、ビジネスでそれをテストすることです。 何から来たの? 私とPlayの間の小さな戦争だったと思います! 2.1。 なんで? カットの下の詳細が、せっかちな人のために:

簡単な結論

攻撃のために、コードネームScalaと呼ばれる秘密の武器を取る必要がありました。 Playに直面した場合! フレームワーク2.1と「あなたはScalaフレームワークです!」と大声で叫んでください。そうすれば、彼はそのような直接性を恐れ、大きなチャンスの世界への扉をささやかに開けます。
「Scalaを知らない?」-「Play 1.2を使用する」
「Scalaに精通していますか?」-「Play 2.1を試してみてください。 しかし、まだ我慢してください。


背景


剣と盾を備えたマウスとキーボードを使って7年間、私は惑星ジャワのさまざまな国を訪れました。 これらはエンタープライズの古代遺跡であり、生命はまだ暖かく、咲いているスプリングランド、彼の家臣であるグラヴィランディアとグライルス市の首都、かつては先進的でエキゾチックなPleiterra Pervoe、そして他の多くの州、都市、さらには遠隔地でした。 しかし、Pleiterra IIでのキャンペーンは予想外に困難でした。
約9か月間、私はPlay 1.2.xを使用して1つのプロジェクトに取り組みました。 Spring Framework 3の後でも、これは巨大なJava EE 5 + JSFは言うまでもなく、開発のスピードと容易さの頂点のように見えました。
その後、短い休憩があり、Grails 2.xを3か月間集中的に使用して、JavaがGroovyに比べて利便性と構文機能の点でどの程度遅れているかを理解しました。 そして、そのGrailsは、純粋なSpring Framework 3 + Javaよりも開発がやや簡単で高速です。
しかし、新しいプロジェクトのフレームワークを選択する時が来ました。その選択はPlay 2.1に落ちました。 これは正しい決断でしたか? 確かに興味深いが、正しいもの-それはまだ時間を表示します。
それまでの間、Play 2.1での作業の印象を共有したいと思います。 Play 1.2.xとの多くの比較があり、Javaと感情についてうめきます。 コードはほとんどなく、一般に受け入れられている用語や概念はロシア語に翻訳されません。 たとえば、 ステートレスフレームワーク

印象


ドキュメントの欠如

プレイテールIIの支配者によって提供されたマップは、完全にはほど遠いものでした。 主要道路は非常に正確に示されていますが、これらの道路の周りは通れません。 迷わないようにするために、私は地元の人々をつかみ、彼らに多くの質問をしなければなりませんでした。 ところで、彼らはとても喜んで答えました。
公式文書はかなりけちです。 Play 2 with JavaPlay 2 with Scalaの 2冊の本があります。 最初のJavaについては、初心者向けのコメント付きの公式ドキュメントをほぼ繰り返しています。 2番目のScalaについては、もう少し便利で、たとえば、第8章JSONを使用した単一ページのJavaScriptアプリケーションの作成など、必要なトピックをカバーしています。
もちろん、大規模で活発なコミュニティがあります 。GoogleグループStackoverflowの両方で助けを求めたり、質問をしたりできます 。 しかし、一見単純な質問に対する答えを常に探す必要がある場合、開発の喜びはいくらか失われます。
ドキュメントの改善にも参加しました( こちら )が、さらに詳しく説明したい場所がまだたくさんあります。
Play 1.2.xでは、ドキュメントはより完全で便利になりました。 StackoverflowとGoogleグループでの検索には、本当に珍しいことしかありませんでした。

コンパイル速度

ここの道路は理想からかけ離れています。 時々私は何時間も走り、泥にandれ、あきらめずに速く走るように馬に懇願しました。 大軍の移籍には非常に長い時間がかかります。 どこでもチェックポイントとチェックの道路。
多くの人にとって、これはニュースではありませんが、ここでのコンパイルは遅いです。 Play 1.2.xよりもはるかに遅い。 ここでは、単純なJavaクラスからScalaテンプレートやコーヒースクリプトまで、ほとんどすべてがコンパイルされることを理解しています。 しかし、これは長い時間です。 正気のエラーメッセージが発行されますが、これは長い時間です。 超高速の理想的なヒットリフレッシュワークフローは失速し、迷惑です。

データベースを操作する

有名な居住者は、要塞を独立して構築する方法を知りません。 彼らは言うことはできません:「別の塔を建てますが、すぐに!」。 いや 彼らには詳細な計画が必要です。
組み込みのデータベース進化エンジンがあります。 ただし、これらのスクリプトの生成には問題があります。 Ebeanは完全なスクリプトを作成できますが、インクリメンタルスクリプトにはすでに問題があります。 残念ながら、Ebeanのアナログjpa.ddl=updateは見つかりませんでした。 誰かが私に言ったら、私は非常に幸せになります。 LiquiBaseのDiffのアナログまたは適応も非常に役立ちます。

雇われた採餌者は見知らぬ男であることが判明した。 うまくいくように見えますが、供給の中断を常に待っています。
概念としてのEbeanは非常に優れています。 主な利点:

物議を醸す問題:

ここにもトランザクションがあります。 コントローラメソッドを@Transactionalとしてマークすることもでき@Transactional 。 ただし、コントローラーメソッドまたはコントローラー自体のみです。 サードパーティのクラスの場合は、これを自分で処理する必要があります。
一般的に、Ebeanは非常に興味深いライブラリであり、HibernateまたはJPAよりも単純で理解しやすい場合もありますが、成長中のプロジェクトのすべてのニーズを満たす十分な可能性があることを疑うことはありません。
もちろん、標準のJPAを使用できますが、Play 1.2.xのModel.find("byName", name)またはSpring Data JPA 1との統合はありません。 数年前に戻ってきたような気がします。

ところで、Ebeanにはいくつかの重大な欠点があります。EbeanORM使用ページの警告セクションでそれらについて詳しく読むことができます。 また、クラスにそのような手書きメソッドが少なくとも1つある場合、Play 2.1はgetter / setterの生成を停止するため、 getまたはset始まるメソッドの名前を避ける必要があります。 getterの場合、 getという単語を省略して、 byEmailまたはbyEmailを呼び出しbyEmail

しかし、 PagingListはステートレスフレームワークには適用されないため、Ebeanのキラー機能と言っても過言ではありません。 ああ、ああ。

NoSqlデータベースの操作に関しては、Elasticsearch、MongoDB(数個でも)、OrientDBのプラグインを簡単に見つけることができます。 私は自分で使ったことがないので、これらのプラグインの品質については何も言えません。

テスト中

軍隊の状態を確認することは、敵のスパイによって常にイライラします。 地元の動物は運動の組織を妨害します。サルはココナッツを投げ、ツタは足を組み、時には神風のスカンクが見つかります。
モデルの単純な単体テストからコントローラーのテスト、Seleniumの使用まで、多くの可能性があります。
私のテストでは、ドキュメントに記載されているようにメモリ内データベースを使用しようとしました。
 @Before public void setUp() throws Exception { start(fakeApplication(inMemoryDatabase(""))); } 

しかし、私にはすぐに2つの問題がありました。大小です。

小:テストでトランザクションを処理する方法 SpringやGrailsの@Transactionalようなものは見つかりませんでした。 テストでトランザクションを開いてロールバックするだけです。 不便で未熟。

大きな問題:メインベースがMySqlであるという事実と、インメモリH2テストの競合。 そのため、H2はMySqlの進化スクリプトを理解することを拒否しますが、次のようなデフォルト以外のデータベース構成を使用します。
 start(fakeApplication(inMemoryDatabase("login-test"))); 

構成を指定せずにsave()メソッドを使用すると、データの保存先が不確実になります。
私はこの問題の解決策について漠然とした説明を見てきましたが、そこには単純さはありません。
テストでデータベースの作業を整理する方法に関する公式文書には何も記載されていません。

良いの。 ソースコードを変更するたびに機能する便利なコマンド~testまたは~test-onlyがあります。 テストの実行に必要な時間を節約します。

セキュリティ

ステートフォージには最も単純な鎧しかありません。 職人はもっと良いものを作ります。
承認および認証機能はPlay 1.2.xのままでした。 @Withアノテーション付きのアクションコンポジションがあり、 Security.Authenticatorとその使用方法の良い例があります: 認証ページの追加、認証システムの実装セクション。
サードパーティのプラグインはより多くの機能を提供します。 たとえば、 DeadboltまたはSecureSocialですが、小さなプロジェクトにはあまりにもきつすぎるように思えたので、手書きの認証を完全に管理しました。
ところで、これは驚くべきことですが、Play 2. 0は Authenticity Tokenなどの便利な機能を失いましたが、失われた能力を補うサードパーティのプラグインがあります。 ただし、Play 2.1では、バージョン2.1のプレスリリースで言及されているが、ドキュメントがほとんどないfiltersがいくつか追加されました。 CSRFFilterだけに言及されたフィルターの中で。 彼について見つかった唯一のことは、ScalaでCSRFフィルターを使用する方法を説明するこの投稿です。 Play 2.1 + Javaに適用する方法と適用するかどうかは、まだ把握する必要があります。

不安定性

途中で気楼に出くわすこともありました。 彼らが近づくと、彼らは姿を消した。 マップには奇跡はありませんでした。
数回、完全に機能するコードが機能しなくなりました! どうやら、ゲッター/セッターのコンパイルと生成が常に正しく動作するとは限りません。 play clean 、プロジェクトを再起動するのに役立ちました。
私が遭遇した最も奇妙なことは、 JDK 7有効なコードタイプJDK 7次のとおりJDK 7です。

 catch (IndexOutOfBoundsException | ArrayStoreException e) 

Play 2.1を完全に混乱させました。エラーもメッセージもありません。これらの行でサーバーがフリーズするだけで、それ以上何も起こりません。 ここで質問し、回答を待った。

パターン

彼らは彼らの頭で吸うことができるような沼地があります。 そして、彼らは吸うことはできません。
率直に言って、テンプレートを効果的に使用するには、Scalaを十分に理解するか、少なくともScalaの内容を理解する必要があります。 そうでなければ、これはすべてコードの理解できないトリックになります。 そして、次のように機能するため、非常に注意する必要があります。
 @main(title = "Home") { <h1>Home page</h1> } 

そのため、新しい行に{が原因で既にエラーが発生しています。
 @main(title = "Home") { <h1>Home page</h1> } 

または別の例:
 //  @if(user == null) //  ,    : @if (user == null) 

Play 2.0でScalaテンプレートについて初めて読んだとき、.Netの非常に便利なRazorのように見えたので、とても嬉しかったです。 私の意見では、Javaの世界の多くのテンプレートエンジンよりも本当に便利です。 ただし、すべての入力パラメーターを最初の行として宣言する必要があることを忘れないでください。 また、コード内でfullName変数を宣言するには、次のようにします。
 @defining(user.getFirstName() + " " + user.getLastName()) { fullName => <div>Hello @fullName</div> } 

そして、いくつかのことをインポートするために必要なもの: @import helper._ 。 さらに多くの「ifs」と「buts」があり、その中であなたはあまり自由ではないと感じます。
主な利点は、Scalaテンプレートがコンパイル段階でコンパイルおよびチェックされることです。これにより、未承諾のエラーや攻撃的なタイプミスの数が減ります。
一般に、Play 2.1でScalaテンプレートが良いか悪いかは重要ではありませんが、Javascript MVCフレームワークが人気を集めており、次のことが重要になるため、背景に隠れています。

JSONを使用する

それから勇敢な戦士は一般的に動揺し、居酒屋で飲みに行きました。
私の意見では、Play 2.1はPlay 1.2.xに少し負けています。 主な理由は、Gsonの代わりに、JavaでJSONを操作するためのメインライブラリとしてJacksonが使用されていることです。 Play 1.2.xでGSONを使用するのが好きでした。便利で柔軟でした。 ジャクソンはまったく異なる方法で働く必要があります。 どうやら、私はまだ彼を楽しむためにジャクソンのそのレベルの理解に達していません。 そして、JSON文字列のフィールド名を二重引用符でエスケープする必要があるという事実は、ため息をつく原因でした。
 return ok(Json.parse("{\"status\": \"success\"}")); 

読みやすさはほとんどありません。 特に、GrailsでのJSONの扱いやすさと比較すると:
 render([result: 'fail'] as JSON) 

もちろん、すべてがそれほど悪いわけではありませんが、Javaでできる最善のことは2のようなものです:
 ObjectNode result = Json.newObject(); ArrayNode arrayNode = result.putArray("photos"); for (Photo photo : photos) { ObjectNode photoAsJson = arrayNode.addObject(); photoAsJson.put("id", photo.id); photoAsJson.put("guid", photo.guid); } return ok(arrayNode); 

かなり耐えられる。
ただし、Scalaの場合、Play 2.1のJSONサポートは大幅に改善されています。
 Json.obj( "users" -> Json.arr( Json.obj( "name" -> "bob", "age" -> 31, "email" -> "bob@gmail.com" ), Json.obj( "name" -> "kiki", "age" -> 25, "email" -> JsNull ) ) ) 

しかし、Groovyでは、より短くシンプルに見えます。 それでも、ScalaがXMLのようにネイティブJSONサポートを追加することが望まれます。
私は自分の人生を単純化することに決め、静的メソッドを備えた2つの追加クラスを追加しました。1つはTuple2アナログであるPair 、もう1つはMapPairを置くクラスです。 その結果、私にとっては簡単になりました。
 return ok(toJson(map( pair("status", "fb-logged-in"), pair("user", map( pair("id", fbUser.id), pair("facebookUserId", fbUser.facebookUser.userId), pair("fullName", fbUser.fullName()) )) ))); 

タプルについて話しているので、Play 2.1ではJava機能のサポートがPlay 1.2.xのライブラリplay.libs.Fからコピーされます。 ただし、これについての公式文書には言及されていません。 Play 1.2.xのドックを監視する必要があります。

もう1つ:Play 1.2.xからXMLサポートも移行されました。XMLの操作にplay.libs.XPathを使用play.libs.XPathと非常に便利です。

メールで作業する

伝書鳩とカラスはすべてここに輸入されます。 簡単に入手できます。 そして、プレテールIIの支配者がすべての鳥を撃ったという噂があります。
Play 1.2.xではなく、Play 1.2.xでメールを送信するための組み込みサポートがあったため、メールについて少し言いたいと思います。 メール用の公式プラグインがあります 。 ここは、作成者自身がメールサポートを追加しないことに決めたと言っています。 伝えられるところでは、それは誰もが自分でできるほど簡単でシンプルです。 Googleグループの多くの質問とinりがこの観点に反論しています。人々はPlay 2.1にPlay 1.2.xよりも機能が劣らないことを期待しています。

構成

以前の契約が巻物に書かれていた場合、現在は別の葉に書かれています。
注目に値する主なことは、彼らがframework IDを削除したことです。 ここで、1つの大きな構成ファイルの代わりに、いくつかの個別の構成ファイルが必要です。 議論の余地がある点として、各アプローチには長所と短所があります。 以前にproductionを開始した場合:
play run --%production
これは次のようになります。
play -Dconfig.resource=prod.conf start
また、 prod.confは、プレフィックスなしのすべての設定オーバーライドが含まれています。

IDE統合

私の最高の馬が地元の道路に足を押し込みました!
すべてのIDEのすべてのOdessaについてはお話ししませんが、私の愛するIntellij IdeaはPlay 2.xをサポートしており、理想とはかけ離れています。 コードナビゲーションは、多くの場合、見たり見たりする必要のない生成されたクラスにつながります。時にはscalaテンプレートの編集に問題があり、SBTの完全なサポートはバージョン13でのみ利用できます。 ここに私が見つけて報告したものがあります: youtrack.jetbrains.com/issues/SCL?q=reported+by%3A+Andrey.Volkov+
コードを書く喜びだけでは十分ではありません。 Play 2.xはそれほど前にリリースされておらず、IDEのサポートに大きなリソースを費やすほど人気が​​ないかもしれないことを理解しています。 IDEからのヘルプをあまり期待しないでください。
Play 1.2.xでは、これははるかに優れています。

シンプルさがなくなった

Playterre Iの国が奇跡に満ちていて、魔法の杖の波で多くのことが行われた場合、Playterra IIには魔法はなく、シャベルと、盾と剣しかありません。
Play 1.2.xは非常にシンプルで便利でした。 何とかそれ自体で多くのことが行われ、うまくいきました。 はい、Play 1.2.xであまりにも多くが発生し、生成されすぎて通常のJavaの世界とはまったく異なるという意見を聞きましたが、それは簡単、簡単、迅速に機能しました。 すべての複雑さは普通のユーザーから隠されていて、最も細心の注意を払ったプログラマーだけが複雑なソースコードを掘り下げる必要がありました。
Play 2.1では、ほとんどすべての「魔法」はScalaに委ねられています。 そしてこれはもはや魔法ではなく、これはScalaの明確に定義された作品です。 プログラマーは常につまずく必要があります。 また、Scalaの基礎さえ知らないと、理解するのは非常に困難です。
楽しみのために比較してください:
 public static void index() { render() } 

そして
 public static Result login() { return ok( login.render() ); } 

最初のコードはよりシンプルですが、いくつかの規則を知って従う必要があり、2番目のコードはより冗長ですが、何かを知って従う必要があります。 2番目の方法はより柔軟ですが、単純ではありません。 私は個人的に最初のものが好きです。
ところで、 login 2番目の例でloginどう思いloginか? これは、scalaテンプレートから生成されたクラスです。 これは、この非常にscalaテンプレートのコンパイル後にのみ表示されます。 つまり IDEは、そのようなクラスが存在しない、または何かを変更するとメソッドシグネチャが一致しないと文句を言います。 コンパイル後、苦情は消えますが、IDEのヒントを使用すると問題が生じます。
Playterre Oneは、翼のある妖精と元気でいっぱいでした。 Playterra IIには、各ギアを見ることができるメカニカルゴーレムしかありません。

紛れもない利点


多くの奇妙なことにも関わらず、欠陥とは言わないまでも、Play 2.1には多くの否定できない利点があります。

フォームと検証の操作

とても快適です。 JSR-303(Bean Validation)の完全サポートに加えて、特定のチェック用に独自のvalidateメソッドを追加する機能。 公式ドキュメントの例を書き換えません。 ここで完全に見ることができます
テンプレートの場合、 inputフィールドの組み込み生成があり、Twitter Bootstrapのマークアップをすぐに生成できます。 唯一の残念は、バージョン1.4の場合です。 カスタムジェネレーターを記述する必要があります(独自のフィールドコンストラクターの記述セクション)。
Authenticity Tokenが削除されておらず、Twitter Bootstrap 2.3フィールドが生成されていた場合、ほぼ理想的です。

Akkaおよびその他の非同期のもの

地元の居酒屋や居酒屋は非常に高速なサービスを提供しています。 そして、キューはありません。
非同期性とマルチスレッドのサポートに関しては、馬に乗って2.1をプレイします。 非同期HTTP要求のネイティブサポート とAkkaとの統合があります。 関数を操作するときに、Javaの冗長性のみが公式ドキュメントにも記載されていない場合...
ただ比較してください。 Java:
 public static Result index() { Promise<Integer> promiseOfInt = play.libs.Akka.future( new Callable<Integer>() { public Integer call() { return intensiveComputation(); } } ); return async( promiseOfInt.map( new Function<Integer,Result>() { public Result apply(Integer i) { return ok("Got result: " + i); } } ) ); } 

Scala:
 def index = Action { val futureInt = scala.concurrent.Future { intensiveComputation() } Async { futureInt.map(i => Ok("Got result: " + i)) } } 

Scalaに切り替えるもう1つの理由。 または何か他のものですが、Javaよりも「機能的」です。
ただし、競合他社は眠っていません。Grails2.3では、非同期コンピューティングのサポートが非常に優れています( 公式ブログに投稿 )。 さらに、非同期コンピューティングはJavaよりもGroovyの方が便利です。クロージャーのサポートが役割を果たします。

スケーラビリティとクラウド

ここの土地は肥沃で、ほとんどすべての人口を養うことができます。 そして、さまざまな形や大きさの雲が空に浮かんでいます。
非同期でステートレスな性質のため、Play 2.1は非常にうまくスケーリングすると言われています。 これまでのところ、私のプロジェクトはそのようなニーズに成長していないため、自分の経験からこれを確認することはできません。
はい。Play2.xは多くのクラウドホスティングサイトでサポートされています。 さらに、ネイティブサポート、つまり WARファイルを作成してTomcat / Jettyの下にデプロイする必要はありません。
それでもwarファイルを収集する必要がある場合は、 サードパーティのプラグインを使用してのみこれを行うことができます。

CoffeeScriptと少ないサポート

小さな悪魔がここで飼いならされ、今では人々に忠実に仕えています。
CoffeeScriptおよびLessのネイティブサポート。 ここで何を追加または説明できるかさえわかりません。 便利に。 そうです。 すべてを縮小したとしても、どこも単純ではありません.min.jsではなく.min.jsをロードするだけです。
これにはまだ問題はありません。

コンソール

Playterra IIの入り口の税関は、新しい労働者を雇いました。 誰も気にしないが、とにかく彼らの作品を見ることはない。 彼らがうまく働くようにすると、誰も彼らに注意を払うことはありません。
コンソールは、Play 1.2.xよりもはるかに便利で機能的になりました。 しかし、これはPlay 2.1自体よりもSBT(Scala Build Tool)の功績です。
便利になったものから、 ~で始まるコマンドについて言及したいと思います。これらのコマンドは、ソースコードが変更されるたびに実行されます。 上記の~testの例。

結果は何ですか?


Playterra IIで休暇をとることは興味深いです。 そこでの移行に関する問題はまだ未解決のままです。
私自身のために、私は次の結論を出しました。




[1]-正直なところ、SpringをPlay 2.1に統合することは可能ですが、 それほど難しくはありません 。 つまり Spring Data JPAおよびSpring Dataの他のプロジェクトは理論的には追加できますが、このテーマに関する具体的な例や記事は見つかりませんでした。 彼の手も届きませんでした。
[2]-記事の準備中に、彼はJSON処理用のJava APIをJava EE 7に実装する必要があることを発見しました。 Oracleブログのこの投稿から判断すると、この例よりも便利で優れています。 GroovyのJSONサポートに十分近い。 将来的にはこれだけ。

Source: https://habr.com/ru/post/J173211/


All Articles