1. ওভারভিউ
এই ল্যাবটি একটি কন্টেইনারাইজড পরিবেশে জাভা অ্যাপ্লিকেশন বিকাশের দায়িত্বপ্রাপ্ত সফ্টওয়্যার ইঞ্জিনিয়ারদের জন্য ডেভেলপমেন্ট ওয়ার্কফ্লোকে প্রবাহিত করার জন্য ডিজাইন করা বৈশিষ্ট্য এবং ক্ষমতা প্রদর্শন করে। সাধারণ কন্টেইনার ডেভেলপমেন্টের জন্য ব্যবহারকারীকে কন্টেইনারের বিবরণ এবং কন্টেইনার তৈরির প্রক্রিয়া বুঝতে হবে। উপরন্তু, ডেভেলপারদের সাধারণত তাদের প্রবাহ ভাঙতে হয়, দূরবর্তী পরিবেশে তাদের অ্যাপ্লিকেশন পরীক্ষা ও ডিবাগ করতে তাদের IDE থেকে বেরিয়ে যেতে হয়। এই টিউটোরিয়ালে উল্লিখিত টুলস এবং প্রযুক্তির সাহায্যে, ডেভেলপাররা তাদের IDE না রেখেই কন্টেইনারাইজড অ্যাপ্লিকেশনের সাথে কার্যকরভাবে কাজ করতে পারে।
যা শিখবেন
এই ল্যাবে আপনি জিসিপি-তে কন্টেইনারগুলি সহ বিকাশের পদ্ধতিগুলি শিখবেন:
- সেটআপ এবং প্রয়োজনীয়তা
- একটি নতুন জাভা স্টার্টার অ্যাপ্লিকেশন তৈরি করা হচ্ছে
- উন্নয়ন প্রক্রিয়ার মধ্য দিয়ে হাঁটছি
- একটি সাধারণ CRUD বিশ্রাম পরিষেবা বিকাশ করা হচ্ছে
- ক্লিনআপ
2. সেটআপ এবং প্রয়োজনীয়তা
স্ব-গতিসম্পন্ন পরিবেশ সেটআপ
- Google ক্লাউড কনসোলে সাইন-ইন করুন এবং একটি নতুন প্রকল্প তৈরি করুন বা বিদ্যমান একটি পুনরায় ব্যবহার করুন৷ আপনার যদি ইতিমধ্যেই একটি Gmail বা Google Workspace অ্যাকাউন্ট না থাকে, তাহলে আপনাকে অবশ্যই একটি তৈরি করতে হবে।
- প্রকল্পের নাম এই প্রকল্পের অংশগ্রহণকারীদের জন্য প্রদর্শনের নাম। এটি একটি অক্ষর স্ট্রিং যা Google API দ্বারা ব্যবহৃত হয় না এবং আপনি যে কোনো সময় এটি আপডেট করতে পারেন।
- সমস্ত Google ক্লাউড প্রজেক্ট জুড়ে প্রোজেক্ট আইডি অবশ্যই অনন্য হতে হবে এবং অপরিবর্তনীয় (সেট করার পরে পরিবর্তন করা যাবে না)। ক্লাউড কনসোল স্বয়ংক্রিয়ভাবে একটি অনন্য স্ট্রিং তৈরি করে; সাধারণত আপনি এটা কি যত্ন না. বেশিরভাগ কোডল্যাবে, আপনাকে প্রজেক্ট আইডি উল্লেখ করতে হবে (এবং এটি সাধারণত
PROJECT_ID
হিসাবে চিহ্নিত করা হয়), তাই আপনি যদি এটি পছন্দ না করেন তবে অন্য একটি এলোমেলো তৈরি করুন, অথবা, আপনি নিজের চেষ্টা করে দেখতে পারেন এটি উপলব্ধ কিনা। তারপর প্রকল্প তৈরি হওয়ার পরে এটি "হিমায়িত" হয়। - একটি তৃতীয় মান আছে, একটি প্রকল্প নম্বর যা কিছু API ব্যবহার করে। ডকুমেন্টেশনে এই তিনটি মান সম্পর্কে আরও জানুন।
- এরপরে, ক্লাউড রিসোর্স/এপিআই ব্যবহার করার জন্য আপনাকে ক্লাউড কনসোলে বিলিং সক্ষম করতে হবে। এই কোডল্যাবের মাধ্যমে চালানোর জন্য খুব বেশি খরচ করা উচিত নয়, যদি কিছু থাকে। রিসোর্স বন্ধ করতে যাতে আপনি এই টিউটোরিয়ালের বাইরে বিলিং করতে না পারেন, কোডল্যাবের শেষে পাওয়া যেকোনো "ক্লিন-আপ" নির্দেশাবলী অনুসরণ করুন। Google ক্লাউডের নতুন ব্যবহারকারীরা $300 USD বিনামূল্যের ট্রায়াল প্রোগ্রামের জন্য যোগ্য৷
ক্লাউডশেল এডিটর শুরু করুন
এই ল্যাবটি ডিজাইন করা হয়েছে এবং Google ক্লাউড শেল এডিটরের সাথে ব্যবহারের জন্য পরীক্ষা করা হয়েছে। সম্পাদক অ্যাক্সেস করতে,
- https://console.cloud.google.com- এ আপনার গুগল প্রকল্প অ্যাক্সেস করুন।
- উপরের ডানদিকের কোণায় ক্লাউড শেল এডিটর আইকনে ক্লিক করুন
- আপনার উইন্ডোর নীচে একটি নতুন ফলক খুলবে
- Open Editor বাটনে ক্লিক করুন
- সম্পাদকটি ডানদিকে একটি এক্সপ্লোরার এবং কেন্দ্রীয় অঞ্চলে সম্পাদকের সাথে খুলবে৷
- স্ক্রিনের নীচে একটি টার্মিনাল ফলকও পাওয়া উচিত
- টার্মিনাল খোলা না থাকলে একটি নতুন টার্মিনাল উইন্ডো খুলতে `ctrl+`` এর কী সমন্বয় ব্যবহার করুন
gCloud সেট আপ করুন
ক্লাউড শেল-এ, আপনার প্রজেক্ট আইডি এবং যে অঞ্চলে আপনি আপনার অ্যাপ্লিকেশন স্থাপন করতে চান সেটি সেট করুন। সেগুলিকে PROJECT_ID
এবং REGION
ভেরিয়েবল হিসাবে সংরক্ষণ করুন৷
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
সোর্স কোড পান
এই ল্যাবের সোর্স কোডটি GitHub-এ GoogleCloudPlatform-এর কন্টেইনার-ডেভেলপার-ওয়ার্কশপে অবস্থিত। নীচের কমান্ড দিয়ে এটি ক্লোন করুন তারপর ডিরেক্টরিতে পরিবর্তন করুন।
git clone https://github.com/GoogleCloudPlatform/container-developer-workshop.git
cd container-developer-workshop/labs/spring-boot
এই ল্যাবে ব্যবহৃত অবকাঠামোর ব্যবস্থা করুন
এই ল্যাবে আপনি GKE-তে কোড স্থাপন করবেন এবং একটি CloudSql ডাটাবেসে সংরক্ষিত ডেটা অ্যাক্সেস করবেন। নিচের সেটআপ স্ক্রিপ্টটি আপনার জন্য এই পরিকাঠামো প্রস্তুত করে। প্রভিশনিং প্রক্রিয়াটি 10 মিনিটের বেশি সময় নেবে। সেটআপ প্রক্রিয়াকরণের সময় আপনি পরবর্তী কয়েকটি ধাপ চালিয়ে যেতে পারেন।
./setup.sh
3. একটি নতুন জাভা স্টার্টার অ্যাপ্লিকেশন তৈরি করা
এই বিভাগে আপনি spring.io দ্বারা প্রদত্ত একটি নমুনা অ্যাপ্লিকেশন ব্যবহার করে স্ক্র্যাচ থেকে একটি নতুন জাভা স্প্রিং বুট অ্যাপ্লিকেশন তৈরি করবেন
নমুনা অ্যাপ্লিকেশন ক্লোন করুন
- একটি স্টার্টার অ্যাপ্লিকেশন তৈরি করুন
curl https://start.spring.io/starter.zip -d dependencies=web -d type=maven-project -d javaVersion=11 -d packageName=com.example.springboot -o sample-app.zip
- অ্যাপ্লিকেশনটি আনজিপ করুন
unzip sample-app.zip -d sample-app
- নমুনা-অ্যাপ ডিরেক্টরিতে পরিবর্তন করুন এবং ক্লাউড শেল IDE ওয়ার্কস্পেসে ফোল্ডারটি খুলুন
cd sample-app && cloudshell workspace .
স্প্রিং-বুট-ডেভটুল এবং জিব যোগ করুন
Spring Boot DevTools সক্ষম করতে আপনার সম্পাদকের এক্সপ্লোরার থেকে pom.xml খুঁজুন এবং খুলুন। পরবর্তীতে বর্ণনা লাইনের পরে নিম্নলিখিত কোডটি পেস্ট করুন যা পড়ে <description>স্প্রিং বুটের জন্য ডেমো প্রকল্প</description>
- pom.xml-এ spring-boot-devtools যোগ করুন
প্রজেক্টের রুটে pom.xml খুলুন। Description
এন্ট্রির পরে নিম্নলিখিত কনফিগারেশন যোগ করুন।
pom.xml
<!-- Spring profiles-->
<profiles>
<profile>
<id>sync</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
- pom.xml-এ jib-maven-plugin সক্রিয় করুন
জিব হল গুগলের একটি ওপেন সোর্স জাভা কনটেইনারাইজিং টুল যা জাভা ডেভেলপারদের তাদের জানা জাভা টুল ব্যবহার করে কন্টেইনার তৈরি করতে দেয়। জিব হল একটি দ্রুত এবং সহজ কন্টেইনার ইমেজ নির্মাতা যা আপনার অ্যাপ্লিকেশনকে একটি কন্টেইনার ইমেজে প্যাকেজ করার সমস্ত ধাপ পরিচালনা করে। এটির জন্য আপনাকে একটি ডকারফাইল লিখতে বা ডকার ইনস্টল করার প্রয়োজন নেই এবং এটি সরাসরি মাভেন এবং গ্রেডলে একত্রিত হয়েছে।
pom.xml ফাইলে নিচে স্ক্রোল করুন এবং জিব প্লাগইন অন্তর্ভুক্ত করতে Build
বিভাগটি আপডেট করুন। সম্পূর্ণ হলে বিল্ড বিভাগটি নিম্নলিখিতটির সাথে মিলিত হওয়া উচিত।
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Jib Plugin-->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<!-- Maven Resources Plugin-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins>
</build>
বিল্ড ফাইল পরিবর্তন সম্পর্কে অনুরোধ করা হলে Always
নির্বাচন করুন।
ম্যানিফেস্ট তৈরি করুন
স্ক্যাফোল্ড কন্টেইনার ডেভেলপমেন্টকে সহজ করার জন্য সমন্বিত টুল সরবরাহ করে। এই ধাপে আপনি স্ক্যাফোল্ড শুরু করবেন যা স্বয়ংক্রিয়ভাবে বেস কুবারনেটস YAML ফাইল তৈরি করবে। প্রক্রিয়াটি ডকারফাইলের মতো ধারক চিত্র সংজ্ঞা সহ ডিরেক্টরিগুলি সনাক্ত করার চেষ্টা করে এবং তারপরে প্রতিটির জন্য একটি স্থাপনা এবং পরিষেবা ম্যানিফেস্ট তৈরি করে।
প্রক্রিয়াটি শুরু করতে নীচের কমান্ডটি চালান।
- টার্মিনালে নিম্নলিখিত কমান্ডটি চালান
skaffold init --generate-manifests
- যখন অনুরোধ করা হয়:
-
Jib Maven Plugin
আপনার কার্সার সরাতে তীরচিহ্নগুলি ব্যবহার করুন৷ - বিকল্পটি নির্বাচন করতে স্পেসবার টিপুন।
- চালিয়ে যেতে এন্টার টিপুন
- পোর্টের জন্য 8080 লিখুন
- কনফিগারেশন সংরক্ষণ করতে y লিখুন
দুটি ফাইল কর্মক্ষেত্রে যোগ করা হয়েছে যেমন, skaffold.yaml
এবং deployment.yaml
অ্যাপের নাম আপডেট করুন
কনফিগারেশনে অন্তর্ভুক্ত ডিফল্ট মানগুলি বর্তমানে আপনার অ্যাপ্লিকেশনের নামের সাথে মেলে না। ডিফল্ট মানগুলির পরিবর্তে আপনার অ্যাপ্লিকেশনের নাম উল্লেখ করতে ফাইলগুলি আপডেট করুন৷
- Skaffold কনফিগারেশনে এন্ট্রি পরিবর্তন করুন
-
skaffold.yaml
খুলুন - বর্তমানে
pom-xml-image
হিসাবে সেট করা ছবির নাম নির্বাচন করুন - রাইট ক্লিক করুন এবং সমস্ত ঘটনা পরিবর্তন করুন নির্বাচন করুন
-
demo-app
হিসাবে নতুন নাম টাইপ করুন
- Kubernetes কনফিগারেশনে এন্ট্রি পরিবর্তন করুন
-
deployment.yaml
ফাইল খুলুন - বর্তমানে
pom-xml-image
হিসাবে সেট করা ছবির নাম নির্বাচন করুন - রাইট ক্লিক করুন এবং সমস্ত ঘটনা পরিবর্তন করুন নির্বাচন করুন
-
demo-app
হিসাবে নতুন নাম টাইপ করুন
হট সিঙ্ক সক্ষম করুন
একটি অপ্টিমাইজ করা হট রিলোড অভিজ্ঞতার সুবিধার জন্য আপনি জিব দ্বারা প্রদত্ত সিঙ্ক বৈশিষ্ট্যটি ব্যবহার করবেন। এই ধাপে আপনি Skaffold কনফিগার করবেন যাতে বিল্ড প্রক্রিয়ায় সেই বৈশিষ্ট্যটি ব্যবহার করা যায়।
দ্রষ্টব্য যে আপনি স্কাফোল্ড কনফিগারেশনে যে "সিঙ্ক" প্রোফাইলটি কনফিগার করছেন সেটি স্প্রিং "সিঙ্ক" প্রোফাইলটি ব্যবহার করে যা আপনি আগের ধাপে কনফিগার করেছেন, যেখানে আপনি স্প্রিং-ডেভ-টুলগুলির জন্য সমর্থন সক্ষম করেছেন৷
- স্কাফোল্ড কনফিগারেশন আপডেট করুন
skaffold.yaml ফাইলে নিম্নলিখিত স্পেসিফিকেশন দিয়ে ফাইলের সম্পূর্ণ বিল্ড সেকশন প্রতিস্থাপন করুন। ফাইলের অন্যান্য বিভাগ পরিবর্তন করবেন না।
skaffold.yaml
build:
artifacts:
- image: demo-app
jib:
project: com.example:demo
type: maven
args:
- --no-transfer-progress
- -Psync
fromImage: gcr.io/distroless/java:debug
sync:
auto: true
একটি ডিফল্ট রুট যোগ করুন
/src/main/java/com/example/springboot/ এ HelloController.java নামে একটি ফাইল তৈরি করুন
একটি ডিফল্ট HTTP রুট তৈরি করতে ফাইলে নিম্নলিখিত বিষয়বস্তু পেস্ট করুন
HelloController.java
package com.example.springboot;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Value;
@RestController
public class HelloController {
@Value("${target:local}")
String target;
@GetMapping("/")
public String hello()
{
return String.format("Hello from your %s environment!", target);
}
}
4. উন্নয়ন প্রক্রিয়ার মধ্য দিয়ে হাঁটা
এই বিভাগে আপনি মৌলিক প্রক্রিয়াগুলি শিখতে এবং আপনার স্টার্টার অ্যাপ্লিকেশনটির কনফিগারেশন এবং সেটআপ যাচাই করতে ক্লাউড কোড প্লাগইন ব্যবহার করে কয়েকটি ধাপ অতিক্রম করবেন।
ক্লাউড কোড স্ক্যাফোল্ডের সাথে একীভূত করে আপনার উন্নয়ন প্রক্রিয়াকে প্রবাহিত করতে। আপনি যখন নিম্নলিখিত ধাপে GKE-তে স্থাপন করবেন, ক্লাউড কোড এবং Skaffold স্বয়ংক্রিয়ভাবে আপনার কন্টেইনার ইমেজ তৈরি করবে, এটি একটি কন্টেইনার রেজিস্ট্রিতে ঠেলে দেবে এবং তারপর GKE-তে আপনার অ্যাপ্লিকেশন স্থাপন করবে। এটি বিকাশকারীর প্রবাহ থেকে বিশদ বিবরণকে বিমূর্ত করে পর্দার আড়ালে ঘটে। ক্লাউড কোড কনটেইনার ভিত্তিক ডেভেলপমেন্টে প্রথাগত ডিবাগ এবং হটসিঙ্ক ক্ষমতা প্রদান করে আপনার উন্নয়ন প্রক্রিয়াকেও উন্নত করে।
কুবারনেটে স্থাপন করুন
- ক্লাউড শেল এডিটরের নীচের প্যানে, ক্লাউড কোড  নির্বাচন করুন
- উপরে প্রদর্শিত প্যানেলে, Kubernetes-এ ডিবাগ নির্বাচন করুন। অনুরোধ করা হলে, বর্তমান কুবারনেটস প্রসঙ্গ ব্যবহার করতে হ্যাঁ নির্বাচন করুন।
- আপনি যখন প্রথমবার কমান্ডটি চালাবেন তখন স্ক্রিনের শীর্ষে একটি প্রম্পট উপস্থিত হবে যাতে আপনি বর্তমান কুবারনেটস প্রসঙ্গটি চান কিনা, বর্তমান প্রসঙ্গটি গ্রহণ করতে এবং ব্যবহার করতে "হ্যাঁ" নির্বাচন করুন।
- পরবর্তীতে কোন কন্টেইনার রেজিস্ট্রি ব্যবহার করতে হবে তা জিজ্ঞাসা করে একটি প্রম্পট প্রদর্শিত হবে। প্রদত্ত ডিফল্ট মান গ্রহণ করতে এন্টার টিপুন
- অগ্রগতি এবং বিজ্ঞপ্তিগুলি দেখতে নীচের ফলকে আউটপুট ট্যাবটি নির্বাচন করুন৷
- কনটেইনারগুলি থেকে লাইভ স্ট্রিমিং অতিরিক্ত বিবরণ এবং লগগুলি দেখতে ডানদিকে ড্রপ ডাউন চ্যানেলে "কুবারনেটস: রান/ডিবাগ - বিস্তারিত" নির্বাচন করুন
- ড্রপডাউন থেকে "কুবারনেটস: রান/ডিবাগ" নির্বাচন করে সরলীকৃত দৃশ্যে ফিরে যান
- যখন বিল্ড এবং পরীক্ষা করা হয়, আউটপুট ট্যাবটি বলে:
Resource deployment/demo-app status completed successfully
, এবং একটি url তালিকাভুক্ত করা হয়েছে: "পরিষেবা ডেমো-অ্যাপ থেকে ফরওয়ার্ড করা URL: http://localhost:8080" - ক্লাউড কোড টার্মিনালে, আউটপুট (http://localhost:8080) এর URL-এর উপর হোভার করুন এবং তারপরে টুল টিপে প্রদর্শিত ওয়েব প্রিভিউ নির্বাচন করুন।
প্রতিক্রিয়া হবে:
Hello from your local environment!
ব্রেকপয়েন্ট ব্যবহার করুন
- /src/main/java/com/example/springboot/HelloController.java এ অবস্থিত HelloController.java অ্যাপ্লিকেশনটি খুলুন
- রুট পাথের জন্য রিটার্ন স্টেটমেন্ট সনাক্ত করুন যা
return String.format("Hello from your %s environment!", target);
- লাইন নম্বরের বাম দিকের ফাঁকা জায়গায় ক্লিক করে সেই লাইনে একটি ব্রেকপয়েন্ট যোগ করুন। ব্রেকপয়েন্ট সেট করা হয়েছে লক্ষ্য করার জন্য একটি লাল সূচক দেখাবে
- আপনার ব্রাউজার পুনরায় লোড করুন এবং নোট করুন ডিবাগার ব্রেকপয়েন্টে প্রক্রিয়াটি বন্ধ করে দেয় এবং আপনাকে GKE-তে দূরবর্তীভাবে চলমান অ্যাপ্লিকেশনটির পরিবর্তনশীল বালি অবস্থা তদন্ত করতে দেয়
- আপনি "টার্গেট" ভেরিয়েবল না পাওয়া পর্যন্ত ভেরিয়েবল বিভাগে ক্লিক করুন।
- বর্তমান মানটিকে "স্থানীয়" হিসাবে পর্যবেক্ষণ করুন
- "টার্গেট" ভেরিয়েবল নামের উপর ডাবল ক্লিক করুন এবং পপআপে, "ক্লাউড" এর মত ভিন্ন কিছুতে মান পরিবর্তন করুন
- ডিবাগ কন্ট্রোল প্যানেলে Continue বাটনে ক্লিক করুন
- আপনার ব্রাউজারে প্রতিক্রিয়া পর্যালোচনা করুন যা এখন আপনার প্রবেশ করা আপডেট করা মান দেখায়।
হট রিলোড
- "%s কোড থেকে হ্যালো" এর মতো একটি ভিন্ন মান ফেরত দিতে বিবৃতিটি পরিবর্তন করুন
- ফাইলটি স্বয়ংক্রিয়ভাবে সংরক্ষিত হয় এবং GKE-তে দূরবর্তী পাত্রে সিঙ্ক হয়
- আপডেট ফলাফল দেখতে আপনার ব্রাউজার রিফ্রেশ করুন.
- ডিবাগ টুলবারে লাল বর্গক্ষেত্রে ক্লিক করে ডিবাগিং সেশন বন্ধ করুন
5. একটি সাধারণ CRUD বিশ্রাম পরিষেবা বিকাশ করা
এই মুহুর্তে আপনার অ্যাপ্লিকেশনটি সম্পূর্ণরূপে কনটেইনারাইজড ডেভেলপমেন্টের জন্য কনফিগার করা হয়েছে এবং আপনি ক্লাউড কোডের সাথে মৌলিক উন্নয়ন কর্মপ্রবাহের মধ্য দিয়ে গেছেন। নিম্নলিখিত বিভাগগুলিতে আপনি Google ক্লাউডে একটি পরিচালিত ডাটাবেসের সাথে সংযুক্ত বিশ্রাম পরিষেবার শেষ পয়েন্ট যোগ করে যা শিখেছেন তা অনুশীলন করেন।
নির্ভরতা কনফিগার করুন
অ্যাপ্লিকেশন কোড একটি ডাটাবেস ব্যবহার করে বাকি পরিষেবা ডেটা বজায় রাখতে। pom.xl এ নিম্নলিখিত যোগ করে নির্ভরতা উপলব্ধ রয়েছে তা নিশ্চিত করুন
-
pom.xml
ফাইলটি খুলুন এবং কনফিগারেশনের নির্ভরতা বিভাগে নিম্নলিখিত যোগ করুন
pom.xml
<!-- Database dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
বাকি পরিষেবা কোড করুন
উদ্ধৃতি.জাভা
/src/main/java/com/example/springboot/ এ Quote.java নামে একটি ফাইল তৈরি করুন এবং নীচের কোডে অনুলিপি করুন। এটি অ্যাপ্লিকেশনে ব্যবহৃত উদ্ধৃতি বস্তুর জন্য সত্তা মডেলকে সংজ্ঞায়িত করে।
package com.example.springboot;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Objects;
@Entity
@Table(name = "quotes")
public class Quote
{
@Id
@Column(name = "id")
private Integer id;
@Column(name="quote")
private String quote;
@Column(name="author")
private String author;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getQuote() {
return quote;
}
public void setQuote(String quote) {
this.quote = quote;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Quote quote1 = (Quote) o;
return Objects.equals(id, quote1.id) &&
Objects.equals(quote, quote1.quote) &&
Objects.equals(author, quote1.author);
}
@Override
public int hashCode() {
return Objects.hash(id, quote, author);
}
}
QuoteRepository.java
src/main/java/com/example/springboot-এ QuoteRepository.java নামে একটি ফাইল তৈরি করুন এবং নিম্নলিখিত কোডে অনুলিপি করুন
package com.example.springboot;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface QuoteRepository extends JpaRepository<Quote,Integer> {
@Query( nativeQuery = true, value =
"SELECT id,quote,author FROM quotes ORDER BY RANDOM() LIMIT 1")
Quote findRandomQuote();
}
এই কোডটি ডেটা ধরে রাখার জন্য JPA ব্যবহার করে। ক্লাস স্প্রিং JPARepository
ইন্টারফেস প্রসারিত করে এবং কাস্টম কোড তৈরির অনুমতি দেয়। কোডটিতে আপনি একটি findRandomQuote
কাস্টম পদ্ধতি যোগ করেছেন।
QuoteController.java
পরিষেবার জন্য শেষ পয়েন্ট প্রকাশ করতে, একটি QuoteController
ক্লাস এই কার্যকারিতা প্রদান করবে।
src/main/java/com/example/springboot-এ QuoteController.java নামে একটি ফাইল তৈরি করুন এবং নিম্নলিখিত বিষয়বস্তুতে অনুলিপি করুন
package com.example.springboot;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class QuoteController {
private final QuoteRepository quoteRepository;
public QuoteController(QuoteRepository quoteRepository) {
this.quoteRepository = quoteRepository;
}
@GetMapping("/random-quote")
public Quote randomQuote()
{
return quoteRepository.findRandomQuote();
}
@GetMapping("/quotes")
public ResponseEntity<List<Quote>> allQuotes()
{
try {
List<Quote> quotes = new ArrayList<Quote>();
quoteRepository.findAll().forEach(quotes::add);
if (quotes.size()==0 || quotes.isEmpty())
return new ResponseEntity<List<Quote>>(HttpStatus.NO_CONTENT);
return new ResponseEntity<List<Quote>>(quotes, HttpStatus.OK);
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<List<Quote>>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping("/quotes")
public ResponseEntity<Quote> createQuote(@RequestBody Quote quote) {
try {
Quote saved = quoteRepository.save(quote);
return new ResponseEntity<Quote>(saved, HttpStatus.CREATED);
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<Quote>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping("/quotes/{id}")
public ResponseEntity<Quote> updateQuote(@PathVariable("id") Integer id, @RequestBody Quote quote) {
try {
Optional<Quote> existingQuote = quoteRepository.findById(id);
if(existingQuote.isPresent()){
Quote updatedQuote = existingQuote.get();
updatedQuote.setAuthor(quote.getAuthor());
updatedQuote.setQuote(quote.getQuote());
return new ResponseEntity<Quote>(updatedQuote, HttpStatus.OK);
} else {
return new ResponseEntity<Quote>(HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<Quote>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/quotes/{id}")
public ResponseEntity<HttpStatus> deleteQuote(@PathVariable("id") Integer id) {
try {
quoteRepository.deleteById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (RuntimeException e) {
System.out.println(e.getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
ডাটাবেস কনফিগারেশন যোগ করুন
application.yaml
পরিষেবা দ্বারা অ্যাক্সেস করা ব্যাকএন্ড ডাটাবেসের জন্য কনফিগারেশন যোগ করুন। src/main/resources
এর অধীনে application.yaml
ফাইল নামক ফাইলটি সম্পাদনা করুন (বা উপস্থিত না থাকলে তৈরি করুন) এবং ব্যাকএন্ডের জন্য একটি প্যারামিটারাইজড স্প্রিং কনফিগারেশন যোগ করুন।
target: local spring: config: activate: on-profile: cloud-dev datasource: url: 'jdbc:postgresql://${DB_HOST:127.0.0.1}/${DB_NAME:quote_db}' username: '${DB_USER:user}' password: '${DB_PASS:password}' jpa: properties: hibernate: jdbc: lob: non_contextual_creation: true dialect: org.hibernate.dialect.PostgreSQLDialect hibernate: ddl-auto: update
ডাটাবেস মাইগ্রেশন যোগ করুন
src/main/resources/db/migration/ এ একটি ফোল্ডার তৈরি করুন
একটি SQL ফাইল তৈরি করুন: V1__create_quotes_table.sql
ফাইলে নিম্নলিখিত বিষয়বস্তু পেস্ট করুন
V1__create_quotes_table.sql
CREATE TABLE quotes(
id INTEGER PRIMARY KEY,
quote VARCHAR(1024),
author VARCHAR(256)
);
INSERT INTO quotes (id,quote,author) VALUES (1,'Never, never, never give up','Winston Churchill');
INSERT INTO quotes (id,quote,author) VALUES (2,'While there''s life, there''s hope','Marcus Tullius Cicero');
INSERT INTO quotes (id,quote,author) VALUES (3,'Failure is success in progress','Anonymous');
INSERT INTO quotes (id,quote,author) VALUES (4,'Success demands singleness of purpose','Vincent Lombardi');
INSERT INTO quotes (id,quote,author) VALUES (5,'The shortest answer is doing','Lord Herbert');
কুবারনেটস কনফিগারেশন
deployment.yaml
ফাইলে নিম্নলিখিত সংযোজনগুলি অ্যাপ্লিকেশনটিকে CloudSQL দৃষ্টান্তগুলির সাথে সংযোগ করার অনুমতি দেয়৷
- টার্গেট - যেখানে অ্যাপটি চালানো হয় সেই পরিবেশ নির্দেশ করতে ভেরিয়েবল কনফিগার করে
- SPRING_PROFILES_ACTIVE - সক্রিয় স্প্রিং প্রোফাইল দেখায়, যা
cloud-dev
কনফিগার করা হবে - DB_HOST - ডাটাবেসের জন্য ব্যক্তিগত আইপি, যা ডাটাবেস ইনস্ট্যান্স তৈরি হওয়ার সময় বা Google ক্লাউড কনসোলের নেভিগেশন মেনুতে
SQL
এ ক্লিক করে উল্লেখ করা হয়েছে - অনুগ্রহ করে মান পরিবর্তন করুন! - DB_USER এবং DB_PASS - ক্লাউডএসকিউএল ইনস্ট্যান্স কনফিগারেশনে সেট করা, জিসিপি-তে সিক্রেট হিসাবে সংরক্ষিত
নিচের বিষয়বস্তু সহ আপনার deployment.yaml আপডেট করুন।
deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: demo-app
labels:
app: demo-app
spec:
ports:
- port: 8080
protocol: TCP
clusterIP: None
selector:
app: demo-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
labels:
app: demo-app
spec:
replicas: 1
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: demo-app
image: demo-app
env:
- name: PORT
value: "8080"
- name: TARGET
value: "Local Dev - CloudSQL Database - K8s Cluster"
- name: SPRING_PROFILES_ACTIVE
value: cloud-dev
- name: DB_HOST
value: ${DB_INSTANCE_IP}
- name: DB_PORT
value: "5432"
- name: DB_USER
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: database
আপনার ডাটাবেসের ঠিকানা দিয়ে DB_HOST মান প্রতিস্থাপন করুন
export DB_INSTANCE_IP=$(gcloud sql instances describe quote-db-instance \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml
প্রয়োগ করুন এবং আবেদন যাচাই করুন
- ক্লাউড শেল এডিটরের নীচের প্যানে, ক্লাউড কোড নির্বাচন করুন তারপর পর্দার শীর্ষে কুবারনেটে ডিবাগ নির্বাচন করুন।
- যখন বিল্ড এবং পরীক্ষা করা হয়, আউটপুট ট্যাবটি বলে:
Resource deployment/demo-app status completed successfully
, এবং একটি url তালিকাভুক্ত করা হয়েছে: "পরিষেবা ডেমো-অ্যাপ থেকে ফরওয়ার্ড করা URL: http://localhost:8080" - এলোমেলো উদ্ধৃতি দেখুন
ক্লাউডশেল টার্মিনাল থেকে, র্যান্ডম-কোট এন্ডপয়েন্টের বিরুদ্ধে একাধিকবার নীচের কমান্ডটি চালান। বিভিন্ন উদ্ধৃতি ফেরত বারবার কল পর্যবেক্ষণ করুন
curl -v 127.0.0.1:8080/random-quote
- একটি উদ্ধৃতি যোগ করুন
নীচে তালিকাভুক্ত কমান্ডটি ব্যবহার করে id=6 সহ একটি নতুন উদ্ধৃতি তৈরি করুন এবং অনুরোধটি প্রতিধ্বনিত হচ্ছে পর্যবেক্ষণ করুন
curl -v -H 'Content-Type: application/json' -d '{"id":"6","author":"Henry David Thoreau","quote":"Go confidently in the direction of your dreams! Live the life you have imagined"}' -X POST 127.0.0.1:8080/quotes
- একটি উদ্ধৃতি মুছুন
এখন আপনি মুছে ফেলা পদ্ধতির সাথে যোগ করা উদ্ধৃতিটি মুছুন এবং একটি HTTP/1.1 204
প্রতিক্রিয়া কোড পর্যবেক্ষণ করুন।
curl -v -X DELETE 127.0.0.1:8080/quotes/6
- সার্ভার ত্রুটি
এন্ট্রিটি ইতিমধ্যে মুছে ফেলার পরে আবার শেষ অনুরোধটি চালিয়ে একটি ত্রুটির অবস্থার অভিজ্ঞতা নিন
curl -v -X DELETE 127.0.0.1:8080/quotes/6
লক্ষ্য করুন প্রতিক্রিয়াটি একটি HTTP:500 Internal Server Error
প্রদান করে।
অ্যাপ্লিকেশন ডিবাগ করুন
পূর্ববর্তী বিভাগে আপনি অ্যাপ্লিকেশনটিতে একটি ত্রুটির অবস্থা খুঁজে পেয়েছেন যখন আপনি একটি এন্ট্রি মুছে ফেলার চেষ্টা করেছিলেন যা ডাটাবেসে ছিল না। এই বিভাগে আপনি সমস্যাটি সনাক্ত করতে একটি ব্রেকপয়েন্ট সেট করবেন। DELETE অপারেশনে ত্রুটি ঘটেছে, তাই আপনি QuoteController ক্লাসের সাথে কাজ করবেন।
- src.main.java.com.example.springboot.QuoteController.java খুলুন
-
deleteQuote()
পদ্ধতি খুঁজুন - ডাটাবেস থেকে একটি আইটেম মুছে ফেলার লাইনটি খুঁজুন:
quoteRepository.deleteById(id);
- লাইন নম্বরের বাম দিকের ফাঁকা জায়গায় ক্লিক করে সেই লাইনে একটি ব্রেকপয়েন্ট সেট করুন।
- ব্রেকপয়েন্ট সেট করা হয়েছে তা নির্দেশ করে একটি লাল সূচক উপস্থিত হবে
-
delete
কমান্ডটি আবার চালান
curl -v -X DELETE 127.0.0.1:8080/quotes/6
- বাম কলামে আইকনে ক্লিক করে ডিবাগ ভিউতে ফিরে যান
- QuoteController ক্লাসে ডিবাগ লাইন বন্ধ করা পর্যবেক্ষণ করুন।
- ডিবাগারে,
step over
আইকনে ক্লিক করুন এবং লক্ষ্য করুন যে একটি ব্যতিক্রম নিক্ষিপ্ত হয়েছে - লক্ষ্য করুন যে একটি খুব সাধারণ
RuntimeException was caught.
এটি ক্লায়েন্টকে একটি অভ্যন্তরীণ সার্ভার ত্রুটি HTTP 500 প্রদান করে যা আদর্শ নয়।
Trying 127.0.0.1:8080... * Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0) > DELETE /quotes/6 HTTP/1.1 > Host: 127.0.0.1:8080 > User-Agent: curl/7.74.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 500 < Content-Length: 0 < Date: < * Connection #0 to host 127.0.0.1 left intact
কোড আপডেট করুন
কোডটি ভুল এবং EmptyResultDataAccessException
ব্যতিক্রম ধরার জন্য ব্যতিক্রম ব্লকটি রিফ্যাক্টর করা উচিত এবং একটি HTTP 404 খুঁজে পাওয়া স্ট্যাটাস কোড ফেরত পাঠাতে হবে।
ভুল সংশোধন করুন।
- ডিবাগ সেশন এখনও চলছে, ডিবাগ কন্ট্রোল প্যানেলে "চালিয়ে যান" বোতাম টিপে অনুরোধটি সম্পূর্ণ করুন৷
- পরবর্তী কোডে নিম্নলিখিত ব্লক যোগ করুন:
} catch (EmptyResultDataAccessException e){
return new ResponseEntity<HttpStatus>(HttpStatus.NOT_FOUND);
}
পদ্ধতি নিম্নলিখিত মত দেখতে হবে
public ResponseEntity<HttpStatus> deleteQuote(@PathVariable("id") Integer id) { try { quoteRepository.deleteById(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } catch(EmptyResultDataAccessException e){ return new ResponseEntity<HttpStatus>(HttpStatus.NOT_FOUND); } catch (RuntimeException e) { System.out.println(e.getMessage()); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } }
- ডিলিট কমান্ডটি পুনরায় চালান
curl -v -X DELETE 127.0.0.1:8080/quotes/6
- ডিবাগারের মধ্য দিয়ে যান এবং
EmptyResultDataAccessException
ধরা পড়েছে এবং একটি HTTP 404 নট ফাউন্ড কলারের কাছে ফিরে এসেছে।
Trying 127.0.0.1:8080... * Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0) > DELETE /quotes/6 HTTP/1.1 > Host: 127.0.0.1:8080 > User-Agent: curl/7.74.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 404 < Content-Length: 0 < Date: < * Connection #0 to host 127.0.0.1 left intact
- ডিবাগ টুলবারে লাল বর্গক্ষেত্রে ক্লিক করে ডিবাগিং সেশন বন্ধ করুন
6. পরিষ্কার করা
অভিনন্দন! এই ল্যাবে আপনি স্ক্র্যাচ থেকে একটি নতুন জাভা অ্যাপ্লিকেশন তৈরি করেছেন এবং কনটেইনারগুলির সাথে কার্যকরভাবে কাজ করার জন্য এটি কনফিগার করেছেন৷ তারপরে আপনি প্রথাগত অ্যাপ্লিকেশন স্ট্যাকগুলিতে পাওয়া একই বিকাশকারী প্রবাহ অনুসরণ করে একটি দূরবর্তী GKE ক্লাস্টারে আপনার অ্যাপ্লিকেশন স্থাপন এবং ডিবাগ করেছেন।
ল্যাব শেষ করার পরে পরিষ্কার করতে:
- ল্যাবে ব্যবহৃত ফাইলগুলি মুছুন
cd ~ && rm -rf container-developer-workshop
- সমস্ত সম্পর্কিত অবকাঠামো এবং সংস্থানগুলি সরাতে প্রকল্পটি মুছুন৷