Быстрая разработка и развертывание приложения инвентаризации хранилища медицинских/биологических лабораторий в виде адаптивного одностраничного приложения (SPA).

…используя AngularJS/Restful Services/MongoDB.

Здравствуйте, я опытный инженер-программист/разработчик веб-приложений, который занимается разработкой с использованием устаревших фреймворков, включая JSP, технологии просмотра JSF (недавно Spring Thymeleaf) с Spring MVC, сервисы Rest, реляционные базы данных для сохранения данных и многое другое. В начале года, в прошлом году, я решил, что пришло время немного запачкать руки одним из новых фреймворков javascript (AngularJS), с которым я играл, но никогда не работал над веб-приложением на работе, которая требовала его использование. Я также хотел заново привыкнуть к использованию хранилищ данных NoSQL, а именно Mongodb. Я работал с Mongodb два года назад в инженерной стартап-компании, поэтому знаком с ней. Кроме того, кажется, что это популярный выбор по многим причинам, которые я не буду сейчас углублять в этом блоге.

Итак, вот и начинается мой путь по этой дороге. Ранее в этом году я исследовал инструмент быстрой разработки приложений (RAD), в котором был пример проекта, включающего AngularJS. Я обнаружил, что в среде разработки JBOSS Studio Developer IDE, которой я недавно пользовался, есть инструмент RAD под названием «Forge». Он содержит пример проекта, который обеспечивает мгновенную интеграцию всего вышеперечисленного, за исключением настройки ORM-фреймворка (Hibernate), которую необходимо было сделать. Я также отметил, что Spring Data может обеспечить взаимодействие NoSql с приложением. Увидев примеры их аннотаций «@Document» и «@Collection», используемых в классах Entity, я убедился, что их фреймворки были настроены для взаимодействия с самой природой Mongodb, являющейся хранилищем данных на основе документов. Поэтому я решил попробовать оба подхода. Итак, я поведу вас по этому пути, позволяющему Mongodb хорошо работать с остальной частью приложения, начиная с JBOSS Forge.

Инструменты JBOSS Developer Studio Forge с использованием сервера приложений Wildfly

Сначала я установил Mongodb, что представляет собой простой процесс, и отредактировал файл persistence.xml, включив в него необходимые свойства хранилища данных (имя базы данных, хост, порт, имя пользователя, пароль). После онлайн-исследований следующим шагом было получение зависимостей для HibernateOGM, которые позволяют приложению взаимодействовать с Mongodb и другими хранилищами данных NoSql. Я мог бы упомянуть, что я решил развернуть это приложение в Wildfly, которое является следующей бета-версией платформы корпоративных приложений JBOSS (EAP). Причина в том, что WildFly, основанный на JEE7, демонстрирует передовые характеристики и функции, которые, по-видимому, необходимы для моего проекта.

Итак, моим следующим шагом было создание файла конфигурации с именем « jboss-deployment-structure.xml », который нужно поместить в каталог «WEB-INF» со следующим содержимым:

<boss-deployment-structure>
  <deployment>
    <dependencies>
     <module name=”org.hibernate” slot=”ogm”                             services=”export” />
     <module name=”org.hibernate.ogm.mongodb” slot=”main”   services=”export” />
    </dependencies>
  </deployment>
</jboss-deployment-structure>

Затем мне нужно было добавить модули Hibernate OGM в правильный каталог сервера приложений. Поэтому я загрузил этот zip-файл и извлек только каталог ogm, который находится вне каталога org.hibernate. Я распаковал в следующий каталог: wildfly-8.2.0.Final\modules\system\layers\base\org\hibernate. Затем я изменил строку в файле persistence.xml:

<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>

Следующим шагом я использую аннотацию «Entity» Hibernate в классе модели, поэтому необходимо включить ссылку на нее в файл persistence.xml, пример ниже. Также удалите ссылку на источник данных в этом файле:

{removed:]
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
…
</properties>
<class>package com.xstreamus.model.Labsample</class>
</persistence-unit>
…

Затем измените спецификацию разрешенных символов в методах Rest Service: (Пример: для моего метода GET…)

@Path(“/{id:[0–9][0–9]*}”) ...becomes:
@Path(“/{id:[0–9,a-z][0–9,a-z,\\-]*}”) ...due to the fact that Id is now a string.

Последним шагом было убедиться, что все мои столбцы, определенные в моем классе сущностей, были определены как строки, связанные с соответствующей аннотацией, когда это необходимо, для нестроковых полей (например: @Digits(fraction = 0, integer = 12) to представлять номер телефона). Кроме того, из-за различий между реляционными базами данных и базами данных на основе документов (или типа ключ/значение) поле id было изменено, как показано ниже:

Was:
private static final long serialVersionUID = 1L;
private Long id;
Now:
@Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String id;

Исходя из исключений, возникших в результате запуска приложения на этом этапе, потребовался еще один шаг. Эта стратегия требовала создания нового UUID вручную и… «Эй, это работает!»

В этот момент мое любопытство к решению Spring взяло верх надо мной. Можно ли сделать столько же шагов, чтобы добраться до этой точки с предложениями Spring? Пришло время узнать…

Spring STS с использованием Spring Boot, Spring Data с использованием встроенного сервера Tomcat

Как я упоминал ранее в этом блоге, я использовал Spring Boot в рабочем проекте, который произвел на меня очень сильное впечатление тем, как быстро я смог развернуть веб-приложение с помощью этого инструмента. Я надеялся получить столь же приятный исход этого испытания. Ну, я должен сказать, что у меня было приложение (уже определенное в предыдущем проекте), использующее AngularJS, использующее API Restful Service, работающее в течение 20 минут, при этом все операции CRUD работают с Mongodb. Проблемы с генерацией идентификатора уже учтены Spring Data, я был в пути. Я мог фактически разработать свое приложение со всей инфраструктурой мгновенно. Мы все чувствовали тот прилив волнения, когда мы делаем правильный поворот в поездке после того, как «заблудились», что возвращает нас на правильный путь. Это то чувство, которое я испытал, когда, не веря своим глазам, оно просто заработало без подстройки! Ниже приводится краткий отчет об этом путешествии:

Я создал проект Spring Boot, выбрав все компоненты, которые я искал (интеграция с Mongodb и т. д.). Я установил плагин AngularJS eclipse и портировал свой код AngularJS, репозитории Spring, контроллеры, остальные API из предыдущего проекта. Я использовал те же параметры подключения к базе данных.

Говоря об остальных API, я автоматически использую RestComtrollers и Jackson (поскольку они находятся в пути к классам, Spring выбирает их автоматически), выполняя автоматическое преобразование объектов в JSON с помощью Springl MappingJackson2HttpMessageConverter. Кроме того, поскольку я сохраняю данные в хранилище данных Mongodb, все данные хранятся в формате JSON, представленном как BSON (двоичный). Spring Data делает этот процесс прозрачным.

Затем я добавил еще несколько полей ввода в представление, стараясь указать типы ввода как «даты» для полей даты и «текст» для текстовых полей. Я добавил каждое соответствующее свойство в класс Java модели.

Я включил проверку входных данных для двух полей, одно из которых представляет «описание/примечания», а другое — «название образца». Остальное могу добавить позже. Я изменил входные теги и добавил условное отображение сообщений об ошибках. Они должны отображаться только после того, как с формой взаимодействовали (грязные) и данный ввод в поле недействителен. Фрагмент ниже используется для первого поля, которое является обязательным:

<div class="col-md-12">
<input id="title" name="title" type="text" class="form-control input-text" placeholder="Enter Description/Notes about your sample" ng-model="formData.sampdescription" autofocus required/>
</div>
<div ng-show="labSampleForm.$dirty && labsampForm.sampdescription.$invalid">
<span style='color:red;text-align:left' ng-show='labsampForm.sampdescription.$error.required'>
Enter required field
</span>
</div>

Ниже заботится о втором поле. Это не только обязательное поле, но и введенный текст проверяется на соответствие правилу шаблона, указанному в ng-контроллере, на которое ссылается ниже «shelfNameFormat»:

<input type="text" class="form-control input-text" id="shelfName" name="shelfName" placeholder="Shelf Id"  ng-model="formData.shelfName" required ng-pattern="shelfNameFormat"/>
<div ng-show="labsampForm.$dirty && labsampForm.shelfName.$invalid">
    <span style="color:red;text-align:left"  ng-   show='labsampForm.shelfName.$error.required'>Enter required field
    </span>
</div>
<div ng-show='labsampForm.$dirty && labsampForm.shelfName.$error.pattern'>
       <span style="color:red;text-align:left" ng-show='labsampForm.shelfName.$error.pattern'>Enter required format: sh-[alphanumeric chars]-[numerals]
       </span>
</div>

Строка ниже была добавлена ​​в регулярное выражение ng-controller, чтобы гарантировать, что пользователь вводит «sh-», за которым следует любое количество буквенно-цифровых символов. За этим следует тире («-»), затем любое количество цифр:

$scope.shelfNameFormat = /sh+\-[a-zA-Z0-9]+\-[0-9]/;

Я мог бы упомянуть, что при запуске приложения в качестве приложения Spring Boot Spring Data обеспечил автоматическое создание моих объектов mongo в соответствующей коллекции в хранилище данных mongodb. Теперь, когда он запущен и работает, я могу показать ниже изображения проверки в действии. На первом снимке экрана показаны проверки при нажатии кнопки «Добавить» без ввода данных в форму:

На приведенном ниже снимке экрана показано, когда для «sampleName» вводится неправильный «шаблон» данных.

Как видите, в приложение добавлен ряд «записей» или документов. После ввода документы можно удалить или отредактировать, щелкнув значок «X» в кружке или значок карандаша, соответственно, справа от описания/примечаний. Это приводит к раскрывающемуся аккордеону со всеми редактируемыми полями:

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

Мне пришлось изменить теги ввода для полей даты. Ниже приведено соглашение, которое я использовал (пример для ‘finishDate), чтобы получить правильное форматирование для обработки angular:

<input type="date" class="form-control input-date" id="finishdate"value="{{formData.finishDate | date: 'yyyy-MM-dd'}}"placeholder="Test End Date" ng-model="formData.finishDate">

Ниже приведен скриншот добавленной «записи», готовой к редактированию:

Данные сохраняются, как показано в сеансе RoboMongo (инструмент, который я выбрал для взаимодействия с базой данных, это довольно приятно!):

Данные редактируются ниже, будучи одним из полей даты, с выбором даты:

Результирующие изменения теперь отражаются в хранилище данных:

Вот и все! Таким образом, конечный результат — это начало отзывчивого веб-/мобильного приложения с сенсорным экраном, которое относится к хранению образцов медицинских/биологических лабораторий и отслеживанию запасов. Кроме того, приложение с полной возможностью CRUD с хранилищем данных документов, в котором коллекции содержат разные документы, реализовано с хранилищем данных Mongodb.

Пример кода

Исходники рабочего примера этого проекта можно найти на GitHub здесь.

Об авторе:

Опытный инженер-программист, включая разработку веб-приложений с полным стеком, не ограничиваясь технологиями и платформами Java, но с большим опытом. Кроме того, 4 года работы с Интернетом вещей (IoT), в частности, с системами отслеживания активов с RFID-метками с использованием современных антенных систем.

Не стесняйтесь отвечать ниже. Как говорится, обратная связь является ключом к стабильной системе.