Использование библиотеки

Подключение библиотеки в проект

Для использования библиотеки необходимо ее подключить в проект. Способ подключения зависит от вида проекта. Например, для maven проекта нужно добавить зависимость


  <dependency>
    <groupId>ru.funsys.avalanche</groupId>
    <artifactId>avalanche-rs</artifactId>
    <version>${avalanche.version}</version>
  </dependency>

где ${avalanche.version} - номер версии библиотеки, например:


  <properties>
    <avalanche.version>1.3.2</avalanche.version>
  </properties>

Помимо добавления зависимости возможно потребуется добавить maven репозиторий, в котором опубликованы библиотеки "Avalanche - application framework for Java". Это можно сделать несколькими способами, например в файл pom.xml проекта или в файл settings.xml локального maven репозитория.

Использование библиотеки в коде проекта

В программной модели приложения использования библиотеки avalanche-rs определяется класс сервиса, в котором декларируются методы REST сервиса с использованием аннотаций библиотеки Jersey и, при необходимости, аннотаций Swagger. В приложении можно определить множество подобных классов.

В классе сервиса необходимо обеспечить наличие одного, множества или массивов полей классов, наследуемых от класса ru.funsys.avalanche.Application, в которых и определяется вся логика реализуемых методов сервиса. Для автоматической установки этих полей класс сервиса должен наследоваться от класса ru.funsys.avalanche.rs.RestService.

Автоматическая установка полей классов осуществляется по имени поля (имя поля совпадает с именем экземпляра класса, определенного в секции <application> в файле конфигурации приложения) или по типу поля (происходит подбор экземпляров классов, определенных в секциях <application> до совпадения типов).

Пример реализации класса сервиса

public class Service extends RestService {

	/**
	 * Поле устанавливается автоматически 
	 */
	private WebApp app;

	@Operation(summary = "Получить список смартфонов",
			responses = {
            		@ApiResponse(responseCode = "200", description = "Ok", content = @Content(array = @ArraySchema(schema = @Schema(implementation = Smartphone.class)))), 
    				@ApiResponse(responseCode = "401", description = "Unauthorized"),
    				@ApiResponse(responseCode = "403", description = "Forbidden"),
    				@ApiResponse(responseCode = "500", description = "Internal server error") })
   	@GET
   	@Path("/list")
   	public Smartphone[] list() throws WebApplicationException {
   		try {
   			return app.list();
   		} catch (Exception e) {
   			throw new WebApplicationException(e, 500);
   		}
	}

    ...
    
 }

где поле app - экземпляр класса WebApp, наследуемого от ru.funsys.avalanche.Application

Можно явно указать какой экземпляр класса тега <application> устанавливать в поле класса сервиса аннотацией SetApplication.

Пример использования аннотации SetApplication в классе сервиса

public class Service extends RestService {

	/**
	 * Установка значения с использованием аннотации 
	 */
	@SetApplication("WebApp")
	private WebApp app;

    ...
    
 }

где значение аннотации "WebApp" это значение атрибута name тега <application> в файле конфигурации приложения.

Пример реализации класса WebApp

public class WebApp extends Application {


	/* -----       Атрибуты класса         ----- */ 
	@CfgAttribute(description = "Адаптер доступа к функциям БД")
	private Adapter database;

	// другие поля класса
	...

	/**
	 * Получить список смартфонов
	 *  
	 * @return результат выполнения запроса
	 * 
	 * @throws Exception ошибка выполнения запроса
	 */
	public Smartphone[] list() throws Exception {
		String sql = getParameterValue("list");
		if (sql == null) {
			String error = error("RS00001E", "list", getNodeName(), getName());
			throw new NullPointerException(error);
		} else {
			sql = String.format(sql, table());
		}
		return database.select(sql, Smartphone.class);
	}
	
	// другие методы класса
	...

}

Изменение файла конфигурации приложения

В файле конфигурации приложения должна быть определена секция, содержащая конфигурационные параметры класса ru.funsys.avalanche.sql.Database, обязательно должны быть определены атрибуты name и resource. Допускается определение конфигурации класса ru.funsys.avalanche.sql.Database как секцией <function>, так и секцией <application>.

Пример определения в секции <function>


	<!-- 
	Сервисные функции работы с БД, источник данных БД определяется в конфигурации 
	контекста WEB приложение (для Tomcat см. вложенный элемент <Resource> секции <context>)
	 -->
	<function class="ru.funsys.avalanche.sql.Database" name="database" description="Функция доступа к БД"
	             resource="java:/jboss/datasources/PostgresDataSource">
	</function>          

Пример определения в секции <application>, обязательно должен быть определен атрибут function в значении true


	<!-- 
	Сервисные функции работы с БД, источник данных БД определяется в конфигурации 
	контекста WEB приложение (для Tomcat см. вложенный элемент <Resource> секции <context>)
	 -->
	<application class="ru.funsys.avalanche.sql.Database" name="database" description="Функция доступа к БД"
	             resource="java:/jboss/datasources/PostgresDataSource" function="true">
	</application>          

Если приложение должно работать с несколькими базами данных, то в конфигурации приложения определяются несколько секций класса ru.funsys.avalanche.sql.Database. Для каждого источника данных своя секция класса.

В секциях <application> одной или несколькими дочерними секциями adapter определяются адаптеры доступа к объектам ru.funsys.avalanche.sql.Database

Пример определения адаптера ru.funsys.avalanche.sql.Adapter, в атрибуте uri указывается локальное имя экземпляра класса ru.funsys.avalanche.sql.Database (значение атрибута name соответствующей секции <function> или <application>).


	<application class="ru.app.demo.rs.app.WebApp" name="WebApp" 
	             description="WEB приложение">
	
		<adapter class="ru.funsys.avalanche.sql.Adapter" name="database" uri="database" />
	
		<!-- Дочерние элементы конфигурации -->
		...
		
	</application>