Прошли те дни, когда целые компании зависели от одного поставщика технологий. Даже маленькие фирмы и любители найдут оптимальное для себя решение, объединяя технологии в одном проекте. Долгое время Java держала первенство среди серверных технологий. Но сегодня Node.js повсюду.



Но даже с ростом популярности Node.js и JavaScript, Java не теряет силу. Кроме того, немногие организации могут позволить себе перенести всю платформу с JVM на Node.js. Это значит, что компания должна либо продолжать использовать текущий стек технологий, либо запускать несколько стеков, которые будут общаться через сетевое API. Однако есть и другой способ: запустить Node.js прямо в процессе JVM. И J2V8, наконец, сделала это возможным.


J2V8



J2V8 это набор коннекторов к V8 для Java. J2V8 упаковывает V8 как динамическую библиотеку и предоставляет Java API для V8 через Java Native Interface (JNI). С J2V8 Вы можете выполнять JavaScript используя V8 также, как если бы использовали Rhino или Nashorn.


Изначально J2V8 был разработан для предоставления высокопроизводительного JavaScript в Tabris.js, кросс-платформенной мобильной библиотеке.


За последние месяцы я настраивал сборку Node.js как динамической библиотеки и обеспечивал взаимодействие с Java API для неё. Теперь вы можете выполнять скрипты для Node.js прямо из Java. В отличии от прочих решений, которые пытаются реализовать Node.js используя другие движки, это настоящий Node.js со всеми багами и возможностями. Node.js запускается в том же процессе что и JVM и всё взаимодействие происходит синхронно через JNI.


Совместное использование Node.js и JVM


J2V8 предоставляет API для выполнения скриптов в Node.js, вызова функций JavaScript из Java и наоборот, подключения NPM модулей и запуска очереди сообщений Node.js. Все модули ядра Node.js также присутствуют.


Запуск Node.js на JVM позволяет легче провести миграцию для любого, кто использует большой Java стек, но хочет начать использовать Node.js. Например, Вы можете запустить на Node.js сервер (такой как Express.js) и вызывать существующие методы Java для обработки запросов.


static String NODE_SCRIPT = "var http = require('http');\n"
  + ""
  + "var server = http.createServer(function (request, response) {\n"
  + " response.writeHead(200, {'Content-Type': 'text/plain'});\n"
  + " response.end(someJavaMethod());\n"
  + "});\n"
  + ""
  + "server.listen(8000);\n"
  + "console.log('Server running at http://127.0.0.1:8000/');";

public static void main(String[] args) throws IOException {
  final NodeJS nodeJS = NodeJS.createNodeJS();
  JavaCallback callback = new JavaCallback() {

    public Object invoke(V8Object receiver, V8Array parameters) {
      return "Hello, JavaWorld!";
    }
  };

  nodeJS.getRuntime().registerJavaMethod(callback, "someJavaMethod");
  File nodeScript = createTemporaryScriptFile(NODE_SCRIPT, "example");

  nodeJS.exec(nodeScript);

  while(nodeJS.isRunning()) {
    nodeJS.handleMessage();
  }
  nodeJS.release();
}

NPM


Вдобавок к вызову существующих методов Java из Node.js, J2V8 предоставляет возможность вызывать JavaScript функции (в том числе NPM модулей) прямо из Java. С такой интеграцией, Java пользователи могут сразу начать использовать NPM модули прямо в JVM. Например, Вы можете использовать jimp для обработки изображений в Java.


public static void main(String[] args) {
  final NodeJS nodeJS = NodeJS.createNodeJS();
  final V8Object jimp = nodeJS.require(new File("path_to_jimp_module"));

  V8Function callback = new V8Function(nodeJS.getRuntime(), new JavaCallback() {    
    public Object invoke(V8Object receiver, V8Array parameters) {
      final V8Object image = parameters.getObject(1);
      executeJSFunction(image, "posterize", 7);
      executeJSFunction(image, "greyscale");
      executeJSFunction(image, "write",  "path_to_output");
      image.release();
      return null;
    }
  });
  executeJSFunction(jimp, "read", "path_to_image", callback);

  while(nodeJS.isRunning()) {
    nodeJS.handleMessage();
  }     
  callback.release();
  jimp.release();
  nodeJS.release();
}

Подключение J2V8


Интеграция с Node.js уже доступна в J2V8 (версия 4.4.0). Вы можете использовать ее на Windows (32-х и 64-х разрядных), MacOS и Linux (64-х разрядных). Используйте следующую зависимость в pom, чтобы получить ее из Maven Central (этот пример для Windows 64-х, не забудьте поменять для других платформ):


<dependency>
  <groupId>com.eclipsesource.j2v8</groupId>
  <artifactId>j2v8_win32_x86_64</artifactId>
  <version>4.4.0</version>
</dependency>

От переводчика


J2V8 дает нам новый уровень абстракции, позволяющий выбрать наиболее подходящую технологию для каждой отдельной задачи в рамках целого проекта. Как разработчика меня всегда привлекала надежность Java и удобство Node.js. И, в скором времени, надеюсь, мы увидим примеры успешных проектов, сочетающих в себе лучшее из двух миров.

Поделиться с друзьями
-->

Комментарии (31)


  1. Sasha_Pitenin
    16.08.2016 20:21
    +1

    Возникает большой вопрос, а зачем нужны такие извращения? Ну если нужно общаться между приложениями можно использовать сокеты! А про потребление памяти вообще кто нибудь думал, что в nodejs утечки большие, что в jvm?! ИМХО


    1. kirill89
      16.08.2016 20:37

      Согласен, извращенность в этом есть, хотя я бы скорее назвал это непривычностью. Общение через сокеты подразумевает ряд усложнений, нужен интерфейс взаимодействия, нужно настраивать окружение, следить за ошибкам и падениями в разных местах, обрабатывать ситуации когда один из сервисов недоступен. Автор предлагает более простой способ интеграции. Хотя, конечно, всё зависит от конкретного проекта.


    1. crackedmind
      16.08.2016 21:16

      Лучше jvm внутри node.js запускать :)


      1. Antelle
        16.08.2016 23:01

        Кто-то даже сделал...


        1. crackedmind
          17.08.2016 02:53
          +2

          Ну елки, хотел пошутить, а тут и даже это есть


    1. lucky_libora
      18.08.2016 22:04
      +1

      часто наблюдаю статьи, где описывается следующая архитектура:

      нода выступает в качестве фронтенд-сервера (рендерит вьюшки, собирает данные с бэкенда), а бэкенд (который был написан 5 лет назад программистом, который уже сменил работу) остается прежним


  1. Trans00
    16.08.2016 21:26
    +3

    Я могу понять людей, которые хотят перестать писать серверную часть на Java (хотя сам к ним не принадлежу), но выбор Js как языка, заменяющего Java, откровенно спорный, по крайней мере для меня.
    Если у вас команда Js разработчиков, то все понятно, но зачем тащить Java рантайм и плюс к тому писать прокладки и подкладки на неродной Java, а если, наоборот, нужен сервер в JVM, но без Java, то кроме очевидных вариантов Groovy, Scala, Kotlin и т.д. есть довольно зрелые проекты, вроде JRuby.
    Но мир велик, если у кого-то есть реальый юзкейс или был юзкей под который хорошо бы лег J2V8 — поделитесь=)


    1. vermilion1
      16.08.2016 21:52

      Например, существует старое веб-приложение. Его новая клиентская часть написана на React, но у этого нового подхода есть один жирный минус — весь рендеринг происходит на клиенте и пользователи ненавидят ждать целых полсекунды, пока все отрендерится и спиннер уйдет с экрана.
      Тут на помощь приходит сервер-сайд рендеринг при помощи J2V8.
      Почему попросту не инсталлировать Node.js? А потому что приложение устанавливается на сервера клиентов, убедить которых в том, что им нужен Node.js настолько сложно (и, возможно, чревато потерей тех самых клиентов), что проще использовать J2V8.


      1. vsb
        17.08.2016 00:20
        +1

        Вопрос в том, зачем нужен J2V8, если в Java есть своя реализация JavaScript, по отзывам достаточно быстрая.


        1. kirill89
          17.08.2016 00:48

          Вопрос не в скорости, а в совместимости. Плюс Node.js несколько шире чем просто JavaScript, посмотрите список модулей, которые есть в его ядре.


          1. sshikov
            17.08.2016 14:06

            А вот кстати насчет совместимости. Я понимаю, что Rhino возможно достаточно устарел, по сравнению с V8, а вот Nashorn? Там по-идее ECMA 5.1, этого недостаточно, чтобы запустить Node?


            1. vsb
              17.08.2016 17:16
              +1

              Я видел статью, где человек на Java 8 использовал React для серверной отрисовки. Скорее всего для любого разумного применения будет достаточно. Ну и транспилеры всякие никто не отменял.


            1. vgoloviznin
              17.08.2016 23:45

              Node это АПИ поверх V8, другие движки именно нодой не запустишь. Но есть и другие сервера на JS, может их и можно будет запустить


              1. sshikov
                18.08.2016 11:47

                Погодите, с чего это вдруг только V8, когда вот же другой движок — https://github.com/nodejs/node-chakracore?


                Про другие сервера я в курсе, серверного JS в природе полно, в самых неожиданных местах. Хоть я и не фанат такого подхода — но для некоторых задач это удобно.


                1. vgoloviznin
                  20.08.2016 11:32

                  Все-таки, это официально не поддерживаемый аддон к обычной ноде, который, как написано у них в гитхабе является шимом для апи к V8


                  Ну и фраза с оф. сайта ноды: Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.


      1. HoHsi
        18.08.2016 14:19
        +1

        А почему бы просто не сделать отдельный сервер для темплейтов и отдельный для API? Пусть ваш старый-проверенный API бегает на Java'е, а рендеринг React сделать на Node, и просто проксировать соответствующие URL'ы любым прокси сервером (а то и вообще написать фронт с учетом, что у вас 2 сервера)


    1. evkin
      17.08.2016 00:25
      +1

      Я определенное время назад искал именно такое решение. Мне в одном java приложении необходимо было запустить трансляцию jade. Существующая реализация jade на чистой java мне не подошла. А то что я нашел для работы node в jvm выглядело печально. Было несколько проектов, но они не развивались и поддерживали только древнюю версию ноды. Пришлось извращаться через запуск процесса ноды из приложения со скриптом враппером, с которым программа общалась через именованный канал. Оно конечно работает… как то)) Но в ближайшее свободное время я полезу копаться в J2V8 для оценки интеграции его в этот проект. И есть надежда что мне это развяжет руки в интеграции гулповых тасков в java приложение. Тогда я вообще буду доволен как слон))


  1. stepanp
    16.08.2016 23:21
    -11

    Просто комбо говняных «технологий»


    1. deniscute
      17.08.2016 19:01
      +1

      технологии неплохие, но по отдельности, по крайней мере в текущих их реализациях.


      1. stepanp
        17.08.2016 23:00
        -2

        Не могу с вами согласиться


  1. ExplosiveZ
    16.08.2016 23:28
    -4

    Это самое ужасное, что я видел в своей жизни. Смесь из строго типизированного языка и JS.
    Как быть с типами? Object'ами общаться?


  1. AndreyRubankov
    17.08.2016 08:07
    +1

    Запуск Node.js на JVM позволяет легче провести миграцию для любого, кто использует большой Java стек, но хочет начать использовать Node.js. Например, Вы можете запустить на Node.js сервер (такой как Express.js) и вызывать существующие методы Java для обработки запросов.

    Интересно каким образом это облегчит миграцию?

    Если у вас какой-то javaEE сервер, допустим TomCat — вам нужно будет задеплоить в него этот javaj-express-js и это уже будет Веб-сервер внутри веб-сервера. Чтобы уйти от EE монстра создадим еще большего монстра.

    А для маленьких standalone серверов нету смысла использовать такой подход, легче будет сразу переписать все на node.js и не заморачиваться.

    Указанный подход лишь породит ошибки, которые не свойственны ни js, ни java, которые будут где-то на стыке и которые никак не отловить. Кроме того, производительность такого решения будет хуже чем чистое JVM или чистое Node.JS решение, JNI вызовы дорогие и они плохо отпимизируются.


  1. AndreyRubankov
    17.08.2016 08:15

    Указанная реализация больше похожа на попытку запустить express.js на jvm и проверить производительность. Или для попытки сделать более простым написание нативного кода, чтобы повысить производительность. Но никак не для того, чтобы предоставить мост для миграции с java на js.


  1. zag2art
    17.08.2016 12:59

    Осталось только java запустить в node.js и все будет ок.


    1. yaroslavgaponov
      17.08.2016 14:25
      +1

      это возможно node-jvm


    1. trikadin
      17.08.2016 15:00
      +1

      Выше писали — уже есть.


      1. yaroslavgaponov
        17.08.2016 16:47

        Выше мост между node.js и java. А это реализация виртуальной машины jvm.


  1. AstarothAst
    17.08.2016 16:58

    Особенно здорово будет отлаживать и править js код созданный путем конкатенации java-строк…


  1. Sirion
    18.08.2016 09:01
    +2

    Астрологи объявили неделю J2V8, Количество людей, путающих Java и Javascript, увеличится вдвое.


  1. AlexZaharow
    18.08.2016 10:45
    +1

    Поскольку каждая библиотека пишется под свою среду, то иногда всё-таки очень удобно заграбастать что-то, написанное на javascript, php, python и других языках https://en.wikipedia.org/wiki/List_of_JVM_languages. По мне так это просто здорово, что я могу взять что-то на javascript и использовать в java. Единственную проблему, которую я вижу — отладка такого кода. Но для JavaScript эта проблема решена в Idea: https://blog.jetbrains.com/idea/2014/03/debugger-for-jdk8s-nashorn-javascript-in-intellij-idea-13-1/ а вот для Eclipse всё никак не сделают. Есть ли отладчики для других языков пока не слышал, но направление хорошее.


    1. AndreyRubankov
      20.08.2016 11:46

      Использовать библиотеку для js поверх jvm — звучит хорошо!

      Но ведь для этого есть все тот же nashorn и еще парочка других движков. Для использования js библиотек не нужно затягивать целую node.js экосистему в jvm.

      А если все же по какой-либо причине нужно использовать библиотеку, которая работает только под node.js — лучше уже поднять node.js отдельно и настроить общение через какой-то канал связи (сокеты, вебсокеты, http, message queue). Но это уже пахнет проблемой в архитектуре.