Собрана внешняя компонента которая позволяет запускать виртуальную машину java в среде 1С. Позволяет как передавать параметры в java — так и получать уведомление через externalevent.
Предпосылкой создания являлся тот факт, что есть много готового функционала которого не хватает в 1С. Язык сpp — довольно сложен для быстрой разработки, и теперь возможно использовать готовые сборки java классов (так называемые jar-файлы) для использования в 1С.
Собрана только под Windows 32-bit и 64-bit!
Компонента позволяет запускать виртуальную машину Java в 1С, загружать необходимые jar – библиотеки, а так же выполнять методы.
GITHUB репозиторий: JVM-plugin
В примере собранный jar-файл с двумя классами:
- первый пример вычисляет факториал и выводит в лог строку;
- второй пример вычисляет расстояние Левенштейна для двух строк;
- загрузка файла — по имени файла возвращает двоичные данные;
- "скриншот" — возвращает скриншот экрана в виде двоичных данных.
Также запускались различные библиотеки, эмуляторы и прочее. Проверялась работа в асинхронном режиме.
Ограничения:
-
Виртуальная машина запускается один раз и может быть запущена только в одном экземпляре;
-
После завершения работы виртуальная машина не может быть повторно запущенна;
-
Разрядность виртуальной машины должна соответствовать разрядности 1С;
-
Добавлять jar-файлы после запуска JVM нельзя;
-
Обновить java классы после запуска JVM нельзя;
-
Возможны проблемы с повторным запуском javafx — приложений.
Для работы необходима установленная JDK 8
- Первый параметр JAVA_HOME путь к JDK (32-bit или 64-bit в зависимости от клиента 1С);
- Второй так называемый CLASSPATH — путь к jar библиотекам.
- Для корректной работы необходимо установить переменную среды: JAVA_HOME
В архиве приложена конфигурация и собранный(подписанный) jar-файл.
Пример работы с компонентой:
Работа в клиент-серверном варианте в СКД:
Написание плагина для Kafka (Simple Consumer)
Kafka producer + consumer — параллельно.
А пример кода 1С:Предприятие (типа пример использования) можно добавить в публикацию?
(1) Компонента находится в стадии разработки
Показать
Далее вызываем метод и передаем имя java-класса который будет исполнять работу.
(2)Спасибо! А параметры?
(3) Само апи пока не закончено. То есть передавать параметры можно — но в демо примере такого нет.
Разница между 1С и java слишком большая и скорее всего придется подготовить некоторый набор вариантов вызова:
LaunchInJVM — без параметра
LaunchInJVM_S с одним параметром типа строка
LaunchInJVM_SS с двумя параметрами типа строка
Какой кейс у этого?
Под линухами взлетает?
(5) возможность использования многочисленных java библиотек
(6) пока должным образом не проверял — сейчас апи наладить бы
Обновил пример.
Поправил api — на текущий момент возможно вызывать передавая до 2-х параметров. Эти функции синхронные — то есть 1С ожидает завершения выполнения методов.
ОбъектВК.LaunchInJVM(<ИмяКласса>); — без параметров
ОбъектВК.LaunchInJVMP(<ИмяКласса>,<Параметр>); — с 1-м
ОбъектВК.LaunchInJVMPP(<ИмяКласса>,<Параметр1>,<Параметр2>); — с 2-мя
Типы параметров: строки, числа, булево. На основании типов параметров ищется метод в java ну и вызывается собственно.
Кейсы самые разные: что то вычислять (работает JIT-компилятор, поэтому шустро), создавать дополнительные окна (работает swing, awt) с информацией, чаты, да что угодно в общем то.
(9) Можно просто XML с параметрами передать. Будет один метод.
(10) иногда все же удобней хотя бы 2…например передать бинарные данные и строку, все же лучше чем конвертировать в xml, а потом распаковывать в java
(6) Потестил чуть больше — взлетает, по крайней мере виртуальную машину удалось завести (на 32-битах). Думаю проблем особых не будет.
Остальной код надо портировать и проверять
Добавлены функции возвращающие байтики:
CallFInJVMB — без параметров
CallFInJVMBP — с одним параметром
CallFInJVMBPP — с двумя параметрами
Для примера:
CallFInJVMB — ОбъектВК.CallFInJVMB(«ScreenShot»); получение скриншота экрана
CallFInJVMBP — ОбъектВК.CallFInJVMBP(«GetFile», ПутьКФайлу); чтение файла
Вот такое в java — 2 строки и никакой возни с cpp
Скриншот уложился в 5 строк
p.s. Вот и преимущества java — работает из коробки, никаких плюсов (которые с++) и кроссплатформенно
p.s.s. Архив обновлен
В файлы добавлен bouncy castle provider — который надо распаковать в JAVA_HOMEjrelibext\r
Можно скачать самостоятельно
Java код
Показать
а как на счет варианта, чтобы компонента работала на linux сервере где и запущен сервер 1С, чтобы пользователи не заморачивались с жавой?
(15) Под линукс ещё не портировал — да и на сервере не тестил.
Java это не только утилити возможности…
Визуализация полезна: для производства или склада можно отображать 3d модель по нажатию кнопки, отображать графики показателей(оборудования или ещё чего)…
Тот же пдф-повернуть? Зачем кидать на сервер(с сервера) сотни мегабайт, если локально за секунды получим результат?
В общем случае — не важно…есть инструмент, а как им работать каждый решает сам для себя
Наглый вопрос — Открытый репозиторий у компоненты есть?
Хм, интересьненько. 🙂
(17) нет
Обновил примеры:
Можно открывать 3d модели(формат obj), вращать, приближать-удалять
Для всех стесняющихся — добавлено видео
Добавлен возврат строк из вызовов, архив обновлен.
Для примера используется распознавание ШК из картинки и возврат ШК в виде строки.
в java
Показать
Вещь интересная, под Linux бы пользовалась спросом)))
(23) сомневаюсь…доля windows юзеров значительно больше — а спроса нет
Правильно ли я понял, что это аналог .NET Bridge для 1С от Elisy, только под Яву?
Это не полноценный мост…
Изначально позиционируется как замена внешних компонент на c++.
Концепция с созданием классов как в .NET bridge — но в 1с — мне не нравится.
А так написал полноценный код на java -> потестил -> упаковал и все запускается и в 32 и 64 битном режиме без танцев с бубнами.
Добавлено видео по работе с СКД в клиент-северном варианте.
Использовалась стандартная консоль СКД (разрешен вызов функций из общих модулей) на управляемых формах:
В вычисляемые поля добавлено ВызватьJavaКлиент(«CompareDouble», Числа,&Поиск) — что приводит к вызову java функции с передачей параметров и возвратом результатов.
Получаем вычисляемое поле с расстоянием Левенштейна в консоле СКД
p.s. для 12000 строк, вызов функции происходил 36000 раз за 6,38 сек. на сервере
В публикацию добавлен пример написания простейшего плагина для чтения из Apache Kafka.
Архив обновлен, вместе с получателем добавлен демо-издатель Kafka.
Прежде чем тыкать в Кафку, необходимо запустить зукипер и кафка-сервер, иначе будете ждать подключения…
По нажатию на «Send to Kafka» — будет отправлено 10 000 пронумерованых сообщений на сервере (асинхронно). При ожиданиях между отправкой более 10 секунд издатель отправляет сообщение «Producer closed» и закрывается
По нажатию на «Load from Kafka» — будет получено либо 500 сообщений с начала партиции (если пустое поле данных), либо произойдет ожидание 5 секунд для получения данных.
Оба и издатель и подписчик обмениваются данными через топик «testTopic»
Перформанс:
1С + java — 3696 сообщений/сек
Вызов без 1С на java — 36554 сообщений/сек
Путем нехитрых манипуляций удалось ускорить издателя до 8-10 тысяч сообщений в секунду.
p.s. Архив обновлен
p.p.s. К сожалению количество сообщений пришлось увеличивать до 20 тысяч что бы замерить скорость…так что жать кнопку «Load from Kafka» придется в два раза больше
Очень круто. А какой-то полноценный стабильный релиз, который в проде можно использовать, есть?
(31) в проде не использовал, но сомневаюсь что могут быть какие то серьезные проблемы.
Планировал выложить в опенсорс, но надо причесать исходники. А на это надо найти время.
(32) А может ну его — причесывание — и выложить как есть 🙂 ? Уж очень завораживающая вещь получилась. Просто думаю нашлись бы люди которые занялись и причесыванием и развитием.
(33) я не первый раз выкладываю…что то энтузиастов не находилось.
По факту мне надо убрать код проверки сертификата для паблика.
(34) Так. Нет времени объяснять 🙂 Что я могу сделать чтобы вы выложили исходники в public ? 🙂
Не получается воспроизвести примеры. Выдается сообщение «JVMLauncher : Cannot find class.». Можете подсказать что не так делаю?
(36) Отвечаю сам же. Подключил папку subst-ом как диск d: и положил в нее Runner-0.0.1-SNAPSHOT.jar
После этого пример заработал 🙂
Все верно. jar файлы загружаются из classpass(library dir)
Исходники надо очистить от сертификата. Если все срочно — напишите в личку, соберу индивидуально
(29) На видео у вас в обработке еще нет команды Send to Kafka. Но в cf-ке в публикации уже есть. В файловом варианте, чтобы добиться выполнения команды send to немножко исправил текст команды:
Показать
Подскажите, не по этому (https://dzone.com/articles/running-apache-kafka-on-windows-os) примеру все настраивали? 🙂
(29) Все отлично работает. Спасибо!
Ну и исходники Runner-0.0.1-SNAPSHOT.jar было бы бесценно скачать за SM вместе с выложенным примером. 🙂 Подхватить-то удается конечно, но жалуется что Source not found 🙂
Глупый вопрос — а зачем подписывать jar файлы?
(42) затем, что демокомпонента проверяет подпись и не дает выполнить неподписанный код.
Практически все исходники есть тут в качестве комментариев. Да и в любой ide можно глянуть…ничего там нет секретного)
Еще вопрос — а предполагается развитие API? Чтобы все-таки можно было вызывать public методы java согласно их сигнатур? Еще вопрос: если, например в пакете в классе есть метод который возвращает значение типа другого класса, то можно ли помещать такое значение в переменную кода 1С и затем передавать в качестве параметра другому методу java-класса? Понимаю что можно это обойти создав, например void метод-обертку, который будет выполнять эту же операцию в самом java классе, но все-таки. Есть какие-то планы на этот счет?
Не вижу никакого смысла в вызове…ни скорости ни удобства.
Апи планируется править, но точно не в эту сторону.
Более рационально использовать как дополнение к native api — когда весь код заранее можно протестировать, а в 1с уже полноценно использовать
Добрался до компа…
Просто создавая объекты java, вызывая методы мы теряем во всем.
По сути вы хотите тот же Elisy.Net Bridge только на java.
плюсы:
— не надо собирать jar файлы
— можно писать код типа на java
минусы:
— в 99% случаев все равно потребуются какие то библиотеки, и одно дело когда мы собираем так называемый UberJar — со всем вместе( а там и включаем свои классы), другое что нам придется прописывать все jar файлы ручками и следить за их версиями…
— не возможно полноценное тестирование перед заливкой в 1С — юнит тесты и прочее проще организовать в java, а там и гит и все остальное из коробки.
— сами себе режем производительность: interop вызовы не бесплатны, чем реже прыгать java -> 1C -> java и т.п. тем выше скорость решения
— теряем в функциональности java — многие конструкции станут недоступны: try-with-resources, multicatch, case и т.п. это как вернутся в каменный век 🙂
KafkaExampleProducer.java
предпосылки:
1. демо пример
2. получить максимум производительности за минимально затраченное время на разработку
Когда происходит вызов 1С, никакой отправки на самом деле не происходит, вместо этого:
при каждом вызове проверяется java-поток на наличие, и если его нет происходит запуск
при каждом вызове в очередь сообщений кладется сообщение
Java-поток берет на себя обязательства по отправке сообщений, опустошает очередь отсылая сообщения, при отсутствии 10 сек сообщений отключается
p.s. код написан на коленке, скорее всего с ошибками, не безопасен, но работает очень шустро. По идее подобный код можно использовать для логирования событий, когда незначительную часть сообщений можно потерять.
p.p.s На деле довольно таки стабильно отсылал сообщения. В прод не рекомендовал бы…но в свое время не выложил текст.
(46) 🙂 Да, ступил. Это я уже потом и сам сообразил. Не столь развернуто правда 🙂
(47) У меня ситуация такая что есть уже готовый профессиональный и отлаженный блок на Java для взаимодействия с Kafka и встала задача дотянуться до него из 1С-ки. Будем пробовать окучить сие с помощью компоненты.
Исходники доступны всем желающим
Существующий пример Kafka-получателя имел существенный недостаток.
https://www.youtube.com/watch?v=jMl66aurQeI
При каждом получении данных происходило подключение и отключение к кафке, что вызывало дополнительные задержки связанные как с сетевым взаимодействием так и с ребалансировкой группы получателей.
Решение такое же простое как и с отправителем -> запускаем поток который будет закрывать получателя после продолжительного интервала.
Записал видео где два 1С клиента успешно общаются…
Скорость конечно не супер, но 80001 сообщение со скоростью 2600 сообщений/сек доставлено(в видио есть вывод статистики по отправителю).
Проверил в асинхронном режиме…вполне себе удобно.
Да, и теперь классы можно адекватно раскладывать по пакетам…kafka.Consumer, kafka.Producer, kafka.ProducerMetrics
(51) А Kafka разве сама (сам) не отслеживает активность consumer-ов? Т.е. там если не хочешь влететь в ребалансировку надо непрерывно опрашивать. Ну дык на то она и «потоковая работа с данными» как я понимаю.
(52) JVM — живет столько сколько живет процесс rphost
Kafka выкинет только если heartbeat — перестанет поступать…а что ему не поступать если Consumer так и останется запущенным и будет отправлять heartbeat.
например:
у нас 2 rphost-а(2 сервера или 2 процесса):
на rphost#1 запустилось регламентное задание, запустился consumer#1, стал лидером — получил сообщения и ждет еще вызова из 1С…но в 1С регламентное задание завершилось. Неважно по какой причине…получены все сообщения или только определенный batch(1000 сообщений и хватит). JVM — продолжает работать, consumer#1 все так же сидит в лидерах и ждет от 1С приказов.
на rphost#2 запускается регламентное задание, запустился consumer#2 ( другой процесс, другая JVM) и ждет пока станет лидером…и тут вопрос в kafke — когда и вообще сделает ли она ребалансировку consumer-ов так, что бы consumer#2 стал лидером и начал получать сообщения для регламентного задания на rphost#2.
Решения два:
1. со стороны 1C — закрывать consumer при завершении регламентного задания.
минусы:
если регламентное задание отрабатывает маленькими пачками и часто, будут переподключения к кафке и создания новых consumer-ов
плюсы
железно подключаемся одним consumer-ом
2. со стороны java — закрывать consumer в другом потоке по истечении какого то интервала со времени последнего вызова.
минусы:
надо подбирать интервал согласно скорости обработки, если он будет меньше скорости обработки — consumer-ы переподключатся.
Например 1С обрабатывает пачку за 10 секунд — можно поставить интервал в java 15 секунд(с последнего вызова). Если 1С затупит — старый закроется , создастся новый Consumer — совершенно без дополнительных телодвижений.
плюсы
если регламентное задание запускается чаще интервала, consumer будет переиспользоваться.
Скачал либы, начал тестить, и есть несколько моментов. (64 разрядка)
Небольшой итог по тому в чем удалось разобраться и чего тут не описано.
1) в классе в яве который подключаем должен быть публичный статик метод(функция) mainInt()
2) не удалось запустить не подписанный jar файл
3)при попытке передать параметры говорит что «много фактических параметров»
4) подписать jar файл пока не удалось
Что пробовал делать я
1) Создал хелоу ворлд свой на яве, вывел в отдельный класс, пишет что класс не найден.
2) с прилоденным архивом пока тоже не получилось пораьотать, выходит ошибка но уже говорит «mainInt» т.е. класс находит, наверно дело в подписи jar файла
Что делаю не так и какие еще есть нюансы использования dll?
Качал последний архив, самый свежий.
(55)
Во… чуть стало понятнее, как вызывать с параметрами и без, но у меня теперь вот такая штука выходит
Так я подключаюсь.
Показать
(56)
Всё получилось, была путаница с методами, теперь вроде всё понял.
Будем дальше тестить и что то изобретать))))
Спасибо, за пояснения.
Было бы классно если бы в публикацию добавили про вызов процедур и функций явы через 1с, а то путаница идет.
И последний вопрос, как много можно передавать параметров?
Поддерживаются только примитивные типы? (про массив и структуры пока можно мечтать или даже мечтание не поможет?))))
(57)
В функцию можно до 4-х параметров, в процедуру можно до 2-х…
Возможно увеличить если будет необходимость
Ни массивы, ни структуры — сама 1С не даст отправить…точно работают строки, числа (int ,float, double)
Возможен только возврат массива байт в Бинарные данные:
Все остальное только через сериализацию ЗначениеВСтрокуВнутр…
(58)
Дополню одной идеей, не знаю насколько это профитно,но…
Как мне кажется удобнее будет переделать вызов класса и метода примерно вот так (Runner.getAll, , )
т.е. пишется класс, а потом через точку метод который необходимо вызвать, чтобы не привязываться исключительно к mainInt
ну или как то по другому реализовать, но суть в том чтобы можно было явно указать метод который необходимо выполнить, ну и через запятую параметры для метода.
вдруг в классе будет 2 и более метода которые можно выполнить, а то получается одна точка входа, а тут уже появляется выбор…
да и городить тогда классы под каждый метод не надо будет.
(59) идея нормальная…
Возможно реализовать альтернативным апи: ClassFunctionCall, ClassFunctionCallP,ClassFunctionCallPP
По сути надо стандартизировать апи, а то сейчас есть разброс в именовании…
Проще отправлять прямиком предложения в репо:https://github.com/MinimaJack/JVM-plugin/issues
(59) Добавлено
Вызовы эквивалентны
time.utils — package
Current — class
mainInt — имя метода
Тип Даты работает и в параметрах и в возвращаемом результате, с учетом адекватности на вхождение в unixtime интервал.
(61)
Огонь,а есть аналогичное для процедуры?