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 развивается и меняется семимильными шагами, это необходимый шаг.