1. 개요
마이크로서비스 아키텍처 및 클라우드 네이티브 애플리케이션 개발의 인기로 인해 빠르고 가벼운 애플리케이션 서버에 대한 요구가 증가하고 있습니다.
이 입문 사용방법(예제)에서는 RESTful 웹 서비스를 만들고 사용하기 위해 Open Liberty 프레임워크를 탐색합니다 . 또한 제공되는 몇 가지 필수 기능을 살펴보겠습니다.
2. 오픈 리버티
Open Liberty는 Eclipse MicroProfile 및 Jakarta EE 플랫폼 의 기능을 사용하여 마이크로서비스를 개발할 수 있는 Java 에코시스템용 개방형 프레임워크 입니다 .
클라우드 네이티브 마이크로서비스 개발에 유망해 보이는 유연하고 빠르며 가벼운 Java 런타임입니다.
프레임워크를 사용하면 앱에 필요한 기능만 구성할 수 있으므로 시작하는 동안 메모리 공간이 더 작아집니다. 또한 Docker 및 Kubernetes 와 같은 컨테이너를 사용하여 모든 클라우드 플랫폼에 배포할 수 있습니다 .
빠른 반복을 위해 코드를 실시간으로 다시 로드하여 신속한 개발을 지원합니다.
3. 구축 및 실행
먼저 open-liberty 라는 간단한 Maven 기반 프로젝트를 만든 다음 최신 liberty-maven-plugin 플러그인을 pom.xml 에 추가합니다 .
<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>3.3-M3</version>
</plugin>
또는 liberty-maven-plugin 에 대한 대안으로 최신 openliberty-runtime Maven 의존성을 추가할 수 있습니다 .
<dependency>
<groupId>io.openliberty</groupId>
<artifactId>openliberty-runtime</artifactId>
<version>20.0.0.1</version>
<type>zip</type>
</dependency>
마찬가지로 최신 Gradle 의존성을 build.gradle 에 추가할 수 있습니다 .
dependencies {
libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '20.0.0.1'
}
그런 다음 최신 jakarta.jakartaee-web-api 및 microprofile Maven 의존성을 추가합니다 .
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>8.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>3.2</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
그런 다음 기본 HTTP 포트 속성을 pom.xml 에 추가해 보겠습니다 .
<properties>
<liberty.var.default.http.port>9080</liberty.var.default.http.port>
<liberty.var.default.https.port>9443</liberty.var.default.https.port>
</properties>
다음으로 src/main/liberty/config 디렉토리 에 server.xml 파일을 생성합니다 .
<server description="Baeldung Open Liberty server">
<featureManager>
<feature>mpHealth-2.0</feature>
</featureManager>
<webApplication location="open-liberty.war" contextRoot="/" />
<httpEndpoint host="*" httpPort="${default.http.port}"
httpsPort="${default.https.port}" id="defaultHttpEndpoint" />
</server>
여기에 응용 프로그램의 상태를 확인하는 mpHealth-2.0 기능을 추가했습니다 .
이것으로 모든 기본 설정이 끝났습니다. Maven 명령을 실행하여 처음으로 파일을 컴파일해 보겠습니다.
mvn clean package
마지막으로 Liberty에서 제공하는 Maven 명령을 사용하여 서버를 실행해 보겠습니다.
mvn liberty:dev
짜잔! 애플리케이션이 시작되고 localhost:9080 에서 액세스할 수 있습니다 .
또한 localhost:9080/health 에서 앱의 상태에 액세스할 수 있습니다 .
{"checks":[],"status":"UP"}
liberty :dev 명령은 서버를 다시 시작하지 않고 코드 또는 구성에 대한 모든 변경 사항을 핫 리로드하는 개발 모드에서 Open Liberty 서버를 시작합니다 .
마찬가지로 liberty:run 명령을 사용하여 프로덕션 모드에서 서버를 시작할 수 있습니다.
또한 liberty:start-server 및 liberty: stop-server를 사용하여 백그라운드에서 서버를 시작/중지할 수 있습니다 .
4. 서블릿
앱에서 서블릿을 사용하기 위해 server.xml 에 servlet-4.0 기능을 추가합니다 .
<featureManager>
...
<feature>servlet-4.0</feature>
</featureManager>
pom.xml 에서 openliberty-runtime Maven 의존성을 사용하는 경우 최신 servlet-4.0 Maven 의존성을 추가합니다 .
<dependency>
<groupId>io.openliberty.features</groupId>
<artifactId>servlet-4.0</artifactId>
<version>20.0.0.1</version>
<type>esa</type>
</dependency>
그러나 liberty-maven-plugin 플러그인을 사용하는 경우에는 필요하지 않습니다.
그런 다음 HttpServlet 클래스를 확장하는 AppServlet 클래스를 만듭니다 .
@WebServlet(urlPatterns="/app")
public class AppServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String htmlOutput = "<html><h2>Hello! Welcome to Open Liberty</h2></html>";
response.getWriter().append(htmlOutput);
}
}
여기에서 지정된 URL 패턴에서 AppServlet을 사용할 수 있도록 하는 @WebServlet 어노테이션을 추가했습니다 .
localhost:9080/app 에서 서블릿에 액세스해 보겠습니다 .
5. RESTful 웹 서비스 생성
먼저 server.xml 에 jaxrs-2.1 기능을 추가해 보겠습니다 .
<featureManager>
...
<feature>jaxrs-2.1</feature>
</featureManager>
그런 다음 RESTful 웹 서비스에 Endpoints을 제공하는 ApiApplication 클래스를 만듭니다 .
@ApplicationPath("/api")
public class ApiApplication extends Application {
}
여기서는 URL 경로에 @ApplicationPath 어노테이션을 사용했습니다 .
그런 다음 모델을 제공하는 Person 클래스를 생성해 보겠습니다 .
public class Person {
private String username;
private String email;
// getters and setters
// constructors
}
다음으로 HTTP 매핑을 정의하는 PersonResource 클래스를 만듭니다 .
@RequestScoped
@Path("persons")
public class PersonResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Person> getAllPersons() {
return Arrays.asList(new Person(1, "normanlewis", "normanlewis@email.com"));
}
}
여기에서 /api/persons Endpoints 에 대한 GET 매핑을 위한 getAllPersons 메서드를 추가했습니다 . 이제 RESTful 웹 서비스를 사용할 준비가 되었으며 liberty:dev 명령이 변경 사항을 즉석에서 로드합니다.
curl GET 요청을 사용하여 /api/persons RESTful 웹 서비스에 액세스해 보겠습니다 .
curl --request GET --url http://localhost:9080/api/persons
그런 다음 응답으로 JSON 배열을 얻습니다.
[{"id":1, "username":"normanlewis", "email":"normanlewis@email.com"}]
마찬가지로 addPerson 메소드 를 생성하여 POST 매핑을 추가할 수 있습니다 .
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response addPerson(Person person) {
String respMessage = "Person " + person.getUsername() + " received successfully.";
return Response.status(Response.Status.CREATED).entity(respMessage).build();
}
이제 curl POST 요청으로 엔드포인트를 호출할 수 있습니다.
curl --request POST --url http://localhost:9080/api/persons \
--header 'content-type: application/json' \
--data '{"username": "normanlewis", "email": "normanlewis@email.com"}'
응답은 다음과 같습니다.
Person normanlewis received successfully.
6. 끈기
6.1. 구성
RESTful 웹 서비스에 지속성 지원을 추가해 보겠습니다.
먼저 pom.xml 에 derby Maven 의존성을 추가합니다 .
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.14.2.0</version>
</dependency>
그런 다음 jpa-2.2 , jsonp-1.1 및 cdi-2.0 과 같은 몇 가지 기능을 server.xml 에 추가합니다 .
<featureManager>
...
<feature>jpa-2.2</feature>
<feature>jsonp-1.1</feature>
<feature>cdi-2.0</feature>
</featureManager>
여기에서 jsonp-1.1 기능은 JSON 처리를 위한 Java API를 제공하고 cdi-2.0 기능은 범위 및 의존성 주입을 처리합니다.
다음으로 src/main/resources/META-INF 디렉토리 에 persistence.xml을 생성합니다 .
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="jpa-unit" transaction-type="JTA">
<jta-data-source>jdbc/jpadatasource</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="both" />
</properties>
</persistence-unit>
</persistence>
여기서는 EclipseLink DDL 생성을 사용하여 데이터베이스 스키마를 자동으로 생성했습니다. Hibernate와 같은 다른 대안을 사용할 수도 있습니다.
그런 다음 dataSource 구성을 server.xml 에 추가해 보겠습니다 .
<library id="derbyJDBCLib">
<fileset dir="${shared.resource.dir}" includes="derby*.jar"/>
</library>
<dataSource id="jpadatasource" jndiName="jdbc/jpadatasource">
<jdbcDriver libraryRef="derbyJDBCLib" />
<properties.derby.embedded databaseName="libertyDB" createDatabase="create" />
</dataSource>
참고로 jndiName 에는 persistence.xml 의 jta-data-source 태그 에 대한 동일한 참조가 있습니다 .
6.2. 엔티티 및 DAO
그런 다음 Person 클래스에 @Entity 어노테이션과 식별자를 추가합니다 .
@Entity
public class Person {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private int id;
private String username;
private String email;
// getters and setters
}
다음으로 EntityManager 인스턴스를 사용하여 데이터베이스와 상호 작용할 PersonDao 클래스를 생성해 보겠습니다 .
@RequestScoped
public class PersonDao {
@PersistenceContext(name = "jpa-unit")
private EntityManager em;
public Person createPerson(Person person) {
em.persist(person);
return person;
}
public Person readPerson(int personId) {
return em.find(Person.class, personId);
}
}
@PersistenceContext 는 persistence.xml 의 persistence-unit 태그 에 대한 동일한 참조를 정의합니다 .
이제 PersonResource 클래스 에 PersonDao 의존성을 주입합니다 .
@RequestScoped
@Path("person")
public class PersonResource {
@Inject
private PersonDao personDao;
// ...
}
여기에서는 CDI 기능에서 제공하는 @Inject 어노테이션을 사용했습니다 .
마지막으로 Person 개체를 유지하기 위해 PersonResource 클래스 의 addPerson 메서드 를 업데이트합니다 .
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
public Response addPerson(Person person) {
personDao.createPerson(person);
String respMessage = "Person #" + person.getId() + " created successfully.";
return Response.status(Response.Status.CREATED).entity(respMessage).build();
}
여기에서 addPerson 메소드는 CDI 관리 Bean에서 트랜잭션을 제어하기 위해 @Transactional 어노테이션 으로 어노테이션됩니다 .
이미 논의한 curl POST 요청으로 Endpoints을 호출해 보겠습니다.
curl --request POST --url http://localhost:9080/api/persons \
--header 'content-type: application/json' \
--data '{"username": "normanlewis", "email": "normanlewis@email.com"}'
그러면 다음과 같은 텍스트 응답을 받게 됩니다.
Person #1 created successfully.
마찬가지로 Person 개체를 가져오기 위해 GET 매핑과 함께 getPerson 메서드를 추가해 보겠습니다 .
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public Person getPerson(@PathParam("id") int id) {
Person person = personDao.readPerson(id);
return person;
}
curl GET 요청을 사용하여 Endpoints을 호출해 보겠습니다.
curl --request GET --url http://localhost:9080/api/persons/1
그런 다음 JSON 응답으로 Person 개체를 가져옵니다 .
{"email":"normanlewis@email.com","id":1,"username":"normanlewis"}
7. JSON-B를 사용하여 RESTful 웹 서비스 사용
먼저 server.xml 에 jsonb-1.0 기능 을 추가하여 모델을 직접 직렬화 및 역직렬화하는 기능을 활성화합니다 .
<featureManager>
...
<feature>jsonb-1.0</feature>
</featureManager>
그런 다음 ConsumeWithJsonb 메서드를 사용하여 RestConsumer 클래스를 생성해 보겠습니다 .
public class RestConsumer {
public static String consumeWithJsonb(String targetUrl) {
Client client = ClientBuilder.newClient();
Response response = client.target(targetUrl).request().get();
String result = response.readEntity(String.class);
response.close();
client.close();
return result;
}
}
여기에서는 ClientBuilder 클래스를 사용하여 RESTful 웹 서비스 엔드포인트를 요청했습니다.
마지막으로 /api/person RESTful 웹 서비스를 사용 하고 응답을 확인하는 단위 테스트를 작성해 보겠습니다.
@Test
public void whenConsumeWithJsonb_thenGetPerson() {
String url = "http://localhost:9080/api/persons/1";
String result = RestConsumer.consumeWithJsonb(url);
Person person = JsonbBuilder.create().fromJson(result, Person.class);
assertEquals(1, person.getId());
assertEquals("normanlewis", person.getUsername());
assertEquals("normanlewis@email.com", person.getEmail());
}
여기서는 JsonbBuilder 클래스를 사용하여 String 응답을 Person 개체 로 구문 분석했습니다 .
또한 RESTful 웹 서비스를 사용하기 위해 mpRestClient-1.3 기능을 추가하여 MicroProfile Rest Client를 사용할 수 있습니다 . RESTful 웹 서비스 엔드포인트를 요청하기 위해 RestClientBuilder 인터페이스를 제공합니다 .
8. 결론
이 기사에서는 Eclipse MicroProfile 및 Jakarta EE 플랫폼의 모든 기능을 제공하는 빠르고 가벼운 Java 런타임인 Open Liberty 프레임워크를 살펴보았습니다.
먼저 JAX-RS를 사용하여 RESTful 웹 서비스를 만들었습니다. 그런 다음 JPA 및 CDI와 같은 기능을 사용하여 지속성을 활성화했습니다.
마지막으로 JSON-B를 사용하여 RESTful 웹 서비스를 사용했습니다.
평소와 같이 모든 코드 구현은 GitHub에서 사용할 수 있습니다 .