주:
- 이 자습서에서는 Oracle Cloud에 액세스해야 합니다. 무료 계정에 등록하려면 Oracle Cloud Infrastructure Free Tier 시작하기를 참조하십시오.
- Oracle Cloud Infrastructure 자격 증명, 테넌시 및 구획에 예제 값을 사용합니다. 실습을 완료했으면 이러한 값을 자신의 클라우드 환경과 관련된 값으로 대체하십시오.
OKE의 Spring Boot를 사용하여 Oracle GraalVM 기반 Java 애플리케이션을 생성하여 ATP에 SOAP 메시지를 저장하고 OCI Queue로 전송
소개
대부분의 고객은 기존 SOAP(Simple Object Access Protocol) 메시징을 사용하여 애플리케이션 간 통신을 활성화합니다. 트랜잭션 데이터를 저장하고, 서비스 분리(decoupling)를 보장하고, 수신 요청 로드 밸런싱을 달성하고, 이러한 메시지의 비동기 통신을 활성화해야 하는 경우가 많습니다.
이 사용지침서에서는 Oracle Autonomous Transaction Processing(ATP) 및 OCI Queue와 같은 다양한 OCI(Oracle Cloud Infrastructure) 서비스와의 트랜잭션 통합자로 사용될 Oracle Cloud Infrastructure Kubernetes Engine(OKE) 인프라에 배포된 Spring Boot를 사용하여 Oracle GraalVM 기반 Java 애플리케이션을 구축하는 방법을 알아봅니다. 이 설정을 통해 시스템은 직접 연결 없이 상호 작용할 수 있으므로 처리 속도가 다른 응용 프로그램 간의 통신을 용이하게 할 수 있습니다. 또한 정보가 데이터베이스에 저장되면 이를 참조하거나 분석할 수 있습니다.
다음 기술을 사용합니다.
Oracle Cloud Infrastructure Services(OCI): OCI는 150여 개의 클라우드 서비스를 제공하는 안전한 고성능 클라우드 플랫폼입니다. 확장성, 보안 및 성능을 위해 설계되었습니다.
-
Oracle Cloud Infrastructure Kubernetes Engine(OKE): OKE는 OCI에서 컨테이너화된 애플리케이션을 배포, 관리 및 확장하기 위한 관리형 서비스입니다. 프로비저닝, 확장 및 모니터링과 같은 작업을 자동화하면서 강력한 보안 및 OCI 통합을 보장합니다. OKE는 Stateless 및 Stateful 워크로드를 모두 지원하며, 모던 앱 개발을 위한 유연한 플랫폼을 제공합니다.
-
OCI Container Registry Classic: OCI의 관리형 Docker 호환 레지스트리로, 사용자가 컨테이너 이미지를 안전하게 저장, 관리 및 배포할 수 있습니다. OKE 및 기타 OCI 서비스와 원활하게 통합되어 컨테이너화된 애플리케이션을 효율적으로 배포할 수 있습니다.
-
Oracle Autonomous Transaction Processing(ATP): ATP는 프로비저닝, 패치 적용, 확장 및 백업과 같은 작업을 자동화하여 고가용성과 보안을 보장하는 클라우드 데이터베이스 서비스입니다. 자율 운영 및 성능 최적화를 위해 머신 러닝을 활용하여 트랜잭션 지향 워크로드를 위한 강력한 성능을 제공합니다. 손쉬운 생성형 AI, 완벽한 데이터 보호 및 보안과 같은 애플리케이션 개발 기능을 갖춘 ATP는 지속적인 고성능 및 최대 가용성을 보장합니다.
-
OCI 대기열: 분산된 애플리케이션 간 비동기, 분리된 통신을 가능하게 하는 완전 관리형 서버리스 메시지 대기열 서비스입니다. 자동 확장, 메시지 지속성 및 공정 처리와 같은 기능을 통해 안정적인 메시지 전달을 보장합니다. OCI Queue는 다른 OCI 서비스와 통합되며 확장 가능한 이벤트 기반 아키텍처에 이상적인 산업 표준 프로토콜을 지원합니다.
Oracle 기술:
- Oracle GraalVM Java, JavaScript, Python 등 다양한 프로그래밍 언어를 지원하는 고성능 다언어 가상 머신(VM)입니다. JIT(Just in Time) 및 AOT(Ahead of Time) 컴파일을 통해 성능이 향상되므로 시작 속도가 빨라지고 리소스 사용량이 줄어듭니다. Oracle GraalVM은 최적화 및 프로파일링을 위한 도구도 제공하므로 마이크로서비스 및 클라우드 네이티브 애플리케이션에 적합합니다.
기타 기술:
- Spring Boot: 자동 구성 및 내장된 웹 서버를 통해 독립형 운영 지원 애플리케이션을 간편하게 생성할 수 있는 Java 프레임워크입니다. 상태 검사 및 측정 지표와 같은 내장 기능을 제공하므로 마이크로서비스 및 확장 가능한 애플리케이션을 신속하게 구축하는 데 이상적입니다.
OCI 상위 아키텍처:
참고:
- JMeter가 고객 애플리케이션에서 생성된 SOAP 메시지를 시뮬레이트할 것임을 명확히 해야 합니다.
- 이 튜토리얼은 학생들에게 실제 경험을 탐구하고 얻을 수있는 제어 환경을 제공하는 교육 목적으로 고안되었습니다. 시연된 보안 구성 및 연습은 학습용으로 설계되었으므로 운용 환경이나 실제 응용 프로그램에 적합하지 않을 수 있습니다.
목표
-
Spring Boot 프레임워크를 사용하여 Oracle GraalVM 기반 Java 애플리케이션을 구축하고, 트랜잭션 메시지를 ATP에 저장하고 OCI Queue로 전송하는 데 필요한 전체 OCI 서비스를 프로비저닝합니다.
-
OKE 클러스터를 프로비전하고 구성합니다.
-
OCI Container Registry Classic을 프로비전, 구성 및 액세스하십시오.
-
ATP 서버리스 데이터베이스를 프로비저닝하고 구성합니다.
-
ATP에서 프로젝트 테이블을 연결하고 생성합니다.
-
OCI 대기열을 프로비저닝하고 구성합니다.
-
Spring Boot로 Oracle GraalVM 기반 Java 애플리케이션을 구축하고 OKE에 배포합니다.
-
JMeter를 사용하여 Spring Boot Oracle GraalVM 애플리케이션을 테스트합니다.
-
필요 조건
-
OCI 환경: 이 튜토리얼에서는 애플리케이션을 효과적으로 배포, 관리, 확장하는 데 필요한 클라우드 인프라, 서비스 및 보안 구성을 제공합니다.
-
OCI 테넌트에 액세스합니다. 무료 Oracle Cloud 계정을 생성하려면 무료 Oracle Cloud 계정 생성을 참조하십시오.
-
퍼블릭 및 프라이빗 서브넷으로 VCN을 생성합니다. 자세한 내용은 VCN 생성 및 서브넷 생성을 참조하십시오.
-
OCI 서비스를 그룹화할 수 있는 컴파트먼트를 생성합니다. 자세한 내용은 구획 생성을 참조하십시오.
-
-
관리 호스트: 상위 레벨 아키텍처에 표시된 것처럼 관리 호스트(이 자습서에서는 Oracle Linux 8 사용)가 있어야 합니다. 관리 호스트는 OCI CLI, kubectl 및 Docker를 사용하여 구성해야 OKE 클러스터 및 OCI Container Registry Classic을 모니터링하고 가시성을 확보하며 제어할 수 있습니다.
-
프로비전 관리 호스트입니다. 자세한 내용은 인스턴스 생성을 참조하십시오.
-
OCI CLI(Oracle Cloud Infrastructure Command Line Interface)를 설치합니다. 자세한 내용은 OCI CLI 설치를 참조하십시오.
-
Oracle Linux 8/7에 Docker를 설치합니다. 자세한 내용은 Installing Docker를 참조하십시오.
-
Linux에 kubectl을 설치하고 설정합니다. 자세한 내용은 Installing kubectl를 참조하십시오.
-
-
개발 환경: 코드를 작성, 테스트 및 디버그하려면 개발 환경이 필요합니다. Apache Maven 및 Oracle GraalVM을 설치합니다.
-
Oracle GraalVM을 설치합니다. 자세한 내용은 Oracle GraalVM 시작을 참조하십시오.
-
Apache Maven을 다운로드하고 설치합니다. 자세한 내용은 Download Maven 및 Install Maven을 참조하십시오.
-
Spring Boot 애플리케이션을 개발합니다. 자세한 내용은 첫번째 Spring 부트 응용 프로그램 개발 및 Spring Quickstart Guide를 참조하십시오.
-
작업 1: OKE 클러스터 프로비전 및 구성
이 작업에서는 Kubernetes 플랫폼을 프로비저닝합니다. 이 플랫폼에서는 애플리케이션이 ATP에 저장할 모든 SOAP 높은 트랜잭션 메시지를 지원하고 각각을 OCI 대기열에 실시간으로 전송할 수 있습니다.
-
OCI 콘솔에 로그인하여 개발자 서비스, OKE(Kubernetes 클러스터)로 이동한 다음 원하는 구획을 선택합니다.
OKE 클러스터를 만드는 방법에는 다음 두 가지가 있습니다.
- 빠른 생성.
- 사용자정의 생성.
-
빠른 생성을 선택합니다. 이 방법은 다음과 같이 OKE의 작업에 필요한 모든 요소를 더 쉽고 빠르게 자동으로 배치합니다.
- VCN(가상 클라우드 네트워크).
- 인터넷 게이트웨이.
- NAT(Network Address Translation) 게이트웨이입니다.
- 서비스 게이트웨이.
- Kubernetes 클러스터.
- Kubernetes 워커 노드 및 노드 풀.
주: 이미 고객에게 서비스, 네트워크, 기반구조가 있는 엔터프라이즈 환경의 경우 OKE 배치를 준수하도록 사용자 정의하고 클라이언트 구조, 리소스 및 모범 사례에 맞게 조정하는 것이 중요합니다.
-
클러스터 생성을 누르고 다음 정보를 입력합니다.
- 이름: OKE 클러스터의 이름을 입력합니다.
- 구획: 이 프로젝트에 대해 생성된 컴파트먼트를 선택합니다.
- Kubernetes 버전: 사용 가능한 최신 Kubernetes 버전을 선택합니다.
- Kubernetes API 끝점: 이 자습서에서는 공용 끝점을 선택하지만, 전용 끝점을 선택할 수도 있습니다.
- 노드 유형: 관리됨 노드를 선택합니다.
- Kubernetes 워커 노드: 비공개 워커를 선택합니다.
- 구성 및 이미지: VM.Standard.E5를 선택합니다. 유연하게 OCPU 수(2) 및 메모리(16GB)를 사용자 정의하고 기본 Oracle Linux 8 이미지를 보존합니다.
- 노드 수: OKE 노드 풀과 함께 배치할 워커 노드 2개를 입력합니다.
OKE 클러스터가 작동 중인지 검토합니다.
작업 2: OCI 컨테이너 레지스트리 클래식 프로비전, 구성 및 액세스
저장소에서 프로젝트 이미지를 관리해야 합니다. 이를 위해 OCI Container Registry Classic을 프로비저닝합니다. 이미지가 OCI Container Registry Classic에 저장되면 OKE에 배포할 수 있습니다.
-
OCI 콘솔로 이동하여 개발자 서비스, 컨테이너 및 아티팩트, 컨테이너 레지스트리로 이동하고 저장소 생성을 누릅니다.
-
다음 정보를 입력하고 Create(만들기)를 누릅니다.
- 컴파트먼트에 생성: 이 프로젝트에 대해 생성된 컴파트먼트를 선택합니다.
- 액세스: 공용을 선택합니다.
- 저장소 이름:
springboot/tutorialapp
을 입력합니다.
-
저장소가 생성되면 Oracle 관리 호스트에서 다음 명령을 사용하여 저장소에 액세스합니다.
docker login -u 'tenancy_namespace/domain/username' regionID.ocir.io
Password: xxxxxx
작업 3: ATP(Oracle Autonomous Transaction Processing) 서버리스 데이터베이스 프로비전 및 구성
ATP 데이터베이스에서는 트랜잭션당 수신된 각 SOAP 메시지의 데이터를 저장하며, 대략 각각 밀리초 순서로 병렬 및 순차적 삽입에 참석합니다.
-
OCI 콘솔로 이동하여 Oracle Database로 이동하고 Autonomous Transaction Processing을 누릅니다.
-
Autonomous Database 생성을 누르고 다음 정보를 입력합니다.
- 구획 선택: 이 프로젝트에 대해 생성된 구획을 선택합니다.
- 표시명: 표시명을 입력합니다.
- 데이터베이스 이름 표시: 데이터베이스 이름을 입력합니다.
- 작업 로드 유형 선택: 트랜잭션 처리를 선택합니다.
- 배포 유형 선택: 서버리스를 선택합니다.
- 데이터베이스 구성:
- 개발자: 선택을 해제합니다.
- 데이터베이스 버전 선택: 23ai를 선택합니다.
- ECPU 개수: 2를 입력합니다.
- 컴퓨트 자동 스케일링: 선택합니다.
- 스토리지: 1024GB를 입력합니다.
- 자동 백업 보존 기간(일): 기본 옵션을 60일로 둡니다.
- 관리자 인증서 생성:
- 사용자 이름: 기본적으로
ADMIN
이며 편집할 수 없습니다. - 비밀번호: 선호 비밀번호를 입력합니다.
- 비밀번호 확인: 비밀번호를 다시 입력합니다.
- 사용자 이름: 기본적으로
- 네트워크 액세스 선택: 프라이빗 끝점 액세스만을 선택한 다음 이 프로젝트에 대해 생성된 VCN 및 서브넷을 선택합니다. 이 설정은 지정된 VCN(전용 네트워크)으로만 연결을 제한합니다. 그러나 회사의 필요에 따라 다른 옵션을 선택할 수 있습니다.
ATP 데이터베이스가 실행 중인지 검토합니다.
작업 4: Oracle Autonomous Transaction Processing(ATP)에서 프로젝트 테이블 연결 및 생성
이제 태스크 3에서 생성된 ATP 데이터베이스에서 프로젝트 테이블을 구성, 연결 및 생성해야 합니다.
-
OCI 콘솔로 이동하여 Oracle Database, Autonomous Transaction Processing으로 이동하고 Database Connection을 누릅니다. TLS 인증, TLS를 선택하고 전자 지갑 다운로드를 누릅니다.
-
전자 지갑
.zip
파일의 압축을 풀고tnsnames.ora
에서 데이터 소스 URL을 가져와서 이 데이터베이스에 접속할 수 있습니다. 이 데이터 소스 URL을 저장합니다.예:
tutorialoracleatp_medium = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=xxxxxxxx.adb.sa-saopaulo-1.oraclecloud.com))(connect_data=(service_name=xxxxxxxxxxxxxxx_tutorialoracleatp_medium.adb.oraclecloud.com))(security=(ssl_server_dn_match=no)))
-
이제 데이터베이스에 액세스해야 합니다. ATP가 프로비저닝되면 ORDS(Oracle REST Data Services) 액세스가 사용으로 설정되었습니다. 자세한 내용은 Oracle REST Data Services를 참조하십시오.
Autonomous Database 세부정보 페이지로 이동하여 데이터베이스 작업을 누릅니다. 동일한 VCN(가상 클라우드 네트워크)에서 실행되는 컴퓨트 인스턴스에서만 액세스할 수 있습니다.
-
브라우저에 URL을 붙여넣고 이전에 ATP 데이터베이스에 입력한 사용자 및 비밀번호를 사용하여 ORDS에 액세스한 다음 Oracle SQL Developer Web 모듈에 액세스합니다.
-
다음 질의를 사용하여 수신할 SOAP 메시지와 관련된
USERS
,CARS
및HOUSES
테이블을 생성합니다.CREATE TABLE USERS ( username varchar(50) NOT NULL, userlastname varchar(50) NOT NULL, id int NOT NULL, email varchar(50) NOT NULL, dateuser varchar(50) NOT NULL, attributeuser varchar(50) NOT NULL ); CREATE TABLE CARS ( userid int NOT NULL, brand varchar(50) NOT NULL, color varchar(50) NOT NULL, plate varchar(50) NOT NULL ); CREATE TABLE HOUSES ( userid int NOT NULL, floors int NOT NULL, locationhouse varchar(50) NOT NULL, rooms int NOT NULL, bathrooms int NOT NULL );
작업 5: OCI 대기열 프로비전 및 구성
OCI 대기열에서는 특정 기간 동안 RESTful HTTP API를 통해 높은 트랜잭션 메시지를 저장합니다. 그런 다음 소비자는 메시지를 즉시 또는 편리하게 읽고 삭제할 수 있으므로 분리 및 데이터 손실을 방지할 수 있습니다.
-
OCI 콘솔로 이동하여 개발자 서비스, 애플리케이션 통합으로 이동하고 대기열을 누릅니다.
-
대기열 생성을 누르고 다음 정보를 입력하고 대기열 생성을 누릅니다.
- 이름: 대기열에 적합한 이름을 입력합니다.
- 구획: 작업 컴파트먼트를 선택합니다.
- 대기열 설정: 이 자습서에서는 기본 구성을 선택하지만, 원하는 경우 가시성 시간 초과, 최대 보존 기간, 최대 채널 소비 및 사용 불능 문자 대기열 설정과 같은 비즈니스 요구에 따라 여러 옵션을 사용자정의할 수 있습니다.
- 암호화 설정 구성: Oracle 관리 키를 선택합니다. 단, 고객 관리 키도 옵션입니다.
OCI 대기열이 실행 중인지 검토합니다.
작업 6: Spring Boot를 사용하여 Oracle GraalVM 기반 Java 애플리케이션을 구축하고 OKE에 배포
이제 Spring Boot에서 다음 작업을 수행하는 Oracle GraalVM 기반 Java 애플리케이션을 개발하고 배포할 예정입니다.
-
각 HTTP Post 요청에서 수신된 XML SOAP 메시지에서 데이터를 가져옵니다.
-
ATP에서 트랜잭션당 XML SOAP 메시지에서 추출된 데이터를 삽입합니다.
-
SOAP XML 형식에서 JSON 형식으로 변환합니다.
-
변환된 각 메시지를 OCI 대기열에 넣습니다.
주: 시작하기 전에 필요 조건 - 관리 호스트 및 필요 조건 - 개발 환경 섹션에 표시된 대로 관리 호스트 및 개발 환경을 생성해야 합니다.
관리 호스트 및 개발 환경이 구성되고 준비되면 Spring Boot 프로젝트 개발을 시작할 수 있습니다.
-
Spring initializr로 이동하고 Spring Boot 프로젝트의 폴더 구조 및 기본 파일을 제공하는 첫번째 프로젝트를 생성하여 나중에 요구사항에 따라 수정합니다. 다음 정보를 입력하고 생성을 누릅니다. 그러면 Spring Boot 프로젝트가 자동으로 다운로드되어 개발 호스트에 저장되고 압축이 해제됩니다.
- 프로젝트: Maven을 선택합니다.
- 언어: Java를 선택합니다.
- 스프링 부트: 3.3.6을 선택합니다.
- 프로젝트 메타데이터:
- 그룹:
com.tutorial_springboot
를 입력합니다. - 아티팩트: 자습서를 입력합니다.
- 이름: 자습서를 입력합니다.
- 설명: Spring Boot Application(SOAP 읽기, JSON으로 변환, ATP 삽입 및 OCI 대기열에 넣기)을 입력합니다.
- 그룹:
- 패키징: Jar를 선택합니다.
- Java: 17을 선택합니다.
- 종속성: Oracle 드라이버, 웹 서비스 봄 및 웹 봄을 선택합니다.
주: 필요에 따라 프로젝트에 일부 종속성을 추가하고 나중에
pom.xml
파일에 직접 추가할 수 있습니다. -
이제 스프링 부트 구조 프로젝트가 있습니다.
pom.xml
파일을 검토하면 작업을 시작합니다.이 자습서에서 제안된 범위에 따라 pom.xml 파일을 업데이트합니다.
-
oci sdk
버전 및 다음 종속성을 추가합니다.oci-java-sdk-common
.oci-java-sdk-queue
.oci-java-sdk-addons-oke-workload-identity
.oci-java-sdk-common-httpclient-jersey3
.
애플리케이션은 OCI로 인증하고 OCI Queue와 같은 OCI 서비스를 연결 및 관리해야 합니다.
-
이미
pom.xml
파일은spring-boot-starter-web-services
종속성을 가지며wsdl4j
종속성을 추가해야 합니다. 주요 목적은 SOAP 메시지에서 수신된 데이터를 가져와서 Java 객체에 배치하고, XML 페이로드를 조작하는 스프링 웹 서비스를 생성하고, 계약 우선 SOAP 서비스 개발을 용이하게 하는 것입니다. 또한 포트, URI를 구성하고 XSD(XML Schema Definition) 파일에서 로드된 XML 스키마를 설정할 수 있습니다. -
JSON 종속성을 추가합니다. 이 라이브러리는 SOAP 메시지에서 추출된 데이터로 JSON 형식을 생성하는 데 사용됩니다.
-
Build 섹션에
spring-boot-maven-plugin
플러그인을 추가합니다. 이 플러그인을 사용하면 jar 실행 가능 Spring Boot 프로젝트 파일을 생성할 수 있습니다. -
Build 섹션에
jaxb2-maven-plugin
플러그인을 추가합니다. 이 플러그인은 JAXB(Java API for XML binding)를 사용하여 XML 스키마에서 Java 클래스를 생성하며, 이러한 방식으로 SOAP 메시지의 데이터를 우리가 생성한 Java 클래스 객체로 전달할 수 있습니다.이 플러그인 섹션에서는 XSD 파일이 Spring Boot 프로젝트에 포함된 경로를 나타내는 구성을 배치하는 것이 중요합니다.
<configuration> <sources> <source>${project.basedir}/src/main/resources/messages.xsd<source> </sources> </configuration>
-
종속성 섹션에
jasypt-spring-boot-starter
종속성을 추가하고application.properties
파일에서 중요한 매개변수를 암호화하여 애플리케이션 내에서 안전하게 사용할 수 있도록 하는jasypt-maven-plugin
플러그인을 빌드 섹션에 추가합니다.
pom.xml
파일에 추가된 다음 종속성을 검토합니다. -
-
라이브러리를 다운로드하고 다음 명령을 실행합니다.
-
개발 환경에서 다음 명령을 실행하여 프로젝트에 액세스합니다.
cd tutorial
-
프로젝트를 정리하고 이전 빌드에서 생성한 모든 파일을 제거합니다.
mvn clean
-
로컬 maven 저장소에서 아티팩트를 비우기(삭제 및 선택적으로 재분석)합니다.
mvn dependency:purge-local-repository
-
-
이미 프로젝트에 종속성과
pom.xml
파일이 구성되어 있습니다. SOAP XML 파일은 클라이언트측의 요청을 나타내므로 SOAP XML 파일과 Spring Boot 프로젝트측의 요청을 해석하는 XSD 파일을 검사합니다.-
이 SOAP XML 파일에는 다음 이미지와 같이 요청당 전송할 두 개의 서로 다른 클라이언트에서 가져온 개인 정보 및 기타 속성과 함께 두 개의 메시지가 있습니다.
-
이제 Spring Boot 프로젝트 측에서 Spring 웹 서비스가 자동으로 WSDL로 익스포트하는 웹 서비스 도메인을 정의하기 위해 XML 스키마가 필요합니다. 다음 이미지는 이 자습서에 대해 정의된
messages.xsd
파일을 보여줍니다.messages.xsd:
-
Spring Boot 프로젝트의 resources 폴더에
messages.xsd
파일을 저장합니다.
-
-
jar 파일에 프로젝트 파일을 빌드하고 설치합니다. 다음 명령을 실행하고 Spring Boot 프로젝트 폴더에 있는지 확인합니다.
mvn install
주: maven 설치 명령이 실행되면 대상 폴더가 자동으로 생성되고, 동일한 방식으로 이전에 생성된 XSD 파일 및 프로젝트의 실행 파일
.jar
파일에 따라 Java 클래스가 생성됩니다. -
이제 Spring Boot 프로젝트에 필요한 Java 클래스를 추가할 수 있습니다.
WebServiceConfig.java Class:
이 Java 클래스는 SOAP 웹 서비스를 생성하기 위해 개발되었습니다.- SOAP 요청을 처리하도록 서블릿을 설정합니다.
- XML 스키마를 기반으로 WSDL 정의를 생성합니다.
- SOAP 웹 서비스의 액세스 끝점을 정의합니다.
- classpath의
messages.xsd
스키마 파일을 사용합니다.
//Imports import org.springframework.boot.web.servlet.ServletRegistrationBean; //import the ServletRegistrationBean class import org.springframework.context.ApplicationContext; //import the ApplicationContext class import org.springframework.context.annotation.Bean; //import the Bean class import org.springframework.context.annotation.Configuration; //import the Configuration class import org.springframework.core.io.ClassPathResource; //import the ClassPathResource class import org.springframework.ws.config.annotation.EnableWs; //import the EnableWs class import org.springframework.ws.config.annotation.WsConfigurerAdapter; //import the WsConfigurerAdapter class import org.springframework.ws.transport.http.MessageDispatcherServlet; //import the MessageDispatcherServlet class import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; //import the DefaultWsdl11Definition class import org.springframework.xml.xsd.SimpleXsdSchema; //import the SimpleXsdSchema class import org.springframework.xml.xsd.XsdSchema; //import the XsdSchema class //Configuration class for the Web Service configuration @EnableWs //Enable the Web Service @Configuration //Define the class as a Configuration class public class WebServiceConfig extends WsConfigurerAdapter { //Create a ServletRegistrationBean object to register the MessageDispatcherServlet object with the application context @Bean public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext) { MessageDispatcherServlet servlet = new MessageDispatcherServlet(); //Create a MessageDispatcherServlet object servlet.setApplicationContext(applicationContext); //Set the application context for the MessageDispatcherServlet object servlet.setTransformWsdlLocations(true); //Set the transformWsdlLocations property to true return new ServletRegistrationBean<>(servlet, "/ws/*"); //Return a new ServletRegistrationBean object with the MessageDispatcherServlet object and the URL pattern } //Create a DefaultWsdl11Definition object to define the WSDL @Bean(name = "messages") public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema messagesSchema) { DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); //Create a DefaultWsdl11Definition object wsdl11Definition.setPortTypeName("MessagesPort"); //Set the port type name wsdl11Definition.setLocationUri("/ws"); //Set the location URI wsdl11Definition.setTargetNamespace("http://tutorial_example.com/ns0"); //Set the target namespace wsdl11Definition.setSchema(messagesSchema); //Set the schema return wsdl11Definition; //Return the DefaultWsdl11Definition object } //Create a XsdSchema object to define the schema @Bean public XsdSchema messagesSchema() { return new SimpleXsdSchema(new ClassPathResource("messages.xsd")); //Return a new SimpleXsdSchema object with the messages.xsd file } }
주: 웹 서비스를 테스트하려면 다음과 같이 동일한 로컬 개발 환경 데스크톱에서 Spring Boot 프로젝트를 실행하고
curl
를 사용하여 HTTP 요청을 전송할 수 있습니다.mvn spring-boot:run
프로젝트가 실행 중이고 웹 서비스가 작동되면 다음과 같이
curl
를 사용하여 로컬 SOAP HTTP 요청을 실행합니다.curl --location 'http://localhost:8080/ws/'
그리고 당신은 우리의 봄 부팅 프로젝트에 노출 된 웹 서비스에서 응답을 얻을 것이다.
-
model
이라는 폴더를 생성합니다. 이 폴더에는 다음 Java 클래스가 추가됩니다.주: 이러한 Java 클래스
Car
,House
및User
는 HTTP SOAP 요청에서 추출된 각 SOAP 메시지의 데이터를 기반으로 정보를 검색합니다.-
Car.java class:
이 Java 클래스는 각 사용자에 링크된 속성을 가진 Car 객체를 나타냅니다.``` //Imports import org.springframework.stereotype.Component; // For component scanning import org.springframework.context.annotation.Scope; // For defining bean scope @Component // Marks a class as a Spring-managed component @Scope("prototype") //A new instance is created every time the bean is requested public class Car { //Attributes private String brand; private String color; private String plate; //"getter" and "setter" methods to get and set the information in each object public String getBrand(){ return brand; } public void setBrand(String brand){ this.brand = brand; } public String getColor(){ return color; } public void setColor(String color){ this.color = color; } public String getPlate(){ return plate; } public void setPlate(String plate){ this.plate = plate; } } ```
-
House.java class:
이 Java 클래스는 각 유저에 연결된 속성을 가진 House 객체를 나타냅니다.//Imports import org.springframework.stereotype.Component; // For component scanning import org.springframework.context.annotation.Scope; // For defining bean scope @Component // Marks a class as a Spring-managed component @Scope("prototype") //A new instance is created every time the bean is requested public class House { //Attributes private int floors; private String location; private int rooms; private int bathrooms; //"getter" and "setter" methods to get and set the information in each object public int getFloors(){ return floors; } public void setFloors(int floors){ this.floors = floors; } public String getLocation(){ return location; } public void setLocation(String location){ this.location = location; } public int getRooms(){ return rooms; } public void setRooms(int rooms){ this.rooms = rooms; } public int getBathRooms(){ return bathrooms; } public void setBathRooms(int bathrooms){ this.bathrooms = bathrooms; } }
-
User.java class:
이 Java 클래스는 Car 및 House 객체를 포함하는 해당 속성을 가진 User 객체를 나타냅니다.//Imports import org.springframework.stereotype.Component; // For component scanning import org.springframework.context.annotation.Scope; // For defining bean scope @Component // Marks a class as a Spring-managed component @Scope("prototype") //A new instance is created every time the bean is requested public class User { //Attributes private String username; private String userlastname; private int id; private String email; private String date; private String attribute; private Car car; private House house; //"getter" and "setter" methods to get and set the information in each object public String getUserName(){ return username; } public void setUserName(String username){ this.username = username; } public String getUserLastName(){ return userlastname; } public void setUserLastName(String userlastname){ this.userlastname = userlastname; } public int getID(){ return id; } public void setID(int id){ this.id = id; } public String getEmail(){ return email; } public void setEmail(String email){ this.email = email; } public String getDate(){ return date; } public void setDate(String date){ this.date = date; } public String getAttribute(){ return attribute; } public void setAttribute(String attribute){ this.attribute = attribute; } public Car getCar(){ return car; } public void setCar(Car car){ this.car = car; } public House getHouse(){ return house; } public void setHouse(House house){ this.house = house; } }
-
-
-
이제 획득한 데이터를 OCI ATP 데이터베이스에 저장하기 위해 Spring Boot 프로젝트에서 필요한 매개변수를 구성합니다.
resources
폴더에서 애플리케이션에 필요한 매개변수를 추가하는 데 사용되는application.properties
파일을 찾아야 합니다. 응용 프로그램이 시작되면 자동으로 생성되고 Spring Boot에 의해 로드됩니다.참고: 암호 또는 관련 데이터와 같은 중요한 정보를 해커가 추출하거나 볼 수 없도록 암호화 및 보안 방법을 관리하는 것이 중요합니다. 이 자습서에서는
pom.xml
파일에 구성된jasypt
라이브러리를 사용합니다. 자세한 내용은 Jasypt를 사용하여 Spring Boot 프로젝트에서 암호를 암호화하는 방법을 참조하십시오. 또한 Spring Boot의 Java 클래스에서는 이 라이브러리와 관련된 주석 및 소스 코드를 추가하여application.properties
매개변수를 해독할 수 있는 위치에 대해 설명합니다.다음 이미지와 같이 ATP 데이터베이스에 필요한 적절한 매개변수를
application.properties
파일에 추가합니다.Spring Boot Java 클래스를 생성하여 데이터베이스에 각 메시지를 저장합니다. 이 클래스는 다음 이미지와 같이
database
폴더에 저장됩니다.-
SoapObjectRepository.java:
이 Spring Boot Java 클래스는 JDBC 드라이버를 사용하여 ATP의 각 메시지를 실시간으로 트랜잭션 형식으로 삽입할 수 있습니다.//Java Classes USER, CAR, HOUSE Imports import com.oracle_springboot_tutorial.tutorial.model.*; //Spring Boot Imports import org.springframework.stereotype.Repository; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.beans.factory.annotation.Autowired; //Repository Class to save SOAP Messages in the Database @Repository public class SoapObjectRepository { private JdbcTemplate template; private User user; //Getters and Setters for JdbcTemplate template object public JdbcTemplate getTemplate(){ return template; } //Autowired annotation to inject JdbcTemplate object into the template object @Autowired public void setTemplate(JdbcTemplate template){ this.template = template; } //Method to save User SOAP Message in the Database public void saveUserSOAPMessage(User user){ this.user = user; String sql = "INSERT INTO USERS (username, userlastname, id, email, dateuser, attributeuser) VALUES(?, ?, ?, ?, ?, ?)"; template.update(sql, user.getUserName(), user.getUserLastName(), user.getID(), user.getEmail(), user.getDate(), user.getAttribute()); } //Method to save Car SOAP Message in the Database public void saveCarSOAPMessage(Car car){ String sql = "INSERT INTO CARS (userid, brand, color, plate) VALUES(?, ?, ?, ?)"; template.update(sql, user.getID(), car.getBrand(), car.getColor(), car.getPlate()); } //Method to save House SOAP Message in the Database public void saveHouseSOAPMessage(House house){ String sql = "INSERT INTO HOUSES (userid, floors, locationhouse, rooms, bathrooms) VALUES(?, ?, ?, ?, ?)"; template.update(sql, user.getID(), house.getFloors(), house.getLocation(), house.getRooms(), house.getBathRooms()); } }
이제 다음 이미지와 같이 먼저
json_message
폴더와 해당 Java Spring Boot 클래스를 생성하는 JSON 소프트웨어 코드를 추가합니다. -
JsonBuilder.java:
이 Spring Boot Java 클래스는 SOAP XML 형식에서 JSON 형식으로 변환됩니다.//Imports to be used for JSON import org.json.JSONArray; import org.json.JSONObject; //Imports to be used for the User class import com.oracle_springboot_tutorial.tutorial.model.*; //Imports to be used for the ArrayList class import java.util.ArrayList; public class JsonBuilder { //The buildJsonMessage method creates a JSON object from the ArrayList of User objects public JSONObject buildJsonMessage(ArrayList<User> usersMessageArray) { JSONObject rootJson = new JSONObject(); //Create a new JSON object called rootJson JSONObject messagesJson = new JSONObject(); //Create a new JSON object called messagesJson JSONArray messageArray = new JSONArray(); //Create a new JSON array called messageArray //Iterate through the ArrayList of User objects and create a JSON object for each User object in the ArrayList for (User user : usersMessageArray) { JSONObject messageJson = new JSONObject(); messageJson.put("username", user.getUserName()); //Add the username of the user to the messageJson object messageJson.put("userlastname", user.getUserLastName()); //Add the userlastname of the user to the messageJson object messageJson.put("id", user.getID()); //Add the id of the user to the messageJson object messageJson.put("email", user.getEmail()); //Add the email of the user to the messageJson object messageJson.put("date", user.getDate()); //Add the date of the user to the messageJson object messageJson.put("attribute", user.getAttribute()); //Add the attribute of the user to the messageJson object // JSONObject bodyJson = new JSONObject(); //Create a new JSON object called bodyJson JSONObject envelopeJson = new JSONObject(); //Create a new JSON object called envelopeJson //Switch statement to check the attribute of the User object switch (user.getAttribute()) { case "CAR": Car car = user.getCar(); envelopeJson.put("brand", car.getBrand()); //Add the brand of the car to the envelopeJson object envelopeJson.put("color", car.getColor()); //Add the color of the car to the envelopeJson object envelopeJson.put("plate", car.getPlate()); //Add the plate of the car to the envelopeJson object break; case "HOUSE": House house = user.getHouse(); envelopeJson.put("floors", house.getFloors()); //Add the floors of the house to the envelopeJson object envelopeJson.put("location", house.getLocation()); //Add the location of the house to the envelopeJson object envelopeJson.put("rooms", house.getRooms()); //Add the rooms of the house to the envelopeJson object envelopeJson.put("bathrooms", house.getBathRooms()); //Add the bathrooms of the house to the envelopeJson object break; default: System.out.println("Unknown subject: " + user.getAttribute()); } bodyJson.put("envelope", envelopeJson); //Add the envelopeJson object to the bodyJson object messageJson.put("body", bodyJson); //Add the bodyJson object to the messageJson object messageArray.put(messageJson); //Add the messageJson object to the messageArray array } messagesJson.put("message", messageArray); //Add the messageArray array to the messagesJson object rootJson.put("messages", messagesJson); //Add the messagesJson object to the rootJson object return rootJson; } }
-
-
이제 JSON 형식의 메시지를 OCI Queue로 전송할 수 있습니다. 다음 이미지와 같이
oci_queue
폴더 및 해당 Java Spring Boot 클래스를 생성합니다.주:
OCIQueue.java
클래스에서는 OKE에서 OCI 대기열로의 액세스를 정의해야 합니다. 이 사용지침서에서는 워크로드 액세스를 사용하여 테넌시와 연관된 사용자, 비밀번호, OCID와 같은 민감한 정보를 처리할 필요 없이 OCI 리소스에 대한 액세스 권한을 부여합니다. 자세한 내용은 OCI 리소스에 워크로드 액세스 권한 부여를 참고하세요.OCIQueue.java
클래스 개발을 시작하기 전에 테넌시에서 워크로드 액세스를 구성합니다. 먼저 Oracle GraalVM 기반 Java 애플리케이션과 연결할 네임스페이스를 생성해야 합니다. admin 호스트에 있는지 확인합니다.kubectl create ns-tutorial
그런 다음 애플리케이션에 대한 Kubernetes 서비스 계정을 생성합니다.
kubectl create serviceaccount tutorialserviceaccount --namespace ns-tutorial
이제 워크로드가 필요한 OCI 리소스에 액세스할 수 있도록 OCI IAM 정책을 정의합니다. 이 자습서에서는 OCI 대기열입니다.
OCI 콘솔로 이동하여 ID 및 보안, 정책으로 이동하고 정책 생성을 누릅니다. 다음 정보를 입력하고 Create(만들기)를 누릅니다.
- 이름: 선호 정책 이름을 입력합니다.
- 설명: Access from oke to oci queue를 입력합니다.
-
정책 작성기:
Allow any-user to use queues in compartment id ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx where all {request.principal.type = 'workload', request.principal.namespace = 'ns-tutorial', request.principal.service_account = 'tutorialserviceaccount', request.principal.cluster_id = 'ocid1.cluster.oc1.sa-saopaulo-1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
작업 로드 액세스 정책, 네임스페이스 및 서비스 계정을 구성한 후에는 계속할 수 있습니다.
application.properties
파일에서 작업 5에서 생성된 특정 OCI 대기열을 접속하고 관리하는 데 필요한 대기열 매개변수를 추가합니다.-
OCIQueue.java:
이 Spring Boot Java 클래스는 OCI Queue에 액세스하여 메시지를 저장할 수 있게 해줍니다.//Imports import com.oracle.bmc.auth.okeworkloadidentity.OkeWorkloadIdentityAuthenticationDetailsProvider; //Import OkeWorkloadIdentityAuthenticationDetailsProvider to enable access and use OCI Workload Identity import com.oracle.bmc.queue.QueueClient; //Import QueueClient to have access and manage of OCI Queue import com.oracle.bmc.queue.model.PutMessagesDetails; //Import PutMessagesDetails to send messages to the OCI Queue import com.oracle.bmc.queue.model.PutMessagesDetailsEntry; //Import PutMessagesDetailsEntry to send messages to the OCI Queue import com.oracle.bmc.queue.requests.PutMessagesRequest; //Import PutMessagesRequest to send messages to the OCI Queue //Imports for the ArrayList and List import java.util.ArrayList; import java.util.List; public class OCIQueue { //Set the required parameters to access to OCI and the Queue //Variables private String queueId; private String endPoint; private String region; //Constructor to initialize the OCI Queue object with the required parameters public OCIQueue(String queueId, String endPoint, String region){ this.queueId = queueId; this.endPoint = endPoint; this.region = region; } //The sendMessages method sends a message to the OCI Queue public void sendMessages(String jsonMessage){ try{ //Create an OkeWorkloadIdentityAuthenticationDetailsProvider object to authenticate the OCI Queue OkeWorkloadIdentityAuthenticationDetailsProvider provider = new OkeWorkloadIdentityAuthenticationDetailsProvider.OkeWorkloadIdentityAuthenticationDetailsProviderBuilder().build(); //Create a QueueClient object to send the message to the OCI Queue QueueClient queueClient = QueueClient.builder().build(provider); queueClient.setRegion(region); queueClient.setEndpoint(endPoint); //Create a PutMessagesDetailsEntry object to send the message PutMessagesDetailsEntry message = PutMessagesDetailsEntry.builder() .content(jsonMessage) .build(); //Create a List of PutMessagesDetailsEntry objects to send the message List<PutMessagesDetailsEntry> messages = new ArrayList<>(); messages.add(message); //Create a PutMessagesDetails object to send the message PutMessagesDetails putMessagesDetails = PutMessagesDetails.builder() .messages(messages) .build(); // Create a PutMessagesRequest object to send the message PutMessagesRequest putMessagesRequest = PutMessagesRequest.builder() .queueId(queueId) .putMessagesDetails(putMessagesDetails) .build(); // Send the request and get the response queueClient.putMessages(putMessagesRequest); }catch(Exception e){ System.out.println("Exception sending message to OCI Queue: "+e); } } }
-
데이터베이스, JSON 및 OCI 대기열에 대한 Spring Boot Java 클래스가 있으면
MessagesEndpoint.java
클래스를 진행할 수 있습니다.이를 위해
endpoint
및 해당 Spring Boot Java 클래스라는 폴더를 생성합니다.주:
MessagesEndpoint.java
에서는 자동 생성된 일부 클래스를 임포트해야 합니다. 이렇게 하려면pom.xml
파일의 Configuration 섹션에서 다음 소스를 추가합니다.<configuration> <sources> <source>${project.build.directory}/generated-sources</source> </sources> </configuration>
pom.xml
파일은 다음과 같아야 합니다.-
MessagesEndpoint.java:
이 Spring Boot Java 클래스의 목적은 SOAP HTTP 요청을 추출하고 해당 값을 각 메시지의 User, Car 및 House Java 객체에 매핑하는 것입니다. 그런 다음 추출된 데이터를 각 SOAP XML 트랜잭션에 대한 ATP 데이터베이스에 저장하고, XML에서 JSON 형식으로 데이터를 변환하고, OCI 대기열에 메시지를 배치합니다. 이러한 메시지는 나중에 소비자가 대기열에서 검색하고 삭제할 수 있습니다.//Imports import com.oracle_springboot_tutorial.tutorial.model.*; //Import all the classes from the model package import com.oracle_springboot_tutorial.tutorial.oci_queue.OCIQueue; //Import the OCIQueue class from the oci_queue package import com.tutorial_example.ns0.Messages;//Import the Messages class from the tutorial_example.ns0 package (Auto generated Java Classes from the WSDL) import com.tutorial_example.ns0.MessageType; //Import the MessageType class from the tutorial_example.ns0 package (Auto generated Java Classes from the WSDL) //Import the ArrayList class from the java.util package import java.util.ArrayList; //Spring Boot imports to be used for the SOAP Web Service import org.springframework.beans.factory.annotation.Autowired; //Import the @Autowired annotation to inject the SoapObjectRepository object import org.springframework.beans.factory.annotation.Value; //Import the @Value annotation to inject the values from the application.properties file import org.springframework.stereotype.Component; //Import the @Component annotation to register the class with Spring //Spring Boot imports import org.springframework.ws.server.endpoint.annotation.Endpoint; //Import the @Endpoint annotation to register the class with Spring WS import org.springframework.ws.server.endpoint.annotation.PayloadRoot; //Import the @PayloadRoot annotation to specify the namespace URI and local part of the request payload import org.springframework.ws.server.endpoint.annotation.RequestPayload; //Import the @RequestPayload annotation to map the request payload to the method parameter import org.springframework.ws.server.endpoint.annotation.ResponsePayload; //Import the @ResponsePayload annotation to map the returned value to the response payload //Imports to be used storing SOAP information in the database import com.oracle_springboot_tutorial.tutorial.database.SoapObjectRepository; //Import the SoapObjectRepository class from the database package //Imports to be used for JSON import com.oracle_springboot_tutorial.tutorial.json_message.JsonBuilder; //Import the JsonBuilder class from the json_message package import org.json.JSONObject; //Import the JSONObject class from the org.json package //The @Endpoint annotation registers the class with Spring WS. //The @Component annotation registers the class with Spring to be used as a Spring Bean. @Endpoint @Component public class MessagesEndpoint { //Inject not encrypted and decrypted values using jasypt library from the application.properties file @Value("${oci.queue.queueId}") private String queueId; @Value("${oci.queue.endPoint}") private String endPoint; @Value("${oci.queue.region}") private String region; @Value("${spring.datasource.password}") private String datasourcePassword; //The @Autowired loads JDBC template in SoapObjectRepository. @Autowired private SoapObjectRepository soapObjectRepository = new SoapObjectRepository(); //Create a new instance of the JsonBuilder class JsonBuilder jsonBuilder = new JsonBuilder(); //The namespace URI private static final String NAMESPACE_URI = "http://tutorial_example.com/ns0"; //The handleMessagesRequest method is annotated with @PayloadRoot, which means that it is invoked when a request with the specified namespace URI and local part is received. @PayloadRoot(namespace = NAMESPACE_URI, localPart = "messages") //The @ResponsePayload annotation makes Spring WS map the returned value to the response payload. @ResponsePayload //The handleMessagesRequest method processes the request and sends the message to the OCI Queue. public void handleMessagesRequest(@RequestPayload Messages request) { OCIQueue ociQueue = new OCIQueue(queueId, endPoint, region); //Create an ArrayList to store the users ArrayList<User> usersMessageArray = new ArrayList<User>(); //Iterate over the messages, extracting the SOAP Messages and storing in the Java Objects (Car, House, User) for (MessageType message : request.getMessage()) { User user = new User(); user.setUserName(message.getUsername()); user.setUserLastName(message.getUserlastname()); user.setID(message.getId()); user.setEmail(message.getEmail()); user.setDate(message.getDate()); user.setAttribute(message.getAttribute()); //Insert User in Oracle ATP soapObjectRepository.saveUserSOAPMessage(user); //Process the attributes Car or House depending of the kind of User processMessage(user, message); //Add the user to the ArrayList usersMessageArray.add(user); } //Convert to JSON format JSONObject jsonObject = jsonBuilder.buildJsonMessage(usersMessageArray); //Send the JSON message to OCI Queue ociQueue.sendMessages(jsonObject.toString()); } //The processMessage method processes the message based on the user's attribute. private void processMessage(User user, MessageType message) { String subject = user.getAttribute(); switch (subject) { case "CAR": handleCAR(user, message); break; case "HOUSE": handleHouse(user, message); break; default: System.out.println("Unknown subject: " + subject); } } //The handleCAR method processes the CAR message. private void handleCAR(User user, MessageType message) { Car car = new Car(); car.setBrand(message.getBody().getEnvelope().getBrand()); car.setColor(message.getBody().getEnvelope().getColor()); car.setPlate(message.getBody().getEnvelope().getPlate()); user.setCar(car); //Insert Car in Oracle ATP soapObjectRepository.saveCarSOAPMessage(user.getCar()); } //The handleHouse method processes the HOUSE message. private void handleHouse(User user, MessageType message) { House house = new House(); house.setFloors(message.getBody().getEnvelope().getFloors()); house.setLocation(message.getBody().getEnvelope().getLocation()); house.setRooms(message.getBody().getEnvelope().getRooms()); house.setBathRooms(message.getBody().getEnvelope().getBathrooms()); user.setHouse(house); //Insert Houses in Oracle ATP soapObjectRepository.saveHouseSOAPMessage(user.getHouse()); } }
-
-
이제 Spring Boot 프로젝트의 전체 구성을 완료했으므로 프로젝트 폴더에
Dockerfile
를 만듭니다.
-
Dockerfile
:FROM container-registry.oracle.com/graalvm/jdk:17 WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
주: Docker 파일의 첫번째 행은 Oracle의 컨테이너 레지스트리에서 GraalVM JDK 이미지를 기본 이미지로 가져와서 설정합니다. 처음부터 최적화된 실행을 위해 JIT(Just-In-Time) 컴파일을 활용하여 고성능 JDK를 제공합니다.
-
다음 명령을 실행하여 로컬 Docker 저장소에서 프로젝트 이미지를 빌드하고 푸시합니다.
docker build . -t springbootapp:latest
-
다음 명령을 실행하여 로컬 Docker 저장소의 이미지를 확인합니다.
docker images
-
OCI Container Registry Classic 저장소의 전체 경로로 Spring Boot 애플리케이션 이미지에 태그를 지정할 수 있습니다.
docker tag springbootapp:latest gru.ocir.io/xxxxxxxxxx/springboot/tutorialapp:latest
-
다음 명령을 실행하여 로컬 Docker 저장소에서 확인합니다.
docker images
-
다음 명령을 실행하여 OCI Container Registry Classic에 이미지를 푸시합니다.
docker push gru.ocir.io/xxxxxxxxxx/springboot/tutorialapp:latest
-
OCI Container Registry Classic에서 OKE 이미지 애플리케이션을 검토하려면 개발자 서비스, 컨테이너 및 아티팩트로 이동하고 컨테이너 레지스트리를 누릅니다.
이미지가 OCI Container Registry Classic에 있으면 개발 환경으로 이동하여 OKE에 이 이미지를 배치할 수 있습니다. 이 자습서에서는 다음 명령을 실행하여 필요한 구성을 만듭니다.
주: 네임스페이스 및 서비스 계정이 이전에 구성되었으므로 암호가 필요합니다.
-
다음 명령을 실행하여 프로젝트 폴더에 액세스합니다.
cd tutorial/
-
다음 명령을 실행하여 OKE에 대한 암호를 만듭니다.
kubectl create secret -n ns-tutorial generic ocir --from-file=.dockerconfigjson=../.docker/config.json --type=kubernetes.io/dockerconfigjson
-
-
OKE 환경이 이미 준비되어 있으므로 OCI Container Registry Classic에서 OKE로 애플리케이션 이미지를 배포하십시오.
주: 응용 프로그램 이미지를 배치하려면 매니페스트 파일이 있어야 합니다. 이 사용지침서에서는 다음
yaml
파일이 매니페스트 파일입니다. 이 파일은 애플리케이션을 배치하고80
포트를 사용하여 수신 중인 OCI 로드 밸런서에 표시되는 수신 서비스를 생성하는 데 사용됩니다.-
springboot_application.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: soap-oci-queue-app namespace: ns-tutorial labels: app: soap-oci-queue-app spec: replicas: 6 selector: matchLabels: app: soap-oci-queue-app template: metadata: labels: app: soap-oci-queue-app spec: serviceAccountName: tutorialserviceaccount automountServiceAccountToken: true containers: - name: soap-oci-queue-app image: gru.ocir.io/xxxxxxxxxxxx/springboot/tutorialapp:latest ports: - containerPort: 8080 imagePullSecrets: - name: ocir-docker-config --- apiVersion: v1 kind: Service metadata: name: svc-dev-app namespace: ns-tutorial spec: selector: app: soap-oci-queue-app ports: - port: 80 targetPort: 8080 type: LoadBalancer
-
-
매니페스트 파일을 저장한 폴더에서
kubectl
명령을 실행합니다.kubectl apply -f springboot_application.yaml
이제 애플리케이션이 배포되고 수신 로드 밸런서 서비스가 OKE에 생성됩니다.
-
OKE에서 생성된 Pod 및 서비스를 검증하려면 다음 명령을 실행합니다.
kubectl get pods -A
kubectl get svc -A
주: tutorial.zip에서 Spring Boot Oracle GraalVM 기반 Java 애플리케이션 프로젝트를 다운로드하십시오.
작업 7: JMeter를 사용하여 Spring Boot Oracle Graal VM 애플리케이션 테스트
JMeter 설치에 대한 자세한 내용은 Getting Started with JMeter를 참조하십시오.
JMeter가 설치되고 구성되면 HTTP POST SOAP 요청을 전송할 수 있습니다. 예를 들어, 스레드 수를 2로 설정하여 동시 사용자 또는 응용 프로그램 2개를 나타내고, Loop Count를 3000으로 설정하면 각 사용자 또는 응용 프로그램이 총 6000개의 SOAP 요청에 대해 3000개의 요청을 보냅니다.
JMeter에서 OCI 로드 밸런서 IP, Spring Boot 프로젝트에 구성된 경로 및 본문의 SOAP XML을 설정합니다.
6000개의 SOAP 트랜잭션을 사용하여 JMeter를 실행하고 확인합니다.
주: 클라이언트 응용 프로그램의 SOAP 메시징을 시뮬레이트할 때 각 SOAP HTTP 요청에 대해 정보는 위에 표시된 SOAP XML 파일에 표시된 것과 동일하며 변경되지는 않지만 실제 고객 환경에서는 정보가 확실히 다를 수 있습니다.
다음 명령문을 실행합니다.
-
ATP에 저장된 총 데이터를 확인합니다.
-
ATP의 각 테이블에 저장된 데이터의 상세내역을 조회합니다.
-
자동차:
-
주택들:
-
USERS:
-
-
OCI 대기열에 저장된 총 OCI 대기열 요청을 봅니다.
-
OCI 대기열의 메시지 세부정보를 JSON 형식으로 보려면 다음을 수행합니다.
확인
- 작성자 - Iván Alexander Vásquez Chinome(Oracle LAD A-Team Cloud 솔루션 전문가)
추가 학습 자원
docs.oracle.com/learn에서 다른 실습을 탐색하거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하세요. 또한 Oracle Learning Explorer가 되려면 education.oracle.com/learning-explorer을 방문하십시오.
제품 설명서는 Oracle Help Center를 참조하십시오.
Create an Oracle GraalVM based Java Application using Spring Boot on OKE to Store SOAP Messages in ATP and Send to OCI Queue
G27168-01
February 2025
Copyright ©2025, Oracle and/or its affiliates.