This commit is contained in:
2025-10-17 00:09:26 +02:00
parent 2aa8d98aa1
commit aa033aafbe
15 changed files with 357 additions and 0 deletions

36
CSV.py Normal file
View File

@@ -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)

9
Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .

View File

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

67
docker-compose.yml Normal file
View File

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

9
flask_backend/Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
FROM python:3.11-slim
WORKDIR /app
COPY ../requirements.txt .
RUN pip install --no-cache-dir -r ../requirements.txt
COPY . .

14
flask_backend/Sender.py Normal file
View File

@@ -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()

View File

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

20
flask_backend/app.py Normal file
View File

@@ -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)

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Upload the </h1>
<form action="/manage/John" method="post">
<button type="submit">Manage John</button>
</form>
<form action="/page/Jane" method="post">
<button type="submit">Go to Jane's Page</button>
</form>
{{ message }}
</body>
</html>

View File

@@ -0,0 +1,65 @@
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<actor>
<list>
<id>59088032</id>
<firstName>Jiri Novak</firstName>
<lastName>Vika</lastName>
<address>
<streetName>StreetName</streetName>
<postCode>4312</postCode>
<cityName>SANDNES</cityName>
<countryCode>NO</countryCode>
<isPostBox>true</isPostBox>
</address>
<addressLine1>StreetName 1A</addressLine1>
<country>NORWAY</country>
<phoneNumber>+4793488400</phoneNumber>
<cellularPhoneNumber>+4793488999</cellularPhoneNumber>
<emailAddress>testguy@gmail.com</emailAddress>
<dateOfBirth>1962-10-01</dateOfBirth>
<hasSecretAddress>false</hasSecretAddress>
<isReservedAgainstSalesMaterial>false</isReservedAgainstSalesMaterial>
</list>
<list>
<id>59088033</id>
<firstName>Tomas Novak</firstName>
<lastName>Vika</lastName>
<address>
<streetName>Postboks 16</streetName>
<postCode>4318</postCode>
<cityName>BERGEN</cityName>
<countryCode>NO</countryCode>
<isPostBox>true</isPostBox>
</address>
<addressLine1>StreetName 1B</addressLine1>
<country>NORWAY</country>
<phoneNumber>+4793488888</phoneNumber>
<emailAddress>testguy2@gmail.com</emailAddress>
<dateOfBirth>1963-10-01</dateOfBirth>
<hasSecretAddress>false</hasSecretAddress>
<isReservedAgainstSalesMaterial>false</isReservedAgainstSalesMaterial>
</list>
<list>
<id>59088034</id>
<firstName>Karel Novak</firstName>
<lastName>Vika</lastName>
<address>
<streetName>StreetName</streetName>
<postCode>4319</postCode>
<cityName>STAVANGER</cityName>
<countryCode>NO</countryCode>
<isPostBox>true</isPostBox>
</address>
<addressLine1>StreetName 1C</addressLine1>
<country>NORWAY</country>
<phoneNumber>+4793488777</phoneNumber>
<emailAddress>testguy3@gmail.com</emailAddress>
<dateOfBirth>1964-10-01</dateOfBirth>
<hasSecretAddress>false</hasSecretAddress>
<isReservedAgainstSalesMaterial>false</isReservedAgainstSalesMaterial>
</list>
</actor>
</soapenv:Body>
</soapenv:Envelope>

View File

@@ -0,0 +1,56 @@
{
"list": [
{
"id": 59088032,
"firstName": "Jiri Novak",
"lastName": "Vika",
"streetName": "StreetName",
"postCode": 4312,
"cityName": "SANDNES",
"countryCode": "NO",
"isPostBox": true,
"addressLine1": "StreetName 1A",
"country": "NORWAY",
"phoneNumber": 4793488400,
"cellularPhoneNumber": 4793488999,
"emailAddress": "testguy@gmail.com",
"dateOfBirth": "1962-10-01",
"hasSecretAddress": false,
"isReservedAgainstSalesMaterial": false
},
{
"id": 59088033,
"firstName": "Tomas Novak",
"lastName": "Vika",
"streetName": "Postboks 16",
"postCode": 4318,
"cityName": "BERGEN",
"countryCode": "NO",
"isPostBox": true,
"addressLine1": "StreetName 1B",
"country": "NORWAY",
"phoneNumber": 4793488888,
"emailAddress": "testguy2@gmail.com",
"dateOfBirth": "1963-10-01",
"hasSecretAddress": false,
"isReservedAgainstSalesMaterial": false
},
{
"id": 59088034,
"firstName": "Karel Novak",
"lastName": "Vika",
"streetName": "StreetName",
"postCode": 4319,
"cityName": "STAVANGER",
"countryCode": "NO",
"isPostBox": true,
"addressLine1": "StreetName 1C",
"country": "NORWAY",
"phoneNumber": 4793488777,
"emailAddress": "testguy3@gmail.com",
"dateOfBirth": "1964-10-01",
"hasSecretAddress": false,
"isReservedAgainstSalesMaterial": false
}
]
}

View File

@@ -0,0 +1,3 @@
list;59088032;Jiri Novak;Vika;StreetName;4312;Sandnes;NO;true;StreetName;StreetName 1A;NORWAY;+4793488400;+4793488999;testguy@gmail.com;1962-10-01;false;false
list;59088033;Tomas Novak;Vika;StreetName;4318;Bergen;NO;true;Postboks 16;StreetName 1B;NORWAY;+4793488888;;testguy2@gmail.com;1963-10-01;false;false
list;59088034;Karel Novak;Vika;StreetName;4319;Stavanger;NO;true;StreetName;StreetName 1C;NORWAY;+4793488777;;testguy3@gmail.com;1964-10-01;false;false
1 list 59088032 Jiri Novak Vika StreetName 4312 Sandnes NO true StreetName StreetName 1A NORWAY +4793488400 +4793488999 testguy@gmail.com 1962-10-01 false false
2 list 59088033 Tomas Novak Vika StreetName 4318 Bergen NO true Postboks 16 StreetName 1B NORWAY +4793488888 testguy2@gmail.com 1963-10-01 false false
3 list 59088034 Karel Novak Vika StreetName 4319 Stavanger NO true StreetName StreetName 1C NORWAY +4793488777 testguy3@gmail.com 1964-10-01 false false

BIN
misc/schéma.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
flask
stomp.py
xmltodict

4
wso2/deployment.toml Normal file
View File

@@ -0,0 +1,4 @@
[super_admin]
username = "admin"
password = "admin"
create_admin_account = true