কিভাবে Java দিয়ে একটা Website Down Detector বানাবো?

অব্জেক্ট অরিয়েন্টেড প্রোগ্রামিং ল্যাবে অনেক পোলাপানের অবস্থা খারাপ। আমাদের প্রোজেক্ট করার কথা অ্যাডভান্সড অব্জেক্ট অরিয়েন্টেড প্রোগ্রামিং ল্যাবে। কিন্তু স্যার মার্কস কম দেখে বাধ্য হয়ে আমাদের বললেন প্রোজেক্ট করতে, কোনো লিমিটেশন নাই। নিজের মতো করতে হবে। আর ভাইবাতে কোড বুঝায় দিতে হবে। না বুঝাইতে পারলে বিপদ। সমস্যা এইখানেই। স্যার ক্লাসেই বললেন এইটা। আমিও ভাবতেছি কি করা যায়। 

তো রিসেন্টলি একটা প্রোজেক্ট শুরু করছিলাম, জাভাস্ক্রিপ্টে অ্যাজাক্স ইউজ করে ওয়েবসাইটের অ্যাভেইলেভিলিটি বের করা। এইটা খুবই সহজ, কিন্তু সব ওয়েবসাইটে কাজ করছিলো না। তাই পুরা প্রজেক্টটা ব্লান্ডার গেলো, আমিও আর কাজ করি নাই ঐটা নিয়ে। 

কিন্তু জাভায় কাজটা খুবই সোজা। 

তো আমি ভাবলাম, কষ্ট কম হবে, ধুপ ধাপ একটা ওয়েবসাইট ডাউন ডিটেক্টর বানায় ফেলি। ৫ মার্কের প্রোজেক্ট হিসেবে আমার মনে এইটা খুব ফাইন জিনিস হবে। ল্যাব ক্লাস আড়াই ঘন্টা, আমি দুই ঘন্টায় শেষ করলাম এই ছাতার প্রোজেক্ট। ফলস্বরূপ ক্লাসে স্যার কি পড়াইছে আর কি বলছে, কিছু শুনি নাই।

 


আইডিয়াটা খুবই সিম্পল। একটা ইউজার ইন্টারফেস থাকতে হবে। ইউজার ইন্টারফেসে আমরা একটা লিঙ্ক বা URL পেস্ট করবো বা লিখে দেবো, তারপর Test বাটনে ক্লিক করলে প্রথমে একটা মেথড ভ্যালিডেট করবে যে লিঙ্কটা কি ভ্যালিড নাকি, মানে এইটা আদৌ কি লিঙ্ক না অন্য কিছু। তারপর যদি এইটা ভ্যালিড লিঙ্ক হয়ে থাকে, তাহলে একটা HTTP Request তৈরি করবে। এই রিকোয়েস্টের রেস্পন্স কোড আমরা চেক করে দেখবো, যদি Status Code 200 হয়, তাহলে ওয়েবসাইট অনলাইন আছে। অনেক সময় ওয়েবসাইট অনলাইন থাকলেও সিকিউর কানেকশন না থাকলে বা SSL Invalid থাকলে জাভা একটা এক্সেপশন থ্রো করে। আমরা এইটাও Exception Handling করে ইউজারকে দেখিয়ে দেবো যে ওয়েবসাইট অনলাইন এবং এসএসএল সার্টিফিকেটে সমস্যা আছে। 

তো কোডিং শুরু করা যাক।

public class Main extends JFrame{
    //URL Input Text
    private final JTextField urlInput = new JTextField("", 20);
    //Status Section Objects
    private final JLabel statusText = new JLabel("Status:");
    private final JLabel statusOut = new JLabel("Standby");
 


প্রথমেই আমরা আমাদের ক্লাস ফাইল তৈরি করে নিলাম। তারপর সেটাকে JFrame ক্লাসে এক্সটেন্ড করে দিলাম।
এবার আমরা ঠিক সেইসব এলিমেন্টের জন্য অব্জেক্ট তৈরি করবো যেগুলো আমাদের পরে ম্যানিপুলেট কিংবা চেঞ্জ করা লাগতে পারে।
যেমন আমার প্রোগ্রামে আমি স্ট্যাটাসের লেখাগুলোয় দেখাবো যে, "Omuk Website in Online"
অথবা "Invalid URL" এরকম কিছু।
তো এই অব্জেক্টগুলো সব রকম মেথড থেকে এক্সেস করতে পারতে হবে, এবং অন্যান্য ক্লাস ফাইল থেকে আলাদা রাখতে হবে। তাই আমি Object গুলোকে প্রাইভেট করে দিয়েছি এবং ক্লাসের শুরুতেই ডিক্লেয়ার করে দিয়েছি। আমরা টেক্সট ইনপুট নেবার জন্য একটা JTextField অব্জেক্ট নিয়েছি, যেইটার 20টা কলাম পর্যন্ত ইন্টারফেসে দেখানো হবে, এবং দুইটা JLabel অব্জেক্ট নিয়েছি, একটা কেবল Status: লেখাটি দেখাবে এবং আরেকটি আমাদের নটিফিকেশনের টেক্সট দেখাবে যেইটা দিয়ে আমরা ইউজার কে দেখাবো যে ওয়েবসাইট কি অনলাইন নাকি অফলাইন।




এইবার আমরা তৈরি করবো isValidURL() মেথড

এই মেথড দিয়ে আমরা চেক করতে পারবো যে একটা ইউআরএল কি আদৌ কোনো ইউআরএল কি না?
এই মেথড একটা বুলিয়ান রিটার্ন করবে, মানে ঠিক হলে true, না হলে false.
এখানে হয়তো regex দিয়ে কাজ করা যেতো, মানে আমরা ইউআরএল ভেঙ্গে ভেঙ্গে দেখতাম যে
এইটা দেখতে কি একটা লিঙ্কের মতো নাকি?

কিন্তু একটা সহজ উপায় হচ্ছে URL() অব্জেক্ট তৈরি করা। URL() অব্জেক্ট কেবল একটা ইউআরএল দিয়েই তৈরি করা যায়। কাজেই ইউআরএল যদি ঠিক না হয়, URL() অব্জেক্ট একটা Exception দিবে। আমরা try/catch করে দেখবো যে ঐ ইউআরএলে কি সমস্যা। আমরা try/catch স্টেটমেন্টে একটা ইউআরএল অব্জেক্ট তৈরি করে সেটাকে URI তে বদলায় নিবো। 

এখানে আমাদের দুটো এক্সেপশন হ্যান্ডেল করতে হবে। প্রথমটির জন্য MalformedURLException যেইটা URLএ ভুল থাকলে Java এইটা Throw করে। আরেকটি হলো URISyntaxException যেইটা URI তৈরি করার সময় ভুল হলে Throw করে।


public boolean isValidURL(String url) {
        try {
            new URL(url).toURI();
        } catch (MalformedURLException | URISyntaxException e) {
            return false;
        }
        return true;
    } 
 

 

এইবার আমরা দেখবো TestURL() মেথডটা কি?

আর কিভাবে কাজ করে?
আসলে এই পুরা প্রোগ্রামে এই মেথডটা আসল রোল প্লে করতেছে। এইটাতেই আমরা ওয়েবসাইটের সার্ভারের সাথে যোগাযোগ করবো। 

//Check If The URL is Available By Creating HTTP Request
    public boolean TestURL(String url) throws IOException {
        boolean result;
        HttpURLConnection connection;
        connection = (HttpURLConnection)(new URL(url)).openConnection();
        statusOut.setForeground(Color.magenta);
        statusOut.setText("Connecting... Wait for a Moment");
        connection.setConnectTimeout(4 * 1000);
        result = (connection.getResponseCode() == 200);
        if (connection.getResponseCode() != 200){
            statusOut.setForeground(Color.RED);
            statusOut.setText("Website is Offline!");
        }
        return result;
    }
 

 এই মেথডটা একটা বুলিয়ান রিটার্ন করে, ওয়েবসাইট এভেইলেবল থাকলে true, আর না হলে false.
এইটা একটা প্যারামিটারাইজড মেথড, এখানে প্যারামিটারে আমরা URL ইনপুট দেবো। তারপর HttpURLConnnection ক্লাসের একটা অব্জেক্ট তৈরি করবো। এইটা জাভার একটা বিল্ট-ইন মেথড। কোনো প্লাগিনের দরকার হয় না। 

এইখানে একবার টাইপকাস্টীং ব্যাবহার করা হয়েছে, একটা URL এর কানেকশন ওপেন করার সময়।
কানেকশন ওপেন করার পরের সময়টাকে আমি ধরে নিয়েছি কানেক্ট করার সময়।
আমি একটা কানেকশন টাইমআউট সেট করে দিয়েছি যাতে করে কানেকশনটা একটা নির্দিস্ট সময় পর্যন্ত চেষ্টা করে এবং যদি এই সময়ের মধ্যে রেস্পন্স না করে কোনো ওয়েবসাইট, আমরা সেটাকে অফলাইন ধরে নেবো। 

এখন স্ট্যাটাস পাবার আগ পর্যন্ত একটা স্ট্যাটাস আমি ইউজারকে দেখিয়েছি যে Connecting... Wait for a Moment.

যখনই টাইমআউট শেষ হয়ে যাবে, তখন স্ট্যাটাস কোড চেক করা হবে একবার, এবং স্ট্যাটাস কোড চেক করে আমরা দেখবো যে ওয়েবসাইটের বর্তমান অবস্থা কি। টাইমাউটের সময়টুকু পেরোনোর পরে আমি স্ট্যাটাসকোড চেক করবো। যদি স্ট্যাটাস কোড ২০০ হয়ে থাকে, তার মানে ওয়েবসাইটটা একদম বহাল তবিয়তে অনলাইন হয়ে আছে।  

এমন আরোও অনেক স্ট্যাটাসকোড আছে, সবগুলো এখানে আলাপ না করি, কয়েকটা দিয়ে দিচ্ছি, 

  1. Informational responses (100199)
  2. Successful responses (200299)
  3. Redirection messages (300399)
  4. Client error responses (400499)
  5. Server error responses (500599)

বাকিগুলো এই লিঙ্কে গিয়ে দেখে আসতে পারো। 

 

 এবার আমরা চলে যাবো মেইন মেথডে, এইটাই সবকিছু কম্পাইল করছে এখানে।

    public void validateData(ActionEvent e){
        String URL = urlInput.getText();
        if(URL.isEmpty()){
            validStatus = false;
            statusText.setForeground(Color.RED);
            statusOut.setText("Please Input URL");
        }
        if(isValidURL(URL)){
            validStatus = true;
            try {
                if(TestURL(URL)){
                    statusOut.setForeground(Color.BLUE);
                    statusOut.setText("Website is Online!");
                }
            } catch (SSLException ex) {
                statusOut.setForeground(Color.RED);
                statusOut.setText("Website is Online! Invalid SSL Certificate");
            } catch (UnknownHostException ex) {
                statusOut.setForeground(Color.RED);
                statusOut.setText("This Website does not exist");
            } catch (IOException ex) {
                statusOut.setForeground(Color.RED);
                statusOut.setText("Error Connecting");
            }
        }else{
            validStatus = false;
            statusOut.setForeground(Color.BLACK);
            statusOut.setText("Please Input valid URL");
        }
    }

 প্রথমে এখানে চেক করা হয়েছে URL Input কি ফাঁকা নাকি, ফাঁকা হলে আমরা ভ্যালিডেশন false করে দিবো এবং ইউজারকে বলবো যে Please Input URL.

তারপর যদি ফাঁকা না হয়, তাহলে আমরা IsValidURL() মেথডটা চালু করবো, যদি URLটা ভ্যালিড হয়, তাহলে এইটা true রিটার্ন করবে, তাহলে তারপরে আমরা পরের ধাপে যাবো, সেখানে আমরা ট্রাইক্যাচ দিয়ে আমাদের HTTP Request টা সেন্ড করবো। এখানে আমি ৩টা এরর হ্যান্ডেল করেছি। 

একটা হলো SSLException.
যদি ওয়েবসাইট অনলাইন থাকেও, অনেক সময় দেখা যায় যে ওয়েবসাইটের এসএসএল সার্টিফিকেট ঠিক থাকে না, তখন একটা এরর থ্রো করে। এইটা তখনই হবে যখন ইউজারের ইনপুট দেয়া URL এ যদি https:// থাকে এবং ওয়েবসাইটের SSL কাজ না করে। 


তারপরে আরেকটা এক্সেপশন হলো UnknownHostException
যদি কোনোভাবেই কোনো স্ট্যাটাস কোড না পাওয়া যায়, এখানে ধরে নেয়া হবে ওয়েবসাইটটার আসলে কোনো অস্তিত্তই নাই।
যেমন amiboka.com, হতে পারে এই ওয়েবসাইটটা কেউ চালুই করে নাই। তাই এইটার কোনো অস্তিত্ব নাই। এইটার কোনো সার্ভার নাই, তাই এইটা কোনো রেস্পন্স করতে পারে নাই।

তারপর হলো IOException হ্যান্ডেলিং।
IOException মূলত ইন্টারনেটের কানেকশন না থাকলে থ্রো করে থাকে। আমরা এইটাকেও হ্যান্ডেল করে নেবো এবং ইউজারের কাছে একটা মেসেজ দেবো যে Error Connecting.

 

এই কয়েকটা হলো মোটামটি মুল প্রোগ্রামিং। বাকি সব মূলত গ্রাফিক্যাল ইন্টারফেস বা গুই এবং অ্যাকশন লিসেনারের জন্য। এখানে একটা ছোট্ট কাজ করেছি আমি যাতে করে ইনপুট টাইপ করে এন্টার চাপ দিলে টেস্ট বাটোনে একটা ইনপুট প্রেস হয়। সেজন্য নিচের লাইনগুলো আমি অ্যাড করে দিয়েছি।

        urlInput.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode()==KeyEvent.VK_ENTER){
                    testButton.doClick();
                }
            }
        });
 

এখানে urlInput হলো আমার ইনপুট প্যানেল, যেখানে URL টাইপ করবো, সেখানে আমি একটা KeyListener দিয়েছি যেইটা  Enter key প্রেস করলে Test বাটনে একটা ক্লিক করে দিবে। 

 

আমি চেষ্টা করবো আমার চ্যানেলে এই ছোট্ট প্রজেক্ট নিয়ে একটা ভিডিও তৈরি করার। সবাইকে অনেক ধন্যবাদ এতক্ষন আমার প্যাচাল পড়ার জন্য। 

নিচে এই হইলো পুরা কোড। চাইলে আমার গিটহাব রিপোসিটোরিতেও ঘুরে দেখে আসতে পারো।


//import libraries
import javax.net.ssl.SSLException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.*;


public class Main extends JFrame{
    //URL Input Text
    private final JTextField urlInput = new JTextField("", 20);
    //Status Section Objects
    private final JLabel statusText = new JLabel("Status:");
    private final JLabel statusOut = new JLabel("Standby");


    public boolean isValidURL(String url) {
        try {
            new URL(url).toURI();
        } catch (MalformedURLException | URISyntaxException e) {
            return false;
        }
        return true;
    }



    //Method to validate the inputs
    //set the initial validation status
    boolean validStatus = true;
    public void validateData(ActionEvent e){
        String URL = urlInput.getText();
        if(URL.isEmpty()){
            validStatus = false;
            statusText.setForeground(Color.RED);
            statusOut.setText("Please Input URL");
        }
        if(isValidURL(URL)){
            validStatus = true;
            try {
                if(TestURL(URL)){
                    statusOut.setForeground(Color.BLUE);
                    statusOut.setText("Website is Online!");
                }
            } catch (SSLException ex) {
                statusOut.setForeground(Color.RED);
                statusOut.setText("Website is Online! Invalid SSL Certificate");
            } catch (UnknownHostException ex) {
                statusOut.setForeground(Color.RED);
                statusOut.setText("This Website does not exist");
            } catch (IOException ex) {
                statusOut.setForeground(Color.RED);
                statusOut.setText("Error Connecting");
            }
        }else{
            validStatus = false;
            statusOut.setForeground(Color.BLACK);
            statusOut.setText("Please Input valid URL");
        }
    }

    //Method to clear the form
    public void actionClear(ActionEvent e){
        statusOut.setForeground(Color.BLACK);
        urlInput.setText("");
        statusOut.setText("Standby");
    }


    //Check If The URL is Available By Creating HTTP Request
    public boolean TestURL(String url) throws IOException {
        boolean result;
        HttpURLConnection connection;
        connection = (HttpURLConnection)(new URL(url)).openConnection();
        statusOut.setForeground(Color.magenta);
        statusOut.setText("Connecting... Wait for a Moment");
        connection.setConnectTimeout(4 * 1000);
        result = (connection.getResponseCode() == 200);
        if (connection.getResponseCode() != 200){
            statusOut.setForeground(Color.RED);
            statusOut.setText("Website is Offline!");
        }
        return result;
    }




    public Main(){
        super("Website Down Detector");
        setSize(500,150);
        setLocation(500,200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Get Containers for contents
        Container mainContainer = this.getContentPane();
        //set layout for main container
        mainContainer.setLayout(new GridLayout(2,1));


        //Button Section Objects
        JButton testButton = new JButton("Test");
        JButton clearButton = new JButton("Clear");

        //Create Panel 1
        JPanel panel1 = new JPanel();
        //Set Flow Layout for Panel 1
        panel1.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2));
        //URL  Input Area
        panel1.add(new JLabel("URL :", SwingConstants.CENTER));
        panel1.add(urlInput);
        urlInput.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode()==KeyEvent.VK_ENTER){
                    testButton.doClick();
                }
            }
        });
        testButton.addActionListener(this::validateData);
        clearButton.addActionListener(this::actionClear);
        panel1.add(testButton);
        panel1.add(clearButton);
        mainContainer.add(panel1);




        //Create Panel 7
        JPanel panel7 = new JPanel();
        //Set Flow Layout for Panel 7
        panel7.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2));
        //Buttons Area
        statusOut.setForeground(Color.BLACK);
        panel7.add(statusText);
        panel7.add(statusOut);
        mainContainer.add(panel7);

        setVisible(true);
        setResizable(false);
        pack();
    }

    public static void main(String[] args){
        new Main();
    }
}

Post a Comment

Previous Post Next Post