Впечатления от работы с Play! Framework 2.1 + Java

    Шла четвёртая неделя тяжёлых боёв с Play! Framework 2.1 + Java. Победа неумолимо приближалась, но до полной капитуляции было далеко.
    После обнадёживающих новостей про развитие Play! 2.1, например в LinkedIn, было решено попробовать его в одном новом проекте. Испытать его, так сказать, в деле. Что из этого получилось? Я бы сказал, что это была небольшая война между мной и Play! 2.1. Почему? Подробности под катом, а для нетерпеливых:

    Краткий вывод

    Для штурма надо было брать секретное оружие под кодовым названием Scala. Если встать лицом к лицу с Play! Framework 2.1 и крикнуть со всей силы: «Ты есть Scala-фреймворк!», то он испугается такой прямоты и скромно откроет свои двери в мир больших возможностей.
    «Не знаете Scala?» — «Используйте Play 1.2».
    «Хорошо разбираетесь в Scala?» — «Обязательно попробуйте Play 2.1. Но всё равно запаситесь терпением».


    Предыстория


    За 7 лет с мышью и клавиатурой мечом и щитом я побывал в разных государствах на планете Java. Это были и древние развалины Энтерпрайзности, где ещё теплится жизнь, и цветущая Спрингляндия, и его вассал Грувиляндия со столицей в Грэилз-Сити, и когда-то передовое и экзотическое Плейтерре Первое, и много-много других государств, городов и даже глухих деревень. Но поход на Плейтерре II оказался неожиданно тяжёлым.
    Я около 9 месяцев работал над одним проектом, используя Play 1.2.x, и был в полном восторге. Даже после Spring Framework 3 это казалось верхом скорости и простоты разработки, не говоря про монструозный Java EE 5 + JSF.
    Потом был небольшой перерыв, в который я успел 3 месяца интенсивно поработать с Grails 2.х и понять, насколько Java отстала от Groovy в плане удобства и возможностей синтаксиса. И что Grails в какой-то степени проще и быстрее в разработке, чем чистый Spring Framework 3 + Java.
    Однако настало время выбирать фреймворк для нового проекта, и выбор пал на Play 2.1. Было ли это правильно решение? Интересное точно, а вот правильное — это ещё покажет время.
    Пока же я хочу поделиться своими впечатлениями от работы с Play 2.1. Будет много сравнений с Play 1.2.x, стенаний по поводу Java и эмоций. Кода почти не будет, и общепринятые термины и понятия не будут переведены на русский язык. Например, stateless framework.

    Впечатления


    Недостаток документации

    Карты местности, которые предоставили правители Плейтерре II, оказались далеко неполными. Главные дороги обозначены вполне точно, но вокруг этих дорог непролазная чаща. Чтобы не плутать, приходилось хватать местных жителей и задавать им немало вопросов. Отвечали они, кстати, весьма охотно.
    Официальная документация достаточно скупа. Есть две книжки Play 2 with Java и Play 2 with Scala. Первая, про Java, во многом повторяет официальную документацию с комментариями для новичков. Вторая, про Scala, чуть более полезна и затрагивает нужные темы, например Chapter 8. Building a single-page JavaScript application with JSON.
    Конечно, есть большое и активное сообщество, попросить о помощи и задать вопрос можно и в Google Groups, и на Stackoverflow. Но удовольствие от разработки несколько теряется, если постоянно приходится искать ответы на казалось бы простые вопросы.
    Я даже поучаствовал в улучшении документации (вот), но есть ещё много мест, которые хочется осветить более подробно.
    Для Play 1.2.x документация была полнее и полезнее. Искать на Stackoverflow и в Google Groups приходилось только действительно необычные вещи.

    Скорость компиляции

    Дороги тут далеки от идеала. Иногда приходилось часами ехать, утопая в грязи и умоляя лошадь не сдаваться и скакать быстрее. Переброска большой армии занимает очень много времени. На дорогах везде КПП и проверки.
    Для многих это не будет новостью, но компиляция тут работает медленно. Намного медленнее, чем в Play 1.2.x. Я понимаю, что тут компилируется почти всё, от простых Java-классов до Scala temlates и coffee scripts. Но это долго. Пусть выдаются вменяемые сообщения об ошибках, но это долго. Молниеносный в идеале Hit refresh workflow пробуксовывает и раздражает.

    Работа с базой данных

    Метные жители не умеют самостоятельно достраивать крепости. Им нельзя сказать: «Возведи ещё башню, да побыстрее!». Нет. Им нужен подробный план.
    Есть встроенный механизм Database Evolutions. Но вот с генерацией этих скриптов проблема. Ebean ещё может создать полный скрипт, а с инкрементарными уже проблемы. Aналога jpa.ddl=update для Ebean я, к сожалению, не нашёл. Если кто-то подскажет, то буду безмерно рад. Аналог или адаптация LiquiBase's Diff была бы тоже очень кстати.

    Нанятые фуражиры оказались странными мужиками. Вроде работают, но постоянно ждёшь перебоев с поставками.
    Ebean как концепция весьма хорош. Главные преимущества:
    • отсутствие сессий (Session, EntityManager и т.п.), что хорошо вписывается в stateless framework. Однако как таковой Persitent Context есть.
    • поддержка Partial Objects, позволяющая писать более производительные запросы.

    Спорные моменты:
    • Частичная поддержка JPA. Надо точно знать и понимать, где эта поддержка заканчивается.
    • Недостаток документации и примеров использования.
    • Не такая активная разработка и не такое большое сообщество, как у Hibernate.

    Транзакции тут тоже есть. Можно даже метод контроллера пометить как @Transactional. Но только метод контроллера или сам контроллер. Для сторонних классов надо уже самому заботиться об этом.
    В общем, Ebean — библиотека очень интересная, местами даже проще и понятнее, чем Hibernate или JPA, но я не могу избавиться от сомнений, что возможностей её хватит, чтобы удовлетворить все потребности растущего проекта.
    Конечно, можно использовать стандартный JPA, но так не хватает Model.find("byName", name) из Play 1.2.x или интеграции со Spring Data JPA1. Возникает чувство, что возвращаешься на несколько лет в прошлое.

    Кстати, у Ebean есть несколько существенных недостатков: подробнее о них можно прочитать в разделе Caveats на странице Using the Ebean ORM. И то, что Play 2.1 перестаёт генерировать getter/setter, если в классе есть хотя бы один такой рукописный метод, заставляет избегать названий методов, начинающихся c get или set. Для геттеров я теперь просто опускаю слово get и называю методы byName или byEmail.

    А вот такая невероятная вещь, можно даже сказать killer feature в Ebean, как PagingList в stateless framework неприменима. Увы и ах.

    Что касается работы с NoSql баз данных, то без труда можно найти плагины для Elasticsearch, MongoDB (даже несколько штук) и OrientDB. Сам не пользовался, поэтому ничего про качество этих плагинов сказать не могу.

    Тестирование

    Проверка состояния армии постоянно срывается вражескими шпионами. Организации учений мешает местная живность: обезьяны кидаются кокосовыми орехами, плющи оплетают ноги, а иногда встречаются скунсы-камикадзе.
    Оно есть, возможностей много: от простых unit-тестов моделей до тестирования контроллеров и использования Selenium.
    В своих тестах я пытался использовать in-memory database так, как это описано в документации:
    @Before
    public void setUp() throws Exception {
        start(fakeApplication(inMemoryDatabase("")));
    }
    

    Однако у меня сразу же возникли две проблемы, большая и маленькая.

    Маленькая: как быть с транзакциями в тестах? Ничего подобного @Transactional из Spring или Grails я нашёл. Остаётся только самому открывать и откатывать транзакции в тестах. Неудобно и незрело.

    Большая: конфликт между тем, что основная база у меня MySql, а для тестов in-memory H2. Так вот, H2 отказывается понимать evoluation scripts для MySql, а использование не default конфигурации БД, например так:
    start(fakeApplication(inMemoryDatabase("login-test")));
    

    влечёт за собой неопределённость того, куда всё же сохранятся данные, если использовать метод save() без указания конфигурации.
    Я видел несколько неясных описаний решения этой проблемы, но простотой там и не пахнет.
    Официальная документация поводу того, как организовать работу БД в тестах, ничего не говорит.

    Из хорошего. Есть полезные команды ~test или ~test-only, которые будут срабатывать каждый раз, кода вы меняет исходный код. Позволяет сэкономить время, необходимое для запуска тестов.

    Security

    В государственных кузницах есть только самые простые доспехи. Народные умельцы куют намного более качественные вещи.
    Возможности по авторизации и аутентификации остались на уровне Play 1.2.x. Есть Action Composition с аннотацией @With, есть Security.Authenticator и хороший пример как им пользоваться: страница Adding authentication, раздел Implementing authenticators.
    Сторонние плагины предлагают более широкие возможности. Например, Deadbolt или SecureSocial, но мне они показались через чур накрученными для небольшого проекта, и я прекрасно обошёлся своей рукописной авторизацией.
    Кстати, это удивительно, но Play 2.0 лишился такой полезной возможности как Authenticity Token, но есть сторонний плагин, который восполняет утраченные способности. Однако, в Play 2.1 добавили некие filters, которые упомянуты в пресс-релизе версии 2.1, но про которые очень мало документации. Среди фильтров упомянут как раз CSRFFilter. Единственное, что удалось найти про него — это вот этот пост, который описывает как работать с фильтром для защиты от CSRF в Scala. Как применить и применимо ли это вообще к Play 2.1 + Java надо ещё разобраться.

    Нестабильность

    Иногда на пути попадались миражи. При приближении они исчезали. На картах миражей отмечено не было.
    Несколько раз вполне работающий код переставал работать! Видимо, не всегда корректно работает компиляция и генерация getters/setters. Помогали play clean и перезапуск проекта.
    Самый странный момент, на который я наткнулся, был в том, что валидный для JDK 7 код типа:

    catch (IndexOutOfBoundsException | ArrayStoreException e)
    

    приводил Play 2.1 в полный ступор: ни ошибок, ни сообщений, просто сервер зависает на этих строчках и дальше ничего не происходит. Задал вопрос здесь, жду ответа.

    Шаблоны

    Тут попадаются такие болота, что могут засосать с головой. А могут и не засосать.
    Надо сказать прямо: для эффективного использования шаблонов надо хорошо знать Scala или хотя бы что-то в ней понимать. Иначе всё это превращается в непонятное хитросплетение кода. И надо быть очень осторожным, потому что так работает:
    @main(title = "Home") {    
      <h1>Home page</h1>    
    }
    

    а так уже будет ошибка из-за { на новой строке:
    @main(title = "Home") 
    {    
      <h1>Home page</h1>    
    }
    

    Или другой пример:
    //так работает
    @if(user == null)
    //а так нет, потому что стоит пробел:
    @if (user == null)
    

    Когда я первый раз прочитал про Scala templates в Play 2.0, то был очень рад, потому что это напоминало очень удобный Razor из .Net. Действительно похоже, и, на мой взгляд, удобнее многих template engine в мире Java. Однако не забывайте, что первой строчкой вы должны объявить все входные параметры. И объявить переменную fullName в коде можно только так:
    @defining(user.getFirstName() + " " + user.getLastName()) { fullName =>
      <div>Hello @fullName</div>
    }
    

    И что надо делать импорт для некоторых вещей: @import helper._. И ещё множество «если» и «но», в рамках которых чувствуешь себя не очень свободно.
    Главный плюс — Scala templates компилируются и проверяются на этапе компиляции, что уменьшает количество неотловленных ошибок и обидных опечаток.
    В общем, хороши или плохи Scala template в Play 2.1 — вопрос спорный, но он отступает на второй план, потому что Javascript MVC фреймворки набирают популярность, и актуальным становится следующее:

    Работа с JSON

    Тут отважный воин вообще растроился и ушёл пить в кабак.
    На мой взгляд, Play 2.1 немного проигрывает Play 1.2.x. Главная причина — вместо Gson используется Jackson как основная библиотека для работы с JSON в Java. Мне понравилось работать с GSON в Play 1.2.x, это было удобно и гибко. С Jackson надо работать совсем по-другому. Видимо, я ещё не достиг того уровня понимания Jackson, чтобы получать от него наслаждение. А то, что имена полей в строке c JSON должны быть эскапированы двойными кавычками, вызвали у меня тяжкий вздох:
    return ok(Json.parse("{\"status\": \"success\"}"));
    

    Читаемость почти никакая. Особенно, если сравнивать с лёгкостью работы с JSON в Grails:
    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 поддержку JSON в версии Play 2.1 значительно доработали:
    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 всё-таки добавят нативную поддержку JSON, как это есть сейчас для XML.
    Я же решил упростить себе жизнь, дописал два дополнительных класса со статическими методами: один — это Pair, аналог Tuple2 из Scala, другой — класс, который кладёт Pairs в Map. В итоге мне стало проще:
    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())
                        ))
                )));
    

    Раз уж речь зашла о кортежах (Tuples), то в Play 2.1 поддержка функционального для Java скопирована из Play 1.2.x, библиотека play.libs.F. Однако упоминаний в официальной документации об это нет. Надо смотреть доки для Play 1.2.x.

    И ещё один момент: поддержка XML тоже перекочевала из Play 1.2.x, и пользоваться play.libs.XPath для работы с XML очень удобно.

    Работа с почтой

    Почтовые голуби и вороны здесь все завозные. Достать их легко. И ходят слухи, что правители Плейтерре II сами всех птиц отстреляли.
    Хочу сказать про почту несколько слов потому, что в Play 1.2.x была встроенная поддержка отправки почты, а в Play 2.1 нет. Есть официальный плагин для почты. Вот вот тут говорят, что сами создатели приняли решение не добавлять поддержку почты. Якобы это так легко и просто, что каждый может сделать сам. Множество вопросов и возмущений в Google Groups опровергает эту точку зрения: люди ждут от Play 2.1 не меньшей функциональности, чем была в Play 1.2.x.

    Конфигурация

    Если раньше договоры писали на свитках, то теперь на отдельных листочках.
    Главное, что стоит отметить, — это то, что убрали framework ID. Теперь вместо одного большого конфигурационного файла, надо иметь несколько отдельных. Спорный момент, у каждого подхода есть свои плюсы и минусы. Если раньше для запуска production было:
    play run --%production
    то теперь это выглядит так:
    play -Dconfig.resource=prod.conf start
    И prod.conf содержит в себе все переопределения настроек без всяких префиксов.

    Интеграция с IDE

    Моя лучшая лошадь подвернула ногу на здешних дорогах!
    Я вам не скажу за всю Одессу за все IDE, но моя любимая Intellij Idea имеет пока далёкую от идеала поддержку Play 2.x. Навигация по коду очень часто приводит в сгенерированные классы, которые смотреть и видеть не нужно, иногда бывают проблемы с редактированием scala templates, полная поддержка SBT будет только в 13 версии. Вот только то, что нашёл и сообщил я сам: youtrack.jetbrains.com/issues/SCL?q=reported+by%3A+Andrey.Volkov+
    Удовольствия от написания кода мало. Я понимаю, что Play 2.x вышел не так уж давно и может быть не так ещё популярен, чтобы тратить большие ресурсы его поддержку в IDE. Просто знайте, что большой помощи от IDE ждать не стоит.
    С Play 1.2.x в этом плане намного лучше.

    Исчезнувшая простота

    Если страна Плейтерре Первое была полна чудес и многое делалось по мановению волшебной палочки, то в Плейтерре 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()
        );
    }
    

    Первый кусочек кода проще, но надо знать и следовать некоторым договорённостям, а второй кусочек кода более многословен, но также надо кое-что знать и кое-чему следовать. Второй может быть более гибким, но не более простым. Первый лично мне нравится больше.
    Кстати, как вы думаете, что такое login во втором примере? Это класс, сгенерированный из scala template. Которые появляется только после компиляции этого самого scala template. Т.е. IDE будет жаловаться, что такого класса нет или сигнатуры методов не совпадают, если вы что-то поменяли. После компиляции жалобы пропадут, но пользоваться подсказками IDE становится проблематично.
    Плейтерре Первое было полно легкокрылых фей и добрых духов. В Плейтерре II есть только механические големы, в которых можно разглядеть каждую шестерёнку.

    Неоспоримые преимущества


    Несмотря на множество странностей, если не сказать недоработок, Play 2.1 обладает рядом неоспоримых преимуществ.

    Работа с формами и валидация

    Очень удобна. Полная поддержка JSR-303 (Bean Validation) плюс возможность дописать свой собственный validate-метод для специфичных проверок. Не буду переписывать примеры из официальной документации. Их можно прекрасно посмотреть здесь.
    Для шаблонов есть встроенная генерация input полей, причём можно сразу генерировать разметку для Twitter Bootstrap. Жаль только, что для версии 1.4. Приходится писать кастомный генератор (раздел Writing your own field constructor).
    Если бы не убрали Authenticity Token и генерировали поля для Twitter Bootstrap 2.3, то был бы практически идеал.

    Akka и прочие асинхронные штучки

    В здешних кабаках и тавернах очень быстрое обслуживание. И никогда не бывает очередей.
    В плане асинхронности и поддержки многопоточности Play 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. Или на что-то другое, но более «функциональное», чем Java.
    Однако конкуренты не дремлят: в Grails 2.3 будет весьма неплохая поддержка асинхронных вычислений (пост в официальном блоге). Тем более заниматься асинхронными вычислениями на Groovy удобнее, чем на Java: поддержка замыканий играет свою роль.

    Масштабируемость и облака

    Земля здешняя плодородна и может прокормить почти любое население. А по небу плывут и плывут облака самых разных форм и размеров.
    Говорят, что благодаря асинхронной и stateless природе, Play 2.1 прекрасно масштабируется. Пока мой проект не дорос до таких потребностей, поэтому не могу подтвердить это на собственном опыте.
    Да, и Play 2.х поддерживается множеством облачных хостингов. Причём поддержка нативная, т.е. не надо собирать war-файл и деплоить под Tomcat/Jetty.
    Если всё же необходимо собрать war-файл, то сделать это можно только с помощью стороннего плагина.

    Поддержка CoffeeScript и Less

    Мелких бесов тут приструнили, и теперь они несут верную службу людям.
    Нативная поддержка CoffeeScript и Less. Даже не знаю, что тут можно добавить или объяснять. Удобно. Так и надо. Даже минифицируется всё проще некуда: просто загружаешь .min.js вместо .js.
    Проблем с этим пока не было.

    Консоль

    Таможня на въезде в Плейтерре II наняла новых работников. Хотя кому какая разница, их работы всё равно никто не видит. Пусть хорошо работают, на них тогда никто и внимания не обратит.
    Консоль стала намного удобнее и функциональнее, чем была для Play 1.2.x. Но это больше заслуга SBT (Scala Build Tool), чем самого Play 2.1.
    Из того, что мне пригодилось, хочу упомянуть команды, начинающиеся с ~, которые выполняются каждый раз, когда происходит изменение исходного кода. Пример с ~test я приводил выше.

    Что в итоге?


    Съездить в отпуск на Плейтерре II интересно. Вопрос же с миграцией туда на совсем пока открытый.
    Для себя я сделал следующие выводы:
    • Чтобы использовать Play 2.1 по полной, надо хорошо знать Scala.
    • Надо быстренько написать веб-приложение на Java? Бери Play 1.2.x. Или Grails. В Groovy не так сложно разобраться, как в Scala.
    • Надо изучать Scala. Именно изучать, потому что отличия от Java и даже Groovy очень существенные.
    • Java почти безнадёжно отстала от других языков программирования. Возвращаться к написанию кода только на Java после того, как начал получать удовольствие от функционального программирования, очень тяжело. Может быть Java 8 спасёт ситуацию.




    [1] — честно говоря, интегрировать Spring в Play 2.1 можно, это даже выглядит не очень сложно. Т.е. Spring Data JPA и другие проекты из Spring Data теоретически можно добавить, но конкретных примеров и статей по этому поводу я не нашёл. У самого руки тоже не дошли.
    [2] — при подготовке статьи обнаружил, что для Java EE 7 должен быть реализован Java API for JSON Processing. Судя по этому посту в блоге Oracle, это будет удобнее и лучше, чем приведённый пример. Достаточно близко к поддержке JSON в Groovy. Только это в будущем.
    Поделиться публикацией

    Комментарии 40

      +2
      Отличная статья!
      Как человек, первый раз попробовавший play! еще в дремучей версии 1.0 (там и близко scala не было), версия 2.x и дальше — это чисто scala framework, и если хочется остаться в рамках java (попробуйте найти программистов с опытом scala), то play! 1.2 и только.

      За что создателей play! сейчас нещадно критикуют.
        +1
        Немного о политике. Если версия 2.0 курировалась и писалась в zenexity людьми очарованными haskell, f# и scala и которые не могли смотреть на java без рвотных позывов, то версия 2.1 дорабатывалась typesafe так как zenexity не выполнила своих прямых обязательств в срок. Сложно сказать будет ли в play 2.* нормальная поддержка java как в 1.*. Насколько мне известно typesafe определили на проект play именно scala разработчиков, да компания продвигает именно scala на рынке. Скорее всего поддержка java будет болтаться в проруби и в последующих версиях. С другой стороны что сегодня можно сделать с java, который безнадежно склеивает ласты.
          +3
          С другой стороны что сегодня можно сделать с java, который безнадежно склеивает ласты.

          Да ну? Прямо таки склеивает ласты, причем безнадежно?
          «А мужики-то не знают...»
            +1
            Да сравнинте хотя бы фичи по датам выпуска в c# и java, там разница в несколько световых лет. Например если говорить про консервативный с++ до даже в его последнем стандарте есть поддержка closure а в java такая фича еще до сих пор под вопросом. Да это сугубо мое личное мение, может от части схожее с авторским. Если вы хотите тут развести троллоло то не советую.
              0
              Не спора ради: замыкания в с++ и java примерно одинаково реализуются (в с++ это просто объект с перегруженным оператором скобки).
              А по делу: пока есть enterprise будет ява!
                0
                Согласен с вами, на мой взгляд с java дела обстоят точно так же как с cobol который до сих пор можно встретить во многих организациях например в крупных банках Люксембурга. Платформа будет существовать еще достаточно долго, наверное столько сколько будет спрос даже если большенство разработчиков будут отдавать предпочтения другим языкам.
                  0
                  У меня такое же впечатление. Поэтому надо изучать и что-то отличное от Java, чтобы не просто не потерять работу, но и иметь удовольствие писать на чём-то современном и красивом.
                    0
                    Я с такими же мыслями изучал scala =)
                    0
                    Насчет cobol'а я бы даже сказал больше — такие АБСки до сих пор продаются (типичный пример accenture alnova).
                  0
                  Я согласен, что Java сильно отстает по синтаксису от C#, и многие фичи (например, generics, annotations) реализованы немного странно и часто в угоду обратной совместимости. Однако говорить, что Java склеивает ласты, мягко говоря, преждевременно.

                  Весь enterpise сидит на Java, есть куча фреймворков, реализованных на этой платформе. Да взять хотя бы тот же Hadoop, который используется все чаще. Да и в Google, Amazon и других гигантах, использующих opensource, Java используется вовсю.
                    0
                    Дык на кобыле (cobol) тоже вон сколько всего написанно. А что собственно вам мешает Hadoop, Lucene итд портировать на c# получится гороздо лучше. Склеивание ласт начинается с забрасывания обогащения фич языка. А то что весь энтерпрайз сидит то заслуги прошлых лет и только sun и если ничего не предринять то будет поздно.
                      +1
                      Развитие C# намертво привязано к проприетарному и некроссплатформенному .NET (да, есть Mono, но уровень поддержки не тот, и по возможностям отстает от .NET). Скорее Scala или что-то подобное заменит, но еще не скоро. Ценность Java как раз не в языке, а в самой платформе и ее экосистеме. А под JVM можно писать и на других языках, на той же Scala.
                        –1
                        Насчет фич в моно есть все необходимое и за ним стоит солидная контора а уровень поддержки нисколько не отличается от j2se. Когда я говорю про склеивание ласт я имею ввиду только java как язык. Одерский как то сказал в одной из своих заметок что java который мы знаем уже давно исчерпал свои возможности а вот jvm нет и именно с ней и стоит работать и развивать ее. Например еклипс как всегда обгадился делая ставку на язык поверх java вместо jvm.
                          0
                          еклипс как всегда обгадился делая ставку на язык поверх java вместо jvm


                          это про Xtend?
                            0
                            Да да он самый, хотя это наверное к этому топику никак не относится
                    0
                    в java такая фича еще до сих пор под вопросом

                    Неправда. Java 8 даёт возможность использования замыканий вполне себе официально: jdk8.java.net/lambda/
                    По небольшому опыту использования JDK8 могу сразу сказать, что джава очень много приобрела с поддержкой лямбд.
                      0
                      Спасибо за информацию, но согласитесь что до последнего момента не было уверености что замыкания войдут в состав 8 версии и х как то уж усиленно двигали в сторону 9. Кстати не замыкания ли виноваты в сдвиге даты выхода 8 версии по сравнению с объявленными датами сразу после покупки java ораклом?
                        0
                        Вы немного с версиями вроде напутали. Непонятно, какие могут быть сомнения, что лямбды могут не войти в 8ку.
                          0
                          Ну насколько я помну там вопрос стоял ребром, в 7рку не включили а восмерку планировали через год макс и поползли слухи что в связи с плотным графиком возможно… И тогда видимо народ взбунтовался и решили дату выхода 8 версии сдвинуть. Может я конечно ошибаюсь и это только слухи но изменение даты выхода имело место.
                            0
                            Про перенос даты не могу не согласиться, хотя, наверное, я имею в виду немного другое. Я следил за JDK8 внимательно только с конца прошлого года, и там в списке майлстоунов было написано, что релиз (General Availability) будет в мае-июне. Однако около конца февраля-начала марта дата релиза сдвинулась на сентябрь…
                            И ещё странно, что в самом JDK8 лямбды есть уже давно, но нет библиотеки потоков для работы с коллекциями. Зато есть отдельная сборка, в которой эти библиотеки есть.
                      0
                      Вы не путаете closure с function literals (они же lambda expressions)? Замыкания были в Java чуть-ли не с самого начала
                        0
                        Учитывая требование на final (ослабленное с приходом лямбд до effectively final), эти замыкания — не совсем то, что под «замыканиями» подразумевают в других языках.
                          0
                          Ну, функциональные языки как раз поощряют использовать immutable стиль программирования. Так что final, ИМХО, — это даже хорошо
                            0
                            Это было бы хорошо, если бы были требуемые инструменты.

                            Если судить по stackoverflow, то далеко не все так просто могут перейти на чистый функциональный стиль. Для некоторых foldLeft в качестве замены итерирования с сайд-эффектом кажется магией.

                            Но забудем об этом. Считаем, что мы гуру ФП.
                            Допустим вам надо за 1 проход по циклу собрать несколько агрегаторов.
                            В scala это foldLeft с использованием кортежей и pattern metching, в C# это Aggregate с их вариацией на тему анонимных классов.
                            А вот в java это только итерирование с сайд-эффектами. Ибо кортежи без сопоставления с образцом не читаемы, а анонимные классы такого не позволят.
                  0
                  Я в свое время смотрел на Play! но остался на Spring Framework. Причины более мощные и обширные инструментальные средства.
                    0
                    Я вас понимаю.
                    В своё время не смог убедить руководство использовать Play 1.2.x в новом проекте: нужны были расширенные возможности по авторизации и аутентификации не только через web, но и через ldap. Поэтому пришлось остаться на Spring Framework и использовать Spring Security.
                    0
                    Интересная статья, порадовали ремарки к каждому пункту.:)
                    Для себя решил вопрос, который давно волновал: попробовать Play 2.1 для маленьких проектов, как что-то более легкое чем Spring, но как понял рановато, лучше видимо еще проще брать что-то аля Spark или тогда уж с Spring не слазить.
                      0
                      Как что-то более лёгкое, чем Spring, я бы рекомендовал попробовать Grails. Потом сможете и большие проекты на нём писать :) Groovy не так уж и труден для изучения и понимания, а Grails уже давно вырос и готов для реального применения.
                        0
                        Да а вы пробовали веб сокеты хостит на грейлз, он не чуть не легковеснее спринга, скорее наоборот. Оба этих продукта работают только с контейнерами сервлетов, что вас отбрасывает на столетия назад к комете и плохому симулированию асинхронизма. Для малых и простых проектов это некритично.
                      0
                      В Play! есть засада с транзакциями. Если включить DAO поддержку, то на каждый HTTP запрос будет стартовать транзакция вне зависимости от того, используется ли DAO в течении запроса или нет. Покрайней мере так было в версии 1.2.
                        0
                        Плей как раз и не был задуман для работы с dao он предусматривал работу а ля рор с актив рекордом, а уш что там всякие доморощенные умелцы накрутили своими кривыми руками с dao то это на их и собственно ваш страх и риск.
                          0
                          Это поведение из коробки. О каких доморощеных умельцах речь?
                            0
                            В play 1.* нет никакой поддержки dao весь автоматизм реализован для поддержки activerecord паттерна. Далее вы говорите про включение поддержки дао, я не знаю каким способом вы ее включаете но изначально play не предусматривает ничего такого. Вам приходися или все делать руками или же использовать готовый модуль.
                              0
                              Действительно, DAO нет. Но поведение из коробки с транзакциями есть. О них речь. Activerecord или DAO — тут не принципиально.
                        0
                        По поводу двойных кавычек в JSON: так ведь стандарт такой! А то, что всякие парсеры позволяют писать без кавычек как раз плохо, потом разработчики удивляются что их JSON не проходит валидацию.
                          +1
                          По сравнению с 1.x у Play 2 значительно улучшилось управление зависимостями. В Play 1.x есть плагины для maven и ivy но это всё какие то костыли и нормально настроить проект на раз-два всё равно довольно сложно.
                          А вот с SBT (как бы ужастен он не был) в Play 2 всё стало заводиться как раз с пол-пинка — выкачал проект, открыл в IDE — можно работать. Соответственно и релизы стало делать как то проще и логичней.
                            0
                            Верно подмечено. В Play 2 работать с зависимостями стало легче.
                              0
                              Play2.* неплохо интегрируется в maven-проекты
                              cescoffier.github.io/maven-play2-plugin/maven/release/usage.html

                              При желании его можно тем-же мавеном подсобрать в war, чтобы не менять деплоймент, например.
                              Но тогда надо быть аккуратным и помнить про nio и подконфигуривать ваш servlet-container на его поддержку.
                              0
                              Пробовал Play!, но не устроило несколько вещей, которые упомянуты автором статьи и которые оказались для меня наиболее существенными недостатками: скорость компиляции, отсустствие встроенное защиты от CSFR, отсутствие нормальной документации. До работы с БД даже не дошел.

                              Результат: сейчас использую Lift. При изменении шаблонов перекомпиляция не требуется, документация есть (хотя тоже не без проблем, но в Google groups обсуждалось множество вопросов и можно воспользоваться коллективным опытом), защита от распространненных уязвимостей (включая XSS и CSFR) «из коробки», интеграция с squeryl. В общем, после Play! я считаю Lift намного более дружественным к разработчику фреймворком.
                                0
                                Используем play 2.1 в текущем проекте. Так же боремся (почти успешно) с перечисленными трудностями. Из плюсов по сравнению со стандартным JEE — простота разработки и развертывания проекта (особенно радуются этому фронтендеры). Основной недостаток — время (пере)компиляции.

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое