Jakarta EE 9 WebService example/JAX-RS Rest
Самый частый вопрос на StackOverflow при апгрейде Томката с 9 на 10-ую версию заключается в том, что проверенное годами REST веб приложение вдруг выдает 404 ошибку при обращении к сервису. В чем же дело? Дело в том, что с введением спецификации Java EE 9 было решено ввести поддержку нового Jax-RS фреймворка Jakarta( на самом деле это все тот же наследник Jersey).
Все решается сменой зависимостей для maven/gradle, изменением импортов исходных классов и небольшой корректировкой xml файлов. Давайте взглянем пример файла pom.xml с зависимостями для Jersey веб приложения:
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.27</version>
</dependency>
<!--<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency> -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.27</version>
</dependency>
</dependencies>
Список зависимостей довольно прост. А теперь взглянем на список зависимостей того же самого веб приложения, но уже с переходом на JavaEE9.
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>3.1.0</version>
</dependency>
<!-- see: https://github.com/eclipse-ee4j/jersey/blob/3.x/examples/cdi-webapp/pom.xml#L142 -->
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-servlet</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-ban-custom-hk2-binding</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version>
</dependency>
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.8.Final</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
Список стал немного больше главным образом из за необходимости загрузки зависимостей новых библиотек.
После сборки приложения и загрузки всех необходимых библиотек, мы получим огромную кучу ошибок. Все они довольно легко лечатся в IDE путем замены сменившихся путей. Например:
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.PersistenceUnit; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; меняем на import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.NoResultException; import jakarta.persistence.Persistence; import jakarta.persistence.PersistenceUnit; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Response;
Все xml файлы persistance прекрасно работают после замены пространств имен на новые:
xmlns=”https://jakarta.ee/xml/ns/persistence”
xsi:schemaLocation=”https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd”
Пример Jakarta EE 9 WebService
Нам понадобится всего 2 класса. Класс с описанием пути приложения и класс реализующий GET метод. Наше приложение мы назовем TestJakartaApp.
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("api")
public class JakartaApp extends Application {
}
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("greeting")
public class TestWebService {
@GET
@Path("{name}")
@Produces(MediaType.APPLICATION_JSON)
public Response greeting(@PathParam("name") String name) {
return Response.status(200).entity("It works!!!!").build();
}
}
Build, Run, вбиваем адрес localhost:8080/TestJakartaApp/api/greeting/name и видим нашу надпись – It works!!!

Если возникнут сложности, можете писать в комментариях или на электронную почту(Телеграмм канал сделаем чуть позже).
Справочник:
Jax – RS – Java API для веб-сервисов RESTful (JAX-RS)
Jakarta – Java EE после 8-ой версии было решено кардинально модернизировать, вплоть до смены namespace. Отныне javax ушел в прошлое и его поддержка в контейнерах веб приложений будет постепенно сходить на нет. Java развивается и меняется семимильными шагами, это необходимый шаг.