08 августа 2019
В этом посту я поделюсь простым и полезным gradle шаблоном для создания мультимодульного Jakarta EE приложения. Мы реализуем один из типичных, который состоит из REST контроллера (module1) и некоторой основной логики (module2). Общая картина архитектуры нашего приложения выглядит вот так:
Итак, давайте сделаем инициализацию проекта с помощью следующего gradle шаблона:
settings.gradle:
rootProject.name = 'ee-application-multi-module-gradle-template'
include 'module1'
include 'module2:module2-api', 'module2:module2-core'
root build.gradle:
defaultTasks 'clean', 'build'
subprojects {
ext.libraryVersions = [
javaee : '8.0',
]
defaultTasks 'clean', 'build'
repositories {
jcenter()
}
}
Выше, мы описали начальную структуру приложения, где module1 является плоским подпроектом для нашего контроллера, а module2 является нашей основной логикой, которая состоит из подпроектов API
и Core
. В качестве контроллера, мы будем использовать основную логику API, и мы решили разделить приложение на модули (что означает отсутсвие общеорганизационных архивов) - наши подпроекты должны быть достаточно простыми:
module1 build.gradle:
apply plugin: 'war'
dependencies {
compile project(':module2:module2-api')
providedCompile "javax:javaee-api:${libraryVersions.javaee}"
}
module2:module2-api:
apply plugin: 'java'
dependencies {
}
module2:module2-core:
apply plugin: 'war'
dependencies {
compile project(':module2:module2-api')
providedCompile "javax:javaee-api:${libraryVersions.javaee}"
}
На самом деле, это всё!
Теперь мы можем реализовать наш контроллер следующим образом:
@Path("/")
@Stateless
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class TestEndpoint {
@EJB(lookup = TestService.TEST_SERVICE_JNDI)
TestService testService;
@GET
@Path("/test")
public Response test() {
SomethingDto something = testService.doSomething();
return Response.ok().entity(something.getMessage()).build();
}
В свою очередь, основная логика API
содержиться в Interface
и DTO
:
TestService.java:
public interface TestService {
String TEST_SERVICE_NAME = "test-service";
String TEST_SERVICE_JNDI ="java:global/module2-core/" + TEST_SERVICE_NAME;
SomethingDto doSomething();
}
SomethingDto.java:
public class SomethingDto implements Serializable{
...
}
В конце концов, основная логика Core
состоит из логики, реализующей API:
TestServiceImpl.java
@Remote(TestService.class)
@Stateless(name = TestService.TEST_SERVICE_NAME)
public class TestServiceImpl implements TestService {
@PersistenceContext
EntityManager entityManager;
@Override
public SomethingDto doSomething() {
TestEntity entity = entityManager.find(TestEntity.class, Long.MAX_VALUE);
return new SomethingDto("Hello Jakarta EE world!");
}
}
Описанная архитектура приложений Jakarta EE позволяет нам наслаждаться всеми возможностями ЕЕ с абсолютно прозрачными взаимодействиями между модулями и в то же время оставаться близким к дизайну микросервисов - поскольку у нас нет ограничений в использований одного контейнера для всех модулей.
Исходный код, доступен на GitHub