Генетикам известно, что гибриды (помесь разных видов) обладают свойствами своих родителей и физиологически более сильные особи. Такого же эффекта можно добиться и в техники, используя сильные стороны разных технологий. В этой статье я покажу преимущество такого подхода, на примере гибрида Ruby и Java. Информации в инете об этом не так уж и много, я надеюсь прочитав этот пост вы сэкономите пару бессонных ночей в отличии от меня;)
Уж и ёж
И так, за ужа у нас будет Ruby:
Хочу отметить, что сильные стороны я перечислил для языков относительно друг друга, я знаю что Си быстрее, а Java тоже высокоуровневый;)Уж и ёж
И так, за ужа у нас будет Ruby:
- Динамическая типизация;
- Гибкость;
- Высокая скорость разработки;
- Много интересных и вкусных gems;
- Высокая производительность;
- Огромное количество готового кода;
- Полноценный GUI;
- Переносимость;
Продвинутый читатель наверно скажет: "JRuby!!". И будет прав! Но в статье я покажу, как организовать мультиязыковый проект, использовать Java классы в скриптах Ruby и скомпилировать один jar вместе с Ruby и его гемами!
Хорошим, тоном при разработки гибридных проектов будет использовать скритовый язык для организации логики приложения, а низкоуровневые задачи решать уже на быстром статическом языке. И придерживаясь этой идеологии мы напишем маленькое web приложение на Sinatra, которое использует Java класс при обработке запросов!
Реализация
Для начала нам понадобиться JDK (я использую 1.6) и Maven. Для тех, кто не знает это утилита для сборки проекта Java вместе с зависимостями. Похож на bundler в руби, но более развитый - он очень много может за счет большого числа плагинов и в тоже время более сложный в настройке. Для работы нам понадобиться Maven версии 3, со вторым работать не будет! Вот тут как его установить. Теперь нам нужно организовать проект под работу с мавеном:
-\Наш проект
|--pom.xml - файл конфигурации проекта Maven
|--\src
|--\main
|--\java - здесь будут Java часть проекта (дальше идет свободная
| |--\net организация пакетов Java)
| |--\flipback
| |--\usejruby| |--UseJRuby.java - наш главный класс
|--\resources - тут лежат дополнительные файлы, в том числе и скрипты Ruby
|--\scripts
|--test.rb - Ruby скрипт вызывающий
Рассмотрим наш Java класс UseJRuby.java
package net.flipback.usejruby; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.SimpleBindings; @SuppressWarnings({ "restriction", "unused" }) public class UseJRuby { public static void main(String[] args) { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("jruby"); try { engine.eval("require 'rubygems';require 'scripts/test'"); } catch (ScriptException e) { e.printStackTrace(); } } public static String helloFromJava() { return "Hello from Java"; } }Суть очень проста, при запуске программы мы запускаем движок JRuby и выполняем код с подключением скрипта с Ruby кодом, который и выполняет логику приложения. Так же у нас есть статический метод helloFromJava, его и будет использовать скрипт для ответа на запрос. Естественно, мы могли написать его в другом классе, но не написали)
Теперь посмотрим Ruby скрипт test.rb:
require 'sinatra' require 'java' $: << File.join(File.dirname(__FILE__),'..') java_import 'net.flipback.usejruby.UseJRuby' class Server < Sinatra::Base get '/' do UseJRuby.helloFromJava end end Server.run!Обычное приложение Sinatra, один маленький нюанс, в обработке запроса к корню приложения, мы вызываем статический метод Java класса!! Отметим, что для подключения джава класса, на надо определить путь к директории с классами:
$: << File.join(File.dirname(__FILE__),'..')
Конфигурация
Теперь, что бы проект собрать надо сконфигурировать pom.xml файл. Код в студию!
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.flipback.useruby</groupId> <artifactId>usejruby</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Use JRUBY</name> <dependencies> <dependency> <groupId>rubygems</groupId> <artifactId>sinatra</artifactId> <version>1.2.6</version> <type>gem</type> </dependency> <dependency> <groupId>org.jruby</groupId> <artifactId>jruby-complete</artifactId> <version>1.6.3</version> <type>jar</type> <scope>compile</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>de.saumya.mojo</groupId> <artifactId>gem-maven-plugin</artifactId> <version>0.28.3</version> <extensions>false</extensions> <configuration> <script> require 'rubygems' require 'scripts/test' </script> </configuration> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>net.flipback.usejruby.UseJRuby</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies-with-gems</descriptorRef> </descriptorRefs> </configuration> <dependencies> <dependency> <groupId>de.saumya.mojo</groupId> <artifactId>gem-assembly-descriptors</artifactId> <version>0.3</version> </dependency> </dependencies> </plugin> </plugins> </build> <repositories> <repository> <id>rubygems-releases</id> <url>http://gems.saumya.de/releases</url> </repository> </repositories> </project>Кода много, но не бойтесь я вами)) И так по частям. Описательная часть нашего проекта:
<groupId>net.flipback.useruby</groupId> <artifactId>usejruby</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Use JRUBY</name>Тут все просто и понятно. Отметим, что все зависимости, библиотеки и плагины имеют свой идентификатор aritfactId, по нему maven найдет его в удаленном репозитории и скачает в локальный. Т.е. устанавливать кроме Mavenа нам ничего не нужно, он сам скачает все что требуется. Дальше плагины:
gem-maven-plugin
Плагин для работы с RubyGems - это гвоздь программы. Именно он позволит
использовать гемы и установит их в проект. Обратите внимание на секцию <script> в ней мы пишем тоже, что и в нашем Java классе. Дело в том, что когда мы соберем проект в jar пакет, он будет запускаться из UseJRuby.class, а при разработке мы можем запустить программу с помощью команды:
$mvn gem:exec
Котрая и выполнит код из секции
<plugin> <groupId>de.saumya.mojo</groupId> <artifactId>gem-maven-plugin</artifactId> <version>0.28.3</version> <extensions>false</extensions> <configuration> <script> require 'rubygems' require 'scripts/test' </script> </configuration> </plugin>
maven-assembly-pluginПлагин для сборки проекта в один jar вместе с зависимостями и гемами. С помощью него мы и соберем приложение и отправим моей маме, она его сможет запустить)) Здесь мы указали, класс для запуска net.flipback.usejruby.UseJRuby, а также указали, что собирать нужно вместе с гемами. Поддержку гемов обеспечивает расширение gem-assembly-descriptors, которое мы прописали в зависимостях.<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>net.flipback.usejruby.UseJRuby</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies-with-gems</descriptorRef> </descriptorRefs> <dependencies> <dependency> <groupId>de.saumya.mojo</groupId> <artifactId>gem-assembly-descriptors</artifactId> <version>0.3</version> </dependency> </dependencies> </plugin>Так с плагинами все! Теперь остались зависимости:
<dependencies> <dependency> <groupId>rubygems</groupId> <artifactId>sinatra</artifactId> <version>1.2.6</version> <type>gem</type> </dependency> <dependency> <groupId>org.jruby</groupId> <artifactId>jruby-complete</artifactId> <version>1.6.3</version> <type>jar</type> <scope>compile</scope> </dependency>
</dependencies>Тут мы прописали, что нам нужен гем под названием sinatra и сам JRuby.
Для гемов нам нужно указать репозиторий:
<repositories> <repository> <id>rubygems-releases</id> <url>http://gems.saumya.de/releases</url> </repository> </repositories>С конфигурацией покончено. А чуть не забыл!! Для работы с плагином gem-maven-plugin пропишите в настройках mavena файл settings.xml:
<pluginGroups> <pluginGroup>de.saumya.mojo</pluginGroup> </pluginGroups>
Сборка
Теперь попробуем запустить проект. Для этого вводи 2-е команды:
$mvn compile #компиляция проекта
$mvn gem:exec #запуск программы
Не пугайтесь, что maven начнет много качать из интернета. Он загружает дерево зависимостей только для первого запуска программы. Если все хорошо, то запустится приложение синатры и при переходе по ссылке http://127.0.0.1:4567/ увидите приветствие из Java класса. По моему это очень круто)
Теперь сборка в jar архив:
$mvn assembly:assembly
После успешного завершения в директории target вы найдете файл с длинным названием sejruby-0.0.1-SNAPSHOT-jar-with-dependencies-with-gems.jar , который включает в себя JRuby и Sinatra и может запускаться везде, где есть JavaRuntime.
П.С.
Комментариев нет:
Отправить комментарий