diff --git a/CSV.py b/CSV.py new file mode 100644 index 0000000..c3653a5 --- /dev/null +++ b/CSV.py @@ -0,0 +1,36 @@ +import json, csv, os, time, stomp +from datetime import datetime +from flask_backend.Stomp_client import get_connection + +QUEUE_NAME = "/queue/testQueue" +OUTPUT_DIR = "/app/output" +os.makedirs(OUTPUT_DIR, exist_ok=True) + +class MyListener(stomp.ConnectionListener): + def on_message(self, frame): + try: + data = json.loads(frame.body) + except json.JSONDecodeError: + print("Received invalid JSON:", frame.body) + return + + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + filename = os.path.join(OUTPUT_DIR, f"message_{timestamp}.csv") + + try: + with open(filename, "w", newline="") as f: + writer = csv.writer(f) + writer.writerow(data.keys()) + writer.writerow(data.values()) + print(f"Saved CSV: {filename}") + except Exception as e: + print("Error writing CSV:", e) + +# Připojení k ActiveMQ s listenerem +listener = MyListener() +conn = get_connection(listener=listener) +conn.subscribe(destination=QUEUE_NAME, id=1, ack="auto") + +# keep process alive +while True: + time.sleep(1) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..17a6ac7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.11-slim + +WORKDIR /app + +COPY requirements.txt . + +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . \ No newline at end of file diff --git a/README.md b/README.md index 0017505..76a182e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ # Titeto-WSO2-ActiveMQ +## WSO2 API Manager +3. Vytvor jednoduche rest api v WSO2 API manageru s resource POST. + + +## Flask +4. Vytvor Python script ktery bude fungovat jako rest API, a jeho endpoint pouzij v API manageru. + +5. Rest API bude prijmat XML jako input_payload. + +6. Rest API tento payload odesle na backend do python scriptu. + +## Sender.py +7. Vytvor JSON payload s mappingem viz. attachment a priklady output payloadu. + +8. Script posle payload jako zpravu do vytvorene Q v ActiveMQ. + +9. Posli vyslednou response s HTTP-SC. + +## Active MQ + +## CSV.py + +10. Vytvor dalsi script ktery bude naslouchat na vytvorenou Q. + +11. Vytvor CSV file dle prikladu viz. attachment. + +12. Uloz CSV s filename viz. diagram s aktualni timestampou, do libovolne slozky na lokalu. \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..82604c8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,67 @@ +version: "3.8" + +services: + # 🐍 Flask REST API + flask_backend: + build: . + container_name: flask_backend + ports: + - "5000:5000" + networks: + - internal + command: ["python", "flask_backend/app.py"] + depends_on: + - activemq + + + # 📨 ActiveMQ + activemq: + image: rmohr/activemq:5.15.9 + container_name: activemq + ports: + - "61613:61613" # STOMP port (pro komunikaci s Pythonem) + - "8161:8161" # Web UI: http://localhost:8161/admin + environment: + ACTIVEMQ_ADMIN_LOGIN: admin + ACTIVEMQ_ADMIN_PASSWORD: admin + restart: always + networks: + - internal + + + receiving_consumer: + build: . + container_name: CSV_python + depends_on: + - activemq + environment: + MQ_HOST: activemq + MQ_PORT: 61613 + MQ_USER: admin + MQ_PASS: admin + command: ["python", "CSV.py"] + volumes: + - ./output:/app/output # ✅ CSV soubory se uloží do ./output na tvém disku + restart: on-failure + networks: + - internal + + # odešle na Flask API testovací XML zprávu + wso2apim: + image: wso2/wso2am:3.2.0 + container_name: wso2apim + volumes: + - ./wso2/deployment.toml:/home/wso2carbon/wso2am-3.2.0/repository/conf/deployment.toml + - ./data/activemq:/opt/activemq/data + ports: + - "9443:9443" # HTTPS Management Console + - "8280:8280" # HTTP Gateway + - "8243:8243" # HTTPS Gateway + environment: + - JAVA_OPTS=-Duser.timezone=UTC + networks: + - internal + +networks: + internal: + driver: bridge \ No newline at end of file diff --git a/flask_backend/Dockerfile b/flask_backend/Dockerfile new file mode 100644 index 0000000..8e898f3 --- /dev/null +++ b/flask_backend/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.11-slim + +WORKDIR /app + +COPY ../requirements.txt . + +RUN pip install --no-cache-dir -r ../requirements.txt + +COPY . . \ No newline at end of file diff --git a/flask_backend/Sender.py b/flask_backend/Sender.py new file mode 100644 index 0000000..20d8beb --- /dev/null +++ b/flask_backend/Sender.py @@ -0,0 +1,14 @@ +import json +from Stomp_client import get_connection + +QUEUE_NAME = "/queue/testQueue" + +def send_to_queue(payload: dict): + """ + Posílá JSON payload do ActiveMQ queue, přijíma dic + """ + conn = get_connection() # připojení s retry loop + conn.send(destination=QUEUE_NAME, body=json.dumps(payload)) + print("Message sent to ActiveMQ:", payload) + conn.disconnect() + diff --git a/flask_backend/Stomp_client.py b/flask_backend/Stomp_client.py new file mode 100644 index 0000000..6e48f70 --- /dev/null +++ b/flask_backend/Stomp_client.py @@ -0,0 +1,25 @@ +import stomp, os, time + +MQ_HOST = os.getenv("MQ_HOST", "activemq") +MQ_PORT = int(os.getenv("MQ_PORT", 61613)) +MQ_USER = os.getenv("MQ_USER", "admin") +MQ_PASS = os.getenv("MQ_PASS", "admin") + +def get_connection(listener=None): + """ + Vrací připojený STOMP Connection objekt. + Pokud listener je None, připojení bude bez listeneru. + """ + conn = stomp.Connection12([(MQ_HOST, MQ_PORT)]) + if listener: + conn.set_listener("", listener) + + while True: + try: + conn.connect(MQ_USER, MQ_PASS, wait=True) + print("Connected to ActiveMQ") + break + except Exception as e: + print("Waiting for ActiveMQ to be ready...", e) + time.sleep(3) + return conn diff --git a/flask_backend/app.py b/flask_backend/app.py new file mode 100644 index 0000000..4efb997 --- /dev/null +++ b/flask_backend/app.py @@ -0,0 +1,20 @@ +from flask import Flask, request, jsonify +from Sender import send_to_queue + +app = Flask(__name__) + +@app.route("/send", methods=["POST"]) +def send(): + # očekává JSON payload + payload = request.get_json() + if not payload: + return jsonify({"error": "No JSON payload provided"}), 400 + + try: + send_to_queue(payload) # voláme funkci z sender.py + return jsonify({"status": "ok"}), 200 + except Exception as e: + return jsonify({"error": str(e)}), 500 + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=5000) diff --git a/flask_backend/templates/index.html b/flask_backend/templates/index.html new file mode 100644 index 0000000..64e95f5 --- /dev/null +++ b/flask_backend/templates/index.html @@ -0,0 +1,19 @@ + + +
+ + +