saved
This commit is contained in:
36
CSV.py
Normal file
36
CSV.py
Normal 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
9
Dockerfile
Normal 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 . .
|
||||
27
README.md
27
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.
|
||||
67
docker-compose.yml
Normal file
67
docker-compose.yml
Normal 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
9
flask_backend/Dockerfile
Normal 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
14
flask_backend/Sender.py
Normal 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()
|
||||
|
||||
25
flask_backend/Stomp_client.py
Normal file
25
flask_backend/Stomp_client.py
Normal 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
20
flask_backend/app.py
Normal 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)
|
||||
19
flask_backend/templates/index.html
Normal file
19
flask_backend/templates/index.html
Normal 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>
|
||||
65
misc/inputs/Input_payload.xml
Normal file
65
misc/inputs/Input_payload.xml
Normal 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>
|
||||
56
misc/inputs/Output_file_AMQ.json
Normal file
56
misc/inputs/Output_file_AMQ.json
Normal 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
|
||||
}
|
||||
]
|
||||
}
|
||||
3
misc/output/Output_file.csv
Normal file
3
misc/output/Output_file.csv
Normal 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
|
||||
|
BIN
misc/schéma.png
Normal file
BIN
misc/schéma.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
flask
|
||||
stomp.py
|
||||
xmltodict
|
||||
4
wso2/deployment.toml
Normal file
4
wso2/deployment.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[super_admin]
|
||||
username = "admin"
|
||||
password = "admin"
|
||||
create_admin_account = true
|
||||
Reference in New Issue
Block a user