1. 개요

마이크로 서비스 아키텍처 및 클라우드 네이티브 애플리케이션 개발의 인기로 인해 빠르고 가벼운 애플리케이션 서버에 대한 요구가 증가하고 있습니다.

이 입문 사용방법(예제)에서는 RESTful 웹 서비스를 만들고 사용 하기 위한 Open Liberty 프레임 워크탐색 합니다 . 또한 제공하는 몇 가지 필수 기능에 대해서도 살펴 보겠습니다.

2. 자유 개방

Open Liberty는 Eclipse MicroProfileJakarta EE 플랫폼의 기능을 사용하여 마이크로 서비스를 개발할 수있는 Java 에코 시스템 용 개방형 프레임 워크입니다 .

클라우드 네이티브 마이크로 서비스 개발에 유망 해 보이는 유연하고 빠르며 가벼운 Java 런타임입니다.

프레임 워크를 사용하면 앱에 필요한 기능 만 구성 할 수 있으므로 시작하는 동안 메모리 사용량이 줄어 듭니다. 또한 DockerKubernetes같은 컨테이너를 사용하여 모든 클라우드 플랫폼에 배포 할 수 있습니다.

빠른 반복을 위해 코드를 실시간으로 다시로드하여 빠른 개발을 지원합니다.

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>

마찬가지로 build.gradle에 최신 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 : run 명령을 사용하여 프로덕션 모드에서 서버를 시작할 수 있습니다.

또한 liberty : start-serverliberty : 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>

그런 다음 , 우리가 만듭니다 ApiApplication의 평온한 웹 서비스 엔드 포인트를 제공하는 클래스를 :

@ApplicationPath("/api")
public class ApiApplication extends Application {
}

여기서는 URL 경로에 @ApplicationPath 어노테이션을 사용했습니다 .

그런 다음 모델을 제공하는 Person 클래스를 만들어 보겠습니다 .

public class Person {
    private String username;
    private String email;

    // getters and setters
    // constructors
}

다음으로 PersonResource 클래스를 만들어 HTTP 매핑을 정의합니다.

@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 엔드 포인트 에 대한 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.1cdi-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을 받는 동일한 참조 갖는다 JTA 데이터 소스 태그 의 persistence.xml한다.

6.2. 엔티티 및 DAO

그런 다음 @Entity 어노테이션과 식별자를 Person 클래스에 추가합니다.

@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를 .

이제 PersonResource 클래스 PersonDao 의존성을 삽입합니다 .

@RequestScoped
@Path("person")
public class PersonResource {
    @Inject
    private PersonDao personDao;

    // ...
}

여기에서는 CDI 기능에서 제공 하는 @Inject 어노테이션을 사용했습니다 .

마지막으로 PersonResource 클래스 addPerson 메서드를 업데이트 하여 Person 개체 를 유지 합니다.

@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 요청으로 엔드 포인트를 호출 해 보겠습니다.

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 요청을 사용하여 엔드 포인트를 호출 해 보겠습니다.

curl --request GET --url http://localhost:9080/api/persons/1

그런 다음 Person 객체를 JSON 응답으로 얻습니다 .

{"email":"normanlewis@email.com","id":1,"username":"normanlewis"}

7. JSON-B를 사용하여 RESTful 웹 서비스 사용

먼저, jsonb-1.0 기능을 server.xml 에 추가하여 모델을 직접 직렬화 및 역 직렬화하는 기능을 활성화합니다 .

<featureManager>
    ...
    <feature>jsonb-1.0</feature>
</featureManager>

그런 다음 ConsumerWithJsonb 메서드를 사용하여 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에서 사용할 수  있습니다 .