Parte e c'è il monitor

This commit is contained in:
Gaetano Savo 2025-07-27 13:05:39 +02:00
parent 32603ae8dd
commit f4095584f1
32 changed files with 4359 additions and 314 deletions

5
META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,5 @@
Manifest-Version: 1.0
Build-Jdk-Spec: 1.8
Created-By: Maven Archiver 3.5.0
Main-Class: com.fideuram.bulk.monitor.JobMonitorApplication

202
README.md
View File

@ -7,14 +7,14 @@ Un'applicazione Spring Boot Batch che gestisce l'elaborazione dati tra due datab
## Requisiti
- Java 11 o superiore
- Java 8 o superiore
- Maven
- SQL Server
## Struttura del Progetto
```plaintext
src/main/java/com/armundia/bulk/
src/main/java/com/fideuram/bulk/
├── BatchApplication.java # Classe principale dell'applicazione
└── config/
├── BatchDispachConfig.java # Configurazione del batch job
@ -31,7 +31,7 @@ Il progetto utilizza:
### Branch
- `master`: versione stabile per Java 21
- `master`: versione stabile per Java 8
- `jdk11`: versione migrata a Java 11 con Spring Boot 2.7.x
### Database
@ -98,16 +98,16 @@ L'applicazione utilizza l'iniezione delle dipendenze di Spring per gestire i Jdb
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "c6stampeJdbcTemplate")
public JdbcTemplate c6stampeJdbcTemplate(DataSource c6stampeDataSource) {
return new JdbcTemplate(c6stampeDataSource);
@Bean(name = "trimestraleJdbcTemplate")
public JdbcTemplate trimestraleJdbcTemplate(DataSource trimestraleDataSource) {
return new JdbcTemplate(trimestraleDataSource);
}
}
@Configuration
public class BatchDispachConfig {
public BatchDispachConfig(JdbcTemplate c6stampeJdbcTemplate) {
this.c6stampeJdbcTemplate = c6stampeJdbcTemplate;
public BatchDispachConfig(JdbcTemplate trimestraleJdbcTemplate) {
this.trimestraleJdbcTemplate = trimestraleJdbcTemplate;
}
}
```
@ -123,7 +123,7 @@ Spring risolve le dipendenze in questo modo:
## Flusso dell'Applicazione
1. L'applicazione parte da `BatchApplication` (classe principale con `@SpringBootApplication`)
2. Spring Boot esegue la scansione del package `com.armundia.bulk` e trova:
2. Spring Boot esegue la scansione del package `com.fideuram.bulk` e trova:
- `BatchDispachConfig` (annotata con `@Configuration`)
- Crea automaticamente i bean definiti in `BatchDispachConfig`
3. `BatchApplication` utilizza il job attraverso:
@ -132,3 +132,187 @@ Spring risolve le dipendenze in questo modo:
@Autowired
private Job dispachJob;
```
## Comandi di Esecuzione
Il progetto include uno script `build.bat` che semplifica la compilazione e l'esecuzione:
### Compilazione
```bash
.\build.bat compile
```
### Esecuzione Job Batch
```bash
# Esecuzione senza job automatici (configurazione predefinita)
.\build.bat run
# Esecuzione con job specifico in modalità debug
.\build.bat debug
```
### Monitor Grafici
```bash
# Monitor GUI (Swing Desktop)
.\build.bat monitor-gui
# Monitor Web: avvia l'app e vai su http://localhost:8080
.\build.bat run
```
## Sistema di Monitoraggio
### Monitor Web (HTML) - **RACCOMANDATO**
**Avvio:**
1. Esegui `.\.build.bat run`
2. Apri il browser su `http://localhost:8080`
**Funzionalità:**
- **Interfaccia web moderna** con design responsive
- **Tabella dinamica** con dettagli completi dei job batch
- **Auto-refresh ON/OFF** configurabile
- **Aggiornamento manuale** con pulsante dedicato
- **Avvio job batch** direttamente dall'interfaccia
- **Gestione errori** con messaggi informativi
- **Formattazione automatica** di date e stati
- **Colori per gli stati** (verde=completato, rosso=fallito, blu=in esecuzione)
**Sezione Avvio Job:**
- Pulsanti dinamici per tutti i job disponibili
- Conferma prima dell'avvio
- Feedback in tempo reale
- Aggiornamento automatico dopo l'avvio
### Monitor GUI (Swing Desktop)
**Avvio:**
```bash
.\build.bat monitor-gui
```
**Funzionalità:**
- **Interfaccia desktop** Java Swing
- **Auto-refresh ON/OFF** toggle
- **Aggiornamento manuale**
- **Tabella con dettagli job**
## API Endpoints
L'applicazione espone i seguenti endpoint REST:
### Monitoraggio Job
```http
GET /actuator/batch/jobs
```
Restituisce la lista delle esecuzioni job con dettagli completi.
### Job Disponibili
```http
GET /actuator/batch/available-jobs
```
Restituisce la lista dei job batch disponibili per l'avvio.
### Avvio Job
```http
POST /actuator/batch/launch/{jobName}
```
Avvia un job batch specifico. Parametri automatici:
- `timestamp`: timestamp di avvio
- `launchedBy`: "monitor"
**Esempio di risposta:**
```json
{
"status": "success",
"message": "Job 'dispachJob' avviato con successo",
"executionId": 123,
"jobStatus": "STARTING"
}
```
## Configurazione Avanzata
### Disabilitazione Auto-Start Job
Per impostazione predefinita, i job non si avviano automaticamente:
```properties
# In application.properties
spring.batch.job.enabled=false
```
### Configurazione Actuator
Gli endpoint di monitoraggio sono abilitati tramite:
```properties
# Endpoint Actuator per il monitoraggio
management.endpoints.web.exposure.include=health,info,batch
management.endpoint.batch.enabled=true
management.endpoints.web.base-path=/actuator
```
### Database Job Repository
L'applicazione utilizza SQL Server per il job repository con tabelle personalizzate:
```properties
spring.sql.init.mode=always
spring.sql.init.schema-locations=classpath:schema-sqlserver.sql
spring.batch.jdbc.initialize-schema=never
```
## Job Disponibili
I job batch configurati nell'applicazione:
1. **`dispachJob`** - Job principale di dispatching
2. **`preTrimestraleJob`** - Job per elaborazioni trimestrali
3. **`helloWorldJob`** - Job di esempio per test
## Risoluzione Problemi
### Job Non Partono Automaticamente
**Comportamento Corretto** - I job sono configurati per non partire automaticamente.
### Monitor GUI Non Si Apre
- Verifica che l'applicazione Spring Boot sia in esecuzione (`.\.build.bat run`)
- Controlla che la porta 8080 non sia occupata
- Usa il monitor web come alternativa
### Errori di Connessione Database
- Verifica le credenziali in `application.properties`
- Controlla che SQL Server sia accessibile
- Verifica che le tabelle Spring Batch siano create
### Job Già in Esecuzione
Se ricevi l'errore "Job già in esecuzione":
- Attendi il completamento del job corrente
- Controlla lo stato nella tabella del monitor
- Verifica i log per eventuali job bloccati
## Log e Debug
I log sono configurati per fornire informazioni dettagliate:
```properties
logging.level.com.fideuram.bulk=TRACE
logging.level.org.springframework.batch=INFO
```
Per debug avanzato, usa:
```bash
.\build.bat debug

118
READMEfl.md Normal file
View File

@ -0,0 +1,118 @@
# Considerazioni sulla Connessione ConsulenzaUnicaFL (PDC)
## Analisi della Configurazione di Connessione
### Configurazione SSIS (w6catr.dtsx)
Il package SSIS `w6catr.dtsx` presenta una configurazione di connessione che richiede attenzione:
#### Dettagli della Connessione
- **Nome Connessione**: `ConsulenzaUnica`
- **Server**: `bfdspdc`
- **Database**: `ConsulenzaUnica`
- **User ID**: `userHP`
- **Provider**: `SQLNCLI11.1` (SQL Server Native Client 11.1)
- **Connection Manager ID**: `{769C2BE7-5528-4CF6-9896-1E69A54EF015}`
#### Stored Procedures Chiamate
Il package esegue le seguenti stored procedures:
1. **Apri Log** (riga 75): `execute [ConsulenzaUnicaFL].[dbo].[Log_InserisciLog] 'Replica_W6Catrf'`
2. **Chiudi Log** (riga 92): `execute [ConsulenzaUnicaFL].[dbo].[Log_ChiudiLog] 'Replica_W6Catrf'`
### ⚠️ Problematiche Identificate
#### 1. Discrepanza nei Nomi dei Database
- **Connessione**: Punta al database `ConsulenzaUnica`
- **Stored Procedures**: Chiamate con prefisso `[ConsulenzaUnicaFL]`
#### 2. Possibili Scenari
1. **Cross-Database Query**: Le stored procedures esistono nel database `ConsulenzaUnicaFL` e vengono chiamate dal database `ConsulenzaUnica`
2. **Errore di Nomenclatura**: Possibile inconsistenza nei nomi dei database
3. **Configurazione Runtime**: Il file di configurazione potrebbe sovrascrivere i parametri di connessione
### Configurazione Esterna
Il package utilizza un file di configurazione esterno:
- **Percorso**: `E:\ETL\Finale\Repliche\w6catr.dtsConfig`
- **Tipo**: Configuration File (ConfigurationType="1")
Questo file potrebbe contenere override dei parametri di connessione a runtime.
### Implementazione Spring Batch
Nel codice Java Spring Batch (`S0200W6catr.java`), le stesse stored procedures vengono chiamate:
```java
// Riga 47 - Apri Log
trimestraleJdbcTemplate.execute("EXEC [ConsulenzaUnicaFL].[dbo].[Log_InserisciLog] 'Replica_W6Catrf'");
// Riga 83 - Chiudi Log
trimestraleJdbcTemplate.execute("EXEC [ConsulenzaUnicaFL].[dbo].[Log_ChiudiLog] 'Replica_W6Catrf'");
```
### 🔍 Azioni Raccomandate per la Risoluzione
#### 1. Verifica Database
```sql
-- Connettiti al server bfdspdc e verifica i database esistenti
SELECT name FROM sys.databases WHERE name LIKE '%Consulenza%';
```
#### 2. Ricerca Stored Procedures
```sql
-- Se esiste ConsulenzaUnicaFL
USE ConsulenzaUnicaFL;
SELECT name, create_date, modify_date
FROM sys.procedures
WHERE name IN ('Log_InserisciLog', 'Log_ChiudiLog');
-- Se esiste solo ConsulenzaUnica
USE ConsulenzaUnica;
SELECT name, create_date, modify_date
FROM sys.procedures
WHERE name IN ('Log_InserisciLog', 'Log_ChiudiLog');
```
#### 3. Verifica Cross-Database Access
```sql
-- Verifica se ConsulenzaUnica può accedere a ConsulenzaUnicaFL
USE ConsulenzaUnica;
SELECT * FROM [ConsulenzaUnicaFL].sys.procedures
WHERE name LIKE '%Log_%';
```
#### 4. Controllo File di Configurazione
Verificare il contenuto del file `E:\ETL\Finale\Repliche\w6catr.dtsConfig` per eventuali override di configurazione.
### 📝 Note per lo Sviluppo
1. **Consistenza**: Assicurarsi che i nomi dei database siano consistenti tra SSIS e Spring Batch
2. **Gestione Errori**: Implementare gestione degli errori per connessioni fallite
3. **Logging**: Aggiungere logging dettagliato per troubleshooting delle connessioni
4. **Documentazione**: Mantenere aggiornata la documentazione delle dipendenze tra database
### 🔧 Configurazione Spring Batch
La configurazione Spring Batch dovrebbe essere allineata con la configurazione SSIS:
```properties
# Esempio di configurazione per ConsulenzaUnicaFL
spring.datasource.consulenza.jdbc-url=jdbc:sqlserver://bfdspdc:1433;databaseName=ConsulenzaUnicaFL
spring.datasource.consulenza.username=userHP
spring.datasource.consulenza.password=${CONSULENZA_PASSWORD}
spring.datasource.consulenza.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
```
### 📊 Impatto sulla Migrazione
Durante la migrazione da SSIS a Spring Batch, considerare:
- Verifica delle dipendenze tra database
- Test delle stored procedures in entrambi gli ambienti
- Validazione delle configurazioni di connessione
- Backup e rollback plan per eventuali problemi
---
**Ultimo aggiornamento**: 23 Luglio 2025
**Autore**: Analisi automatica del progetto BatchDataProcessing

View File

@ -2,7 +2,7 @@
setlocal
rem Imposta JAVA_HOME
set JAVA_HOME=C:\Dev2012\BUILDERS\java\jdk-21.0.6
set JAVA_HOME=C:\Dev2012\BUILDERS\java\jdk1.8.0_291
rem Aggiungi java al PATH
set PATH=%JAVA_HOME%\bin;%PATH%
@ -18,7 +18,8 @@ if "%1"=="run" (
if not exist target\pdcreport-bulk-0.0.1-SNAPSHOT.jar (
call mvn clean package
)
java -jar target\pdcreport-bulk-0.0.1-SNAPSHOT.jar --spring.batch.job.name=dispachJob >run.log 2>&1
java -jar target\pdcreport-bulk-0.0.1-SNAPSHOT.jar >run.log 2>&1
@REM java -jar target\pdcreport-bulk-0.0.1-SNAPSHOT.jar --spring.batch.job.name=copiaTabelleJob >run.log 2>&1
goto :eof
)
@ -31,9 +32,28 @@ if "%1"=="debug" (
goto :eof
)
if "%1"=="debug-remote" (
echo Avvio dell'applicazione con debug remoto Java...
echo IMPORTANTE: Connetti il debugger IDE alla porta 5005
echo Premi CTRL+C per terminare quando hai finito il debug
if not exist target\pdcreport-bulk-0.0.1-SNAPSHOT.jar (
call mvn clean package
)
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -jar target\pdcreport-bulk-0.0.1-SNAPSHOT.jar
goto :eof
)
if "%1"=="monitor-gui" (
echo Avvio monitor grafico...
start "Spring Batch Monitor" java -jar target\job-monitor-jar-with-dependencies.jar
if not exist target\pdcreport-bulk-0.0.1-SNAPSHOT.jar (
call mvn clean package
)
echo Estrazione dipendenze...
if not exist target\lib mkdir target\lib
cd target\lib
jar -xf ..\pdcreport-bulk-0.0.1-SNAPSHOT.jar BOOT-INF/lib/
cd ..\..
start "Spring Batch Monitor" java -cp "target\classes;target\lib\BOOT-INF\lib\*" com.fideuram.bulk.monitor.ui.JobMonitorFrame
goto :eof
)

View File

@ -0,0 +1,152 @@
<?xml version="1.0"?>
<DTS:Executable xmlns:DTS="www.microsoft.com/SqlServer/Dts"
DTS:refId="Package"
DTS:CreationDate="10/29/2013 3:07:19 PM"
DTS:CreationName="Microsoft.Package"
DTS:CreatorComputerName="BFDSREPORTING6"
DTS:CreatorName="FIDEURAM\f701264"
DTS:DTSID="{81F16A17-10F5-45B4-BC74-23D67DBD331B}"
DTS:ExecutableType="Microsoft.Package"
DTS:LastModifiedProductVersion="16.0.5270.0"
DTS:LocaleID="1033"
DTS:ObjectName="STAGING_APPO_CONTRATTI"
DTS:PackageType="5"
DTS:VersionBuild="24"
DTS:VersionGUID="{F3091FA4-14BF-4EF5-8951-C5720FF41B32}">
<DTS:Property
DTS:Name="PackageFormatVersion">8</DTS:Property>
<DTS:ConnectionManagers>
<DTS:ConnectionManager
DTS:refId="Package.ConnectionManagers[bfdskreport01p.C6StampeCentralizzate.F701264]"
DTS:CreationName="OLEDB"
DTS:DTSID="{4B3CE9AD-EB43-4A30-BECB-9783AC3E3CD8}"
DTS:ObjectName="bfdskreport01p.C6StampeCentralizzate.F701264">
<DTS:ObjectData>
<DTS:ConnectionManager
DTS:ConnectRetryCount="1"
DTS:ConnectRetryInterval="5"
DTS:ConnectionString="Data Source=bfdskreport01p;User ID=F701264;Initial Catalog=C6StampeCentralizzate;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False;">
<DTS:Password
DTS:Name="Password"
Sensitive="1"
Encrypted="1">AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAACxGazWeQCkeEpbM2ToeHqwAAAAAIAAAARABUAFMAAAADZgAAwAAAABAAAACbDARvTMUt5XIzBLuwGP1QAAAAAASAAACgAAAAEAAAAGrG6t5lpqSmH5ZhrdL7gJoYAAAANUQETitZdTw9KfiA7wCC/vX+j7Zc0yJeFAAAAC6kmuqkmJ4wdqD4hFaeIoN5YU29</DTS:Password>
</DTS:ConnectionManager>
</DTS:ObjectData>
</DTS:ConnectionManager>
<DTS:ConnectionManager
DTS:refId="Package.ConnectionManagers[RicodificaMassiva.dtsx]"
DTS:CreationName="FILE"
DTS:DTSID="{832B8132-F5E1-4CBC-8274-97EED4EDBF31}"
DTS:ObjectName="RicodificaMassiva.dtsx">
<DTS:ObjectData>
<DTS:ConnectionManager
DTS:ConnectionString="D:\C6_batch\SSIS_ContrattoSeiPeriodico_New\SSIS_ContrattoSeiPeriodico\SSIS_ContrattoSeiPeriodico\RicodificaMassiva.dtsx" />
</DTS:ObjectData>
</DTS:ConnectionManager>
</DTS:ConnectionManagers>
<DTS:Variables />
<DTS:Executables>
<DTS:Executable
DTS:refId="Package\Crea APPO_CONTRATTI"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Execute SQL Task"
DTS:DTSID="{45843141-72A0-4085-95C0-CF8A6025B8A4}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="Crea APPO_CONTRATTI"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; Microsoft SQL Server v9; © 2004 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{4B3CE9AD-EB43-4A30-BECB-9783AC3E3CD8}"
SQLTask:BypassPrepare="False"
SQLTask:SqlStatementSource="EXEC C6StagingPeriodico.RP_ST_APPO_CONTRATTI" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
<DTS:Executable
DTS:refId="Package\Ricodifica Massiva"
DTS:CreationName="Microsoft.ExecutePackageTask"
DTS:Description="Execute Package Task"
DTS:DTSID="{1EAA0041-003A-4AB0-A49D-9A735E1DA967}"
DTS:ExecutableType="Microsoft.ExecutePackageTask"
DTS:LocaleID="-1"
DTS:ObjectName="Ricodifica Massiva"
DTS:TaskContact="Executes DTS packages;Microsoft Corporation; Microsoft SQL Server v9; (C) 2004 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1">
<DTS:Variables />
<DTS:ObjectData>
<ExecutePackageTask>
<Connection>{832B8132-F5E1-4CBC-8274-97EED4EDBF31}</Connection>
</ExecutePackageTask>
</DTS:ObjectData>
</DTS:Executable>
</DTS:Executables>
<DTS:PrecedenceConstraints>
<DTS:PrecedenceConstraint
DTS:refId="Package.PrecedenceConstraints[Constraint]"
DTS:CreationName=""
DTS:DTSID="{8F4DDD39-42EC-42E8-9F69-AEDDF191F3C2}"
DTS:From="Package\Ricodifica Massiva"
DTS:LogicalAnd="True"
DTS:ObjectName="Constraint"
DTS:To="Package\Crea APPO_CONTRATTI" />
</DTS:PrecedenceConstraints>
<DTS:DesignTimeProperties><![CDATA[<?xml version="1.0"?>
<!--This CDATA section contains the layout information of the package. The section includes information such as (x,y) coordinates, width, and height.-->
<!--If you manually edit this section and make a mistake, you can delete it. -->
<!--The package will still be able to load normally but the previous layout information will be lost and the designer will automatically re-arrange the elements on the design surface.-->
<Objects
Version="sql12">
<!--Each node below will contain properties that do not affect runtime behavior.-->
<Package
design-time-name="Package">
<LayoutInfo>
<GraphLayout
Capacity="4" xmlns="clr-namespace:Microsoft.SqlServer.IntegrationServices.Designer.Model.Serialization;assembly=Microsoft.SqlServer.IntegrationServices.Graph" xmlns:mssgle="clr-namespace:Microsoft.SqlServer.Graph.LayoutEngine;assembly=Microsoft.SqlServer.Graph" xmlns:assembly="http://schemas.microsoft.com/winfx/2006/xaml">
<NodeLayout
Size="205,42"
Id="Package\Crea APPO_CONTRATTI"
TopLeft="81.8888877506058,164.308175132053" />
<NodeLayout
Size="136,44"
Id="Package\Ricodifica Massiva"
TopLeft="370.799784975419,83.4999986052513" />
<EdgeLayout
Id="Package.PrecedenceConstraints[Constraint]"
TopLeft="438.799784975419,127.499998605251">
<EdgeLayout.Curve>
<mssgle:Curve
StartConnector="{assembly:Null}"
EndConnector="-254.410897224813,36.8081765268017"
Start="0,0"
End="-254.410897224813,29.3081765268017">
<mssgle:Curve.Segments>
<mssgle:SegmentCollection
Capacity="5">
<mssgle:LineSegment
End="0,14.4040882634009" />
<mssgle:CubicBezierSegment
Point1="0,14.4040882634009"
Point2="0,18.4040882634009"
Point3="-4,18.4040882634009" />
<mssgle:LineSegment
End="-250.410897224813,18.4040882634009" />
<mssgle:CubicBezierSegment
Point1="-250.410897224813,18.4040882634009"
Point2="-254.410897224813,18.4040882634009"
Point3="-254.410897224813,22.4040882634009" />
<mssgle:LineSegment
End="-254.410897224813,29.3081765268017" />
</mssgle:SegmentCollection>
</mssgle:Curve.Segments>
</mssgle:Curve>
</EdgeLayout.Curve>
<EdgeLayout.Labels>
<EdgeLabelCollection />
</EdgeLayout.Labels>
</EdgeLayout>
</GraphLayout>
</LayoutInfo>
</Package>
</Objects>]]></DTS:DesignTimeProperties>
</DTS:Executable>

View File

@ -0,0 +1,204 @@
<?xml version="1.0"?>
<DTS:Executable xmlns:DTS="www.microsoft.com/SqlServer/Dts"
DTS:refId="Package"
DTS:CreationDate="9/18/2013 11:02:13 AM"
DTS:CreationName="Microsoft.Package"
DTS:CreatorComputerName="BFDSREPORTING6"
DTS:CreatorName="FIDEURAM\f701264"
DTS:DTSID="{859815A1-E12C-44FD-A5FA-647ECE25B5EB}"
DTS:ExecutableType="Microsoft.Package"
DTS:LastModifiedProductVersion="12.0.2430.0"
DTS:LocaleID="1033"
DTS:ObjectName="STAGING_PRETRIMESTRALE"
DTS:PackageType="5"
DTS:VersionBuild="22"
DTS:VersionGUID="{BDC94B8F-BBB5-4886-852E-D9BA64B40EC4}">
<DTS:Property
DTS:Name="PackageFormatVersion">8</DTS:Property>
<DTS:ConnectionManagers>
<DTS:ConnectionManager
DTS:refId="Package.ConnectionManagers[bfdskreport01p.C6StampeCentralizzate.F701264]"
DTS:CreationName="OLEDB"
DTS:DTSID="{2BE1DE83-BAD5-40DB-ACE0-50E4690861FD}"
DTS:ObjectName="bfdskreport01p.C6StampeCentralizzate.F701264">
<DTS:ObjectData>
<DTS:ConnectionManager
DTS:ConnectionString="Data Source=bfdskreport01p;User ID=F701264;Initial Catalog=C6StampeCentralizzate;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False;">
<DTS:Password
DTS:Name="Password"
Sensitive="1"
Encrypted="1">AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAzJ7rFSfYgUC3WDUzwpLuTwAAAAAIAAAARABUAFMAAAADZgAAwAAAABAAAAC8KVk2JjMj9xDk8NOfFTv0AAAAAASAAACgAAAAEAAAAOX8NIHAQfClAPyJDuX3RX4YAAAARbpWOGYrLhaapr/g9M1YuHdZl22FI65WFAAAAKnMsV9jGOdRivBht4G0Ly3K7aC9</DTS:Password>
</DTS:ConnectionManager>
</DTS:ObjectData>
</DTS:ConnectionManager>
</DTS:ConnectionManagers>
<DTS:Variables />
<DTS:Executables>
<DTS:Executable
DTS:refId="Package\Avvio Trimestrale"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Avvio la trimestrale su C6MartPeriodico_Tab_Semaforo"
DTS:DTSID="{864DCCCE-02C6-4E9F-8545-3F76DD63BCC9}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="Avvio Trimestrale"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; SQL Server 2014; © 2014 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{2BE1DE83-BAD5-40DB-ACE0-50E4690861FD}"
SQLTask:SqlStatementSource="exec C6MartPeriodico.SP_Valorizza_Stati_semaforo_TRIM trim_start,SEI&#xA;&#xA;delete from C6MartPeriodico.tab_semaforo where id_milestone&gt;8" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
<DTS:Executable
DTS:refId="Package\Congelamento CONTRATTO SEI"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Execute SQL Task"
DTS:DTSID="{C90C28F5-8426-43CF-9293-1A1FF89FA3FC}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="Congelamento CONTRATTO SEI"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; Microsoft SQL Server v9; © 2004 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{2BE1DE83-BAD5-40DB-ACE0-50E4690861FD}"
SQLTask:BypassPrepare="False"
SQLTask:SqlStatementSource="EXEC [C6StagingPeriodico].[RP_ST_CONTRATTIPRETRIMESTRALE]" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
<DTS:Executable
DTS:refId="Package\Truncate Tab_Semaforo"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Execute SQL Task"
DTS:DTSID="{0D5F42C2-2795-409B-A2B6-09692BE9C16A}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="Truncate Tab_Semaforo"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; SQL Server 2014; © 2014 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{2BE1DE83-BAD5-40DB-ACE0-50E4690861FD}"
SQLTask:SqlStatementSource="truncate table C6MartPeriodico.tab_semaforo" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
</DTS:Executables>
<DTS:PrecedenceConstraints>
<DTS:PrecedenceConstraint
DTS:refId="Package.PrecedenceConstraints[Constraint]"
DTS:CreationName=""
DTS:DTSID="{6D7CBA9B-44FD-408A-B0FC-4CF1EACCCA0A}"
DTS:From="Package\Truncate Tab_Semaforo"
DTS:LogicalAnd="True"
DTS:ObjectName="Constraint"
DTS:To="Package\Avvio Trimestrale" />
<DTS:PrecedenceConstraint
DTS:refId="Package.PrecedenceConstraints[Constraint 1]"
DTS:CreationName=""
DTS:DTSID="{BB592DCD-840F-4F97-979F-6332529B57F8}"
DTS:From="Package\Avvio Trimestrale"
DTS:LogicalAnd="True"
DTS:ObjectName="Constraint 1"
DTS:To="Package\Congelamento CONTRATTO SEI" />
</DTS:PrecedenceConstraints>
<DTS:DesignTimeProperties><![CDATA[<?xml version="1.0"?>
<!--This CDATA section contains the layout information of the package. The section includes information such as (x,y) coordinates, width, and height.-->
<!--If you manually edit this section and make a mistake, you can delete it. -->
<!--The package will still be able to load normally but the previous layout information will be lost and the designer will automatically re-arrange the elements on the design surface.-->
<Objects
Version="sql12">
<!--Each node below will contain properties that do not affect runtime behavior.-->
<Package
design-time-name="Package">
<LayoutInfo>
<GraphLayout
Capacity="8" xmlns="clr-namespace:Microsoft.SqlServer.IntegrationServices.Designer.Model.Serialization;assembly=Microsoft.SqlServer.IntegrationServices.Graph" xmlns:mssgle="clr-namespace:Microsoft.SqlServer.Graph.LayoutEngine;assembly=Microsoft.SqlServer.Graph" xmlns:assembly="http://schemas.microsoft.com/winfx/2006/xaml">
<NodeLayout
Size="160,42"
Id="Package\Avvio Trimestrale"
TopLeft="169.166664145887,89.699998396039" />
<NodeLayout
Size="230,42"
Id="Package\Congelamento CONTRATTO SEI"
TopLeft="315.083328720182,165.83333046635" />
<NodeLayout
Size="193.333333333334,42"
Id="Package\Truncate Tab_Semaforo"
TopLeft="28.7499995715916,22.0999996048212" />
<EdgeLayout
Id="Package.PrecedenceConstraints[Constraint]"
TopLeft="125.249999571592,64.0999996048212">
<EdgeLayout.Curve>
<mssgle:Curve
StartConnector="{assembly:Null}"
EndConnector="123.916664574295,25.5999987912178"
Start="0,0"
End="123.916664574295,18.0999987912178">
<mssgle:Curve.Segments>
<mssgle:SegmentCollection
Capacity="5">
<mssgle:LineSegment
End="0,8.79999939560891" />
<mssgle:CubicBezierSegment
Point1="0,8.79999939560891"
Point2="0,12.7999993956089"
Point3="4,12.7999993956089" />
<mssgle:LineSegment
End="119.916664574295,12.7999993956089" />
<mssgle:CubicBezierSegment
Point1="119.916664574295,12.7999993956089"
Point2="123.916664574295,12.7999993956089"
Point3="123.916664574295,16.7999993956089" />
<mssgle:LineSegment
End="123.916664574295,18.0999987912178" />
</mssgle:SegmentCollection>
</mssgle:Curve.Segments>
</mssgle:Curve>
</EdgeLayout.Curve>
<EdgeLayout.Labels>
<EdgeLabelCollection />
</EdgeLayout.Labels>
</EdgeLayout>
<EdgeLayout
Id="Package.PrecedenceConstraints[Constraint 1]"
TopLeft="249.166664145887,131.699998396039">
<EdgeLayout.Curve>
<mssgle:Curve
StartConnector="{assembly:Null}"
EndConnector="180.916664574295,34.133332070311"
Start="0,0"
End="180.916664574295,26.633332070311">
<mssgle:Curve.Segments>
<mssgle:SegmentCollection
Capacity="5">
<mssgle:LineSegment
End="0,13.0666660351555" />
<mssgle:CubicBezierSegment
Point1="0,13.0666660351555"
Point2="0,17.0666660351555"
Point3="4,17.0666660351555" />
<mssgle:LineSegment
End="176.916664574295,17.0666660351555" />
<mssgle:CubicBezierSegment
Point1="176.916664574295,17.0666660351555"
Point2="180.916664574295,17.0666660351555"
Point3="180.916664574295,21.0666660351555" />
<mssgle:LineSegment
End="180.916664574295,26.633332070311" />
</mssgle:SegmentCollection>
</mssgle:Curve.Segments>
</mssgle:Curve>
</EdgeLayout.Curve>
<EdgeLayout.Labels>
<EdgeLabelCollection />
</EdgeLayout.Labels>
</EdgeLayout>
</GraphLayout>
</LayoutInfo>
</Package>
</Objects>]]></DTS:DesignTimeProperties>
</DTS:Executable>

View File

@ -0,0 +1,272 @@
<?xml version="1.0"?>
<DTS:Executable xmlns:DTS="www.microsoft.com/SqlServer/Dts"
DTS:refId="Package"
DTS:CreationDate="10/1/2013 12:29:19 PM"
DTS:CreationName="Microsoft.Package"
DTS:CreatorComputerName="BFDSREPORTING6"
DTS:CreatorName="FIDEURAM\f701264"
DTS:DTSID="{BB5415F0-900C-4CC0-859D-977A9E530CB1}"
DTS:ExecutableType="Microsoft.Package"
DTS:LastModifiedProductVersion="16.0.5270.0"
DTS:LocaleID="1033"
DTS:ObjectName="STAGING_VCONTRATTI"
DTS:PackageType="5"
DTS:VersionBuild="17"
DTS:VersionGUID="{AE5E7943-DCCC-4F3E-8E36-2C331A096247}">
<DTS:Property
DTS:Name="PackageFormatVersion">8</DTS:Property>
<DTS:ConnectionManagers>
<DTS:ConnectionManager
DTS:refId="Package.ConnectionManagers[bfdskreport01p.C6StampeCentralizzate.F701264]"
DTS:CreationName="OLEDB"
DTS:DTSID="{0DC751EE-62A4-462B-973D-F420C3361BF9}"
DTS:ObjectName="bfdskreport01p.C6StampeCentralizzate.F701264">
<DTS:ObjectData>
<DTS:ConnectionManager
DTS:ConnectRetryCount="1"
DTS:ConnectRetryInterval="5"
DTS:ConnectionString="Data Source=bfdskreport01p;User ID=F701264;Initial Catalog=C6StampeCentralizzate;Provider=SQLNCLI11.1;Persist Security Info=True;Auto Translate=False;">
<DTS:Password
DTS:Name="Password"
Sensitive="1"
Encrypted="1">AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAACxGazWeQCkeEpbM2ToeHqwAAAAAIAAAARABUAFMAAAADZgAAwAAAABAAAADdPRJZLRYNHNuHhAmaK9LEAAAAAASAAACgAAAAEAAAAO4jugsFa/FxJVzRF79HFPgYAAAApEc+oenhJ7AsMaR0+/do0NzumKDmWc0OFAAAAKAg2dVWlfp5pxNBCZRavsylj0pV</DTS:Password>
</DTS:ConnectionManager>
</DTS:ObjectData>
</DTS:ConnectionManager>
<DTS:ConnectionManager
DTS:refId="Package.ConnectionManagers[RicodificaMassiva.dtsx]"
DTS:CreationName="FILE"
DTS:DTSID="{6A09B842-E7AE-4F73-903C-CD37D3C5E36F}"
DTS:ObjectName="RicodificaMassiva.dtsx">
<DTS:ObjectData>
<DTS:ConnectionManager
DTS:ConnectionString="D:\C6_batch\SSIS_ContrattoSeiPeriodico_New\SSIS_ContrattoSeiPeriodico\SSIS_ContrattoSeiPeriodico\RicodificaMassiva.dtsx" />
</DTS:ObjectData>
</DTS:ConnectionManager>
</DTS:ConnectionManagers>
<DTS:Variables />
<DTS:Executables>
<DTS:Executable
DTS:refId="Package\Aggiorna APPO_CONTRATTI"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Execute SQL Task"
DTS:DTSID="{E1023C19-59AD-4672-8DC2-24047E1FCA89}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="Aggiorna APPO_CONTRATTI"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; Microsoft SQL Server v9; © 2004 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{0DC751EE-62A4-462B-973D-F420C3361BF9}"
SQLTask:BypassPrepare="False"
SQLTask:SqlStatementSource="EXEC [C6StagingPeriodico].[RP_UPDATE_APPO_CONTRATTI]" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
<DTS:Executable
DTS:refId="Package\Popola Semaforo App_Rendicontazione"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Execute SQL Task"
DTS:DTSID="{05CCF40B-39A0-4C0A-B8CF-25C790432FCC}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="Popola Semaforo App_Rendicontazione"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; SQL Server 2014; © 2014 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{0DC751EE-62A4-462B-973D-F420C3361BF9}"
SQLTask:SqlStatementSource="exec C6MartPeriodico.SP_Valorizza_Stati_semaforo_TRIM trim_start,SEI" xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
<DTS:Executable
DTS:refId="Package\Ricodifica Massiva"
DTS:CreationName="Microsoft.ExecutePackageTask"
DTS:Description="Execute Package Task"
DTS:DTSID="{2B2A0BD5-4921-47E7-BA95-79234EA5627F}"
DTS:ExecutableType="Microsoft.ExecutePackageTask"
DTS:LocaleID="-1"
DTS:ObjectName="Ricodifica Massiva"
DTS:TaskContact="Executes DTS packages;Microsoft Corporation; Microsoft SQL Server v9; (C) 2004 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1">
<DTS:Variables />
<DTS:ObjectData>
<ExecutePackageTask>
<Connection>{6A09B842-E7AE-4F73-903C-CD37D3C5E36F}</Connection>
</ExecutePackageTask>
</DTS:ObjectData>
</DTS:Executable>
<DTS:Executable
DTS:refId="Package\tronca semaforo App_Rendicontazione"
DTS:CreationName="Microsoft.ExecuteSQLTask"
DTS:Description="Execute SQL Task"
DTS:DTSID="{A59D403E-4E6A-47F3-95EB-FEC2E08184C3}"
DTS:ExecutableType="Microsoft.ExecuteSQLTask"
DTS:LocaleID="-1"
DTS:ObjectName="tronca semaforo App_Rendicontazione"
DTS:TaskContact="Execute SQL Task; Microsoft Corporation; SQL Server 2014; © 2014 Microsoft Corporation; All Rights Reserved;http://www.microsoft.com/sql/support/default.asp;1"
DTS:ThreadHint="0">
<DTS:Variables />
<DTS:ObjectData>
<SQLTask:SqlTaskData
SQLTask:Connection="{0DC751EE-62A4-462B-973D-F420C3361BF9}"
SQLTask:SqlStatementSource="truncate table C6MartPeriodico.tab_semaforo " xmlns:SQLTask="www.microsoft.com/sqlserver/dts/tasks/sqltask" />
</DTS:ObjectData>
</DTS:Executable>
</DTS:Executables>
<DTS:PrecedenceConstraints>
<DTS:PrecedenceConstraint
DTS:refId="Package.PrecedenceConstraints[Constraint]"
DTS:CreationName=""
DTS:DTSID="{3EB7D4D7-2EB1-4087-A6FB-8C4AC021E9D7}"
DTS:From="Package\Ricodifica Massiva"
DTS:LogicalAnd="True"
DTS:ObjectName="Constraint"
DTS:To="Package\Aggiorna APPO_CONTRATTI" />
<DTS:PrecedenceConstraint
DTS:refId="Package.PrecedenceConstraints[Constraint 1]"
DTS:CreationName=""
DTS:DTSID="{2A9D2718-0B04-4D68-9E97-AA5DB1B8BD8A}"
DTS:From="Package\tronca semaforo App_Rendicontazione"
DTS:LogicalAnd="True"
DTS:ObjectName="Constraint 1"
DTS:To="Package\Popola Semaforo App_Rendicontazione" />
<DTS:PrecedenceConstraint
DTS:refId="Package.PrecedenceConstraints[Constraint 2]"
DTS:CreationName=""
DTS:DTSID="{BC56F8C9-B08E-4103-B3F2-C58A55E4DDBC}"
DTS:From="Package\Popola Semaforo App_Rendicontazione"
DTS:LogicalAnd="True"
DTS:ObjectName="Constraint 2"
DTS:To="Package\Ricodifica Massiva" />
</DTS:PrecedenceConstraints>
<DTS:DesignTimeProperties><![CDATA[<?xml version="1.0"?>
<!--This CDATA section contains the layout information of the package. The section includes information such as (x,y) coordinates, width, and height.-->
<!--If you manually edit this section and make a mistake, you can delete it. -->
<!--The package will still be able to load normally but the previous layout information will be lost and the designer will automatically re-arrange the elements on the design surface.-->
<Objects
Version="sql12">
<!--Each node below will contain properties that do not affect runtime behavior.-->
<Package
design-time-name="Package">
<LayoutInfo>
<GraphLayout
Capacity="8" xmlns="clr-namespace:Microsoft.SqlServer.IntegrationServices.Designer.Model.Serialization;assembly=Microsoft.SqlServer.IntegrationServices.Graph" xmlns:mssgle="clr-namespace:Microsoft.SqlServer.Graph.LayoutEngine;assembly=Microsoft.SqlServer.Graph" xmlns:assembly="http://schemas.microsoft.com/winfx/2006/xaml">
<NodeLayout
Size="212,42"
Id="Package\Aggiorna APPO_CONTRATTI"
TopLeft="207.311317774485,201.10817476012" />
<NodeLayout
Size="275,42"
Id="Package\Popola Semaforo App_Rendicontazione"
TopLeft="3.08333332712456,74.9666653261582" />
<NodeLayout
Size="136,44"
Id="Package\Ricodifica Massiva"
TopLeft="157.583331067115,134.199997698665" />
<NodeLayout
Size="163,42"
Id="Package\tronca semaforo App_Rendicontazione"
TopLeft="0.416666660457835,4.63333323260148" />
<EdgeLayout
Id="Package.PrecedenceConstraints[Constraint]"
TopLeft="225.583331067115,178.199997698665">
<EdgeLayout.Curve>
<mssgle:Curve
StartConnector="{assembly:Null}"
EndConnector="87.7279867073698,22.9081770614555"
Start="0,0"
End="87.7279867073698,15.4081770614555">
<mssgle:Curve.Segments>
<mssgle:SegmentCollection
Capacity="5">
<mssgle:LineSegment
End="0,7.45408853072776" />
<mssgle:CubicBezierSegment
Point1="0,7.45408853072776"
Point2="0,11.4540885307278"
Point3="4,11.4540885307278" />
<mssgle:LineSegment
End="83.7279867073698,11.4540885307278" />
<mssgle:CubicBezierSegment
Point1="83.7279867073698,11.4540885307278"
Point2="87.7279867073698,11.4540885307278"
Point3="87.7279867073698,15.4540885307278" />
<mssgle:LineSegment
End="87.7279867073698,15.4081770614555" />
</mssgle:SegmentCollection>
</mssgle:Curve.Segments>
</mssgle:Curve>
</EdgeLayout.Curve>
<EdgeLayout.Labels>
<EdgeLabelCollection />
</EdgeLayout.Labels>
</EdgeLayout>
<EdgeLayout
Id="Package.PrecedenceConstraints[Constraint 1]"
TopLeft="81.9166666604578,46.6333332326015">
<EdgeLayout.Curve>
<mssgle:Curve
StartConnector="{assembly:Null}"
EndConnector="58.6666666666667,28.3333320935567"
Start="0,0"
End="58.6666666666667,20.8333320935567">
<mssgle:Curve.Segments>
<mssgle:SegmentCollection
Capacity="5">
<mssgle:LineSegment
End="0,10.1666660467784" />
<mssgle:CubicBezierSegment
Point1="0,10.1666660467784"
Point2="0,14.1666660467784"
Point3="4,14.1666660467784" />
<mssgle:LineSegment
End="54.6666666666667,14.1666660467784" />
<mssgle:CubicBezierSegment
Point1="54.6666666666667,14.1666660467784"
Point2="58.6666666666667,14.1666660467784"
Point3="58.6666666666667,18.1666660467784" />
<mssgle:LineSegment
End="58.6666666666667,20.8333320935567" />
</mssgle:SegmentCollection>
</mssgle:Curve.Segments>
</mssgle:Curve>
</EdgeLayout.Curve>
<EdgeLayout.Labels>
<EdgeLabelCollection />
</EdgeLayout.Labels>
</EdgeLayout>
<EdgeLayout
Id="Package.PrecedenceConstraints[Constraint 2]"
TopLeft="140.583333327125,116.966665326158">
<EdgeLayout.Curve>
<mssgle:Curve
StartConnector="{assembly:Null}"
EndConnector="16.9999977399904,39.2333323725068"
Start="0,0"
End="9.49999773999045,39.2333323725068">
<mssgle:Curve.Segments>
<mssgle:SegmentCollection
Capacity="5">
<mssgle:LineSegment
End="0,35.2333323725068" />
<mssgle:CubicBezierSegment
Point1="0,35.2333323725068"
Point2="0,39.2333323725068"
Point3="4,39.2333323725068" />
<mssgle:LineSegment
End="9.49999773999045,39.2333323725068" />
</mssgle:SegmentCollection>
</mssgle:Curve.Segments>
</mssgle:Curve>
</EdgeLayout.Curve>
<EdgeLayout.Labels>
<EdgeLabelCollection />
</EdgeLayout.Labels>
</EdgeLayout>
</GraphLayout>
</LayoutInfo>
</Package>
</Objects>]]></DTS:DesignTimeProperties>
</DTS:Executable>

2038
fonte/w6catr.dtsx Normal file

File diff suppressed because it is too large Load Diff

12
pom.xml
View File

@ -18,7 +18,7 @@
</parent>
<properties>
<java.version>11</java.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
@ -47,6 +47,14 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@ -64,7 +72,7 @@
<configuration>
<archive>
<manifest>
<mainClass>com.armundia.bulk.monitor.JobMonitorApplication</mainClass>
<mainClass>com.fideuram.bulk.monitor.JobMonitorApplication</mainClass>
</manifest>
</archive>
<descriptorRefs>

104
settings.xml Normal file
View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<pluginGroups>
<pluginGroup>com.intesasanpaolo.maven.plugins</pluginGroup>
</pluginGroups>
<servers>
<server>
<id>artifactory-central-repos</id>
<!-- central mirror id -->
<username>snapshot-deployer</username>
<password>snapshot</password>
<configuration>
<httpConfiguration>
<all>
<connectionTimeout>60000</connectionTimeout>
<readTimeout>60000</readTimeout>
</all>
</httpConfiguration>
</configuration>
</server>
<server>
<id>artifactory-local-repos</id>
<!-- local repos id -->
<username>snapshot-deployer</username>
<password>snapshot</password>
<configuration>
<httpConfiguration>
<all>
<connectionTimeout>60000</connectionTimeout>
<readTimeout>60000</readTimeout>
</all>
</httpConfiguration>
</configuration>
</server>
<server>
<id>artifactory-local-plugins-repos</id>
<!-- local repos id -->
<username>snapshot-deployer</username>
<password>snapshot</password>
<configuration>
<httpConfiguration>
<all>
<connectionTimeout>60000</connectionTimeout>
<readTimeout>60000</readTimeout>
</all>
</httpConfiguration>
</configuration>
</server>
<server>
<id>artifactory-remote-repos</id>
<!-- remote repos id -->
<username>snapshot-deployer</username>
<password>snapshot</password>
<configuration>
<httpConfiguration>
<all>
<connectionTimeout>60000</connectionTimeout>
<readTimeout>60000</readTimeout>
</all>
</httpConfiguration>
</configuration>
</server>
</servers>
<mirrors>
<mirror>
<id>artifactory-central-repos</id>
<mirrorOf>central</mirrorOf>
<name>Artifactory di Produzione</name>
<url>https://arti0-artifactory.sede.corp.sanpaoloimi.com/artifactory/remote-repos/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>artifactory-local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>artifactory-local-repos</id>
<!--<name>Artifactory releases</name>-->
<url>https://arti0-artifactory.sede.corp.sanpaoloimi.com/artifactory/local-repos/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>artifactory-local-plugins-repos</id>
<url>https://arti0-artifactory.sede.corp.sanpaoloimi.com/artifactory/local-repos/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifactory-local</activeProfile>
</activeProfiles>
</settings>

View File

@ -1,74 +0,0 @@
package com.armundia.bulk.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.c6stampe.url}")
private String c6stampeUrl;
@Value("${spring.datasource.c6stampe.username}")
private String c6stampeUsername;
@Value("${spring.datasource.c6stampe.password}")
private String c6stampePassword;
@Value("${spring.datasource.seireport.url}")
private String seireportUrl;
@Value("${spring.datasource.seireport.username}")
private String seireportUsername;
@Value("${spring.datasource.seireport.password}")
private String seireportPassword;
@Value("${spring.datasource.batch.url}")
private String batchUrl;
@Value("${spring.datasource.batch.username}")
private String batchUsername;
@Value("${spring.datasource.batch.password}")
private String batchPassword;
@Bean(name = "batchDataSource")
public DataSource batchDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(batchUrl);
ds.setUsername(batchUsername);
ds.setPassword(batchPassword);
return ds;
}
@Primary
@Bean(name = "c6stampeDataSource")
public DataSource c6stampeDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(c6stampeUrl);
ds.setUsername(c6stampeUsername);
ds.setPassword(c6stampePassword);
return ds;
}
@Bean(name = "seireportDataSource")
public DataSource seireportDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(seireportUrl);
ds.setUsername(seireportUsername);
ds.setPassword(seireportPassword);
return ds;
}
@Primary
@Bean(name = "c6stampeJdbcTemplate")
public JdbcTemplate c6stampeJdbcTemplate(DataSource c6stampeDataSource) {
return new JdbcTemplate(c6stampeDataSource);
}
@Bean(name = "seireportJdbcTemplate")
public JdbcTemplate seireportJdbcTemplate(DataSource seireportDataSource) {
return new JdbcTemplate(seireportDataSource);
}
}

View File

@ -1,12 +1,11 @@
package com.armundia.bulk;
package com.fideuram.bulk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BatchApplication {
public static void main(String[] args) {
SpringApplication.run(BatchApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(BatchApplication.class, args);
}
}

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.config;
package com.fideuram.bulk.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -12,15 +12,16 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.transaction.PlatformTransactionManager;
import com.armundia.bulk.mail.BatchMailMessage;
import com.fideuram.bulk.mail.BatchMailMessage;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public abstract class AbstractBatchConfig {
protected final JdbcTemplate c6stampeJdbcTemplate;
protected final JdbcTemplate seireportJdbcTemplate;
protected final JdbcTemplate outputJdbcTemplate;
protected final JdbcTemplate trimestraleJdbcTemplate;
protected final JdbcTemplate benvenutoJdbcTemplate;
protected final Logger logger;
@Autowired
@ -30,10 +31,12 @@ public abstract class AbstractBatchConfig {
protected BatchMailMessage mailMessage;
protected AbstractBatchConfig(
@Qualifier("c6stampeJdbcTemplate") JdbcTemplate c6stampeJdbcTemplate,
@Qualifier("seireportJdbcTemplate") JdbcTemplate seireportJdbcTemplate) {
this.c6stampeJdbcTemplate = c6stampeJdbcTemplate;
this.seireportJdbcTemplate = seireportJdbcTemplate;
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
this.outputJdbcTemplate = outputJdbcTemplate;
this.trimestraleJdbcTemplate = trimestraleJdbcTemplate;
this.benvenutoJdbcTemplate = benvenutoJdbcTemplate;
this.logger = LoggerFactory.getLogger(this.getClass());
}

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.config;
package com.fideuram.bulk.config;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
@ -7,57 +7,45 @@ import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.BatchStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Autowired;
@Configuration
public class BatchDispachConfig extends AbstractBatchConfig {
@Autowired
private JobLauncher jobLauncher;
@Autowired
@Qualifier("copiaTabelleJob")
private Job copiaTabelleJob;
public BatchDispachConfig(
@Qualifier("c6stampeJdbcTemplate") JdbcTemplate c6stampeJdbcTemplate,
@Qualifier("seireportJdbcTemplate") JdbcTemplate seireportJdbcTemplate) {
super(c6stampeJdbcTemplate, seireportJdbcTemplate);
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
super(outputJdbcTemplate, trimestraleJdbcTemplate, benvenutoJdbcTemplate);
}
@Bean
public Job dispachJob(JobRepository jobRepository, Step ciaoStep, Step seiReportStep, Step notifySampleEndStep) {
public Job dispachJob(JobRepository jobRepository, Step ciaoStep, Step seiReportStep, Step stepCheLanciaCopiaDati, Step notifySampleEndStep) {
logger.info("Configurazione del job dispachJob");
return new JobBuilder("dispachJob")
.repository(jobRepository)
.incrementer(new RunIdIncrementer())
.start(ciaoStep)
.next(seiReportStep)
.next(notifySampleEndStep)
.build();
}
@Bean
public Step seiReportStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
logger.info("Configurazione dello step seiReportStep");
return new StepBuilder("seiReportStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.debug("Inizio esecuzione tasklet SEIReport");
try {
logger.info("Verifica connessione al database SEIReport...");
seireportJdbcTemplate.queryForObject("SELECT 1", Integer.class);
logger.info("Connessione al database SEIReport OK");
logger.info("Esecuzione query di inserimento...");
String sql = "INSERT INTO SEIReport.dbo.EventoLog (Codice, Testo) select coalesce(max(codice)+1,1), concat('Prova del ',CONVERT(VARCHAR, GETDATE(), 101)) from SEIReport.dbo.EventoLog";
logger.info("Query da eseguire: {}", sql);
seireportJdbcTemplate.update(sql);
logger.info("Inserimento su SEIReport completato");
return RepeatStatus.FINISHED;
} catch (Exception e) {
logger.error("Errore durante l'esecuzione dello step SEIReport: {}", e.getMessage(), e);
throw e;
}
})
// .next(seiReportStep)
// .next(stepCheLanciaCopiaDati) // Temporaneamente disabilitato per test
// .next(notifySampleEndStep)
.build();
}
@ -71,18 +59,18 @@ public class BatchDispachConfig extends AbstractBatchConfig {
logger.debug("Inizio esecuzione tasklet");
try {
logger.info("Verifica connessione al database...");
c6stampeJdbcTemplate.queryForObject("SELECT 1", Integer.class);
outputJdbcTemplate.queryForObject("SELECT 1", Integer.class);
logger.info("Connessione al database OK");
logger.info("Esecuzione query di inserimento...");
String sql = "INSERT INTO C6StampeCentralizzate.dbo.LogN (Application, Logged, [Level], Message) VALUES('sampleStep',getDate(), 0, 'Avvio')";
logger.info("Query da eseguire: {}", sql);
int rowsAffected = c6stampeJdbcTemplate.update(sql);
int rowsAffected = outputJdbcTemplate.update(sql);
logger.info("Inserimento completato con successo. Righe inserite: {}", rowsAffected);
// Verifica che l'inserimento sia avvenuto
Integer count = c6stampeJdbcTemplate.queryForObject(
Integer count = outputJdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM C6StampeCentralizzate.dbo.LogN WHERE Application = 'sampleStep'",
Integer.class
);
@ -96,6 +84,78 @@ public class BatchDispachConfig extends AbstractBatchConfig {
})
.build();
}
@Bean
public Step seiReportStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
logger.info("Configurazione dello step seiReportStep");
return new StepBuilder("seiReportStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.debug("Inizio esecuzione tasklet SEIReport");
try {
logger.info("Verifica connessione al database SEIReport...");
benvenutoJdbcTemplate.queryForObject("SELECT 1", Integer.class);
logger.info("Connessione al database SEIReport OK");
logger.info("Esecuzione query di inserimento...");
String sql = "INSERT INTO SEIReport.dbo.EventoLog (Codice, Testo) select coalesce(max(codice)+1,1), concat('Prova del ',CONVERT(VARCHAR, GETDATE(), 101)) from SEIReport.dbo.EventoLog";
logger.info("Query da eseguire: {}", sql);
benvenutoJdbcTemplate.update(sql);
logger.info("Inserimento su SEIReport completato");
return RepeatStatus.FINISHED;
} catch (Exception e) {
logger.error("Errore durante l'esecuzione dello step SEIReport: {}", e.getMessage(), e);
throw e;
}
})
.build();
}
@Bean
public Step stepCheLanciaCopiaDati(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
logger.info("Configurazione dello step stepCheLanciaCopiaDati");
return new StepBuilder("stepCheLanciaCopiaDati")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Lancio del job copiaTabelleJob");
try {
// Parametri unici per il job di copia
JobParameters jobParameters = new JobParametersBuilder()
.addString("fonte", "trimestrale")
.addString("destinazione", "output")
.addLong("timestamp", System.currentTimeMillis())
.toJobParameters();
// Lancia il job di copia dati in modo sincrono ma gestendo le transazioni
JobExecution jobExecution = jobLauncher.run(copiaTabelleJob, jobParameters);
// Attendi il completamento se necessario
while (jobExecution.isRunning()) {
Thread.sleep(1000);
logger.debug("Job copiaTabelleJob ancora in esecuzione...");
}
// Verifica il risultato finale
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
logger.info("Job copiaTabelleJob completato con successo");
} else {
logger.error("Job copiaTabelleJob fallito con status: {}", jobExecution.getStatus());
throw new RuntimeException("Fallimento del job di copia tabelle: " + jobExecution.getStatus());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interruzione durante l'attesa del job di copia", e);
}
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step notifySampleEndStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return createNotificationStep(

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.config;
package com.fideuram.bulk.config;
import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;

View File

@ -0,0 +1,9 @@
package com.fideuram.bulk.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BatchRepositoryConfig {
// Usa la configurazione automatica di Spring Batch
// Le configurazioni specifiche sono gestite tramite application.properties
}

View File

@ -0,0 +1,96 @@
package com.fideuram.bulk.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.trimestrale.url}")
private String trimestraleUrl;
@Value("${spring.datasource.trimestrale.username}")
private String trimestraleUsername;
@Value("${spring.datasource.trimestrale.password}")
private String trimestralePassword;
@Value("${spring.datasource.benvenuto.url}")
private String benvenutoUrl;
@Value("${spring.datasource.benvenuto.username}")
private String benvenutoUsername;
@Value("${spring.datasource.benvenuto.password}")
private String benvenutoPassword;
@Value("${spring.datasource.batch.url}")
private String batchUrl;
@Value("${spring.datasource.batch.username}")
private String batchUsername;
@Value("${spring.datasource.batch.password}")
private String batchPassword;
@Value("${spring.datasource.output.url}")
private String outputUrl;
@Value("${spring.datasource.output.username}")
private String outputUsername;
@Value("${spring.datasource.output.password}")
private String outputPassword;
@Primary
@Bean(name = "batchDataSource")
public DataSource batchDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(batchUrl);
ds.setUsername(batchUsername);
ds.setPassword(batchPassword);
return ds;
}
@Bean(name = "outputDataSource")
public DataSource outputDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(outputUrl);
ds.setUsername(outputUsername);
ds.setPassword(outputPassword);
return ds;
}
@Bean(name = "trimestraleDataSource")
public DataSource trimestraleDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(trimestraleUrl);
ds.setUsername(trimestraleUsername);
ds.setPassword(trimestralePassword);
return ds;
}
@Bean(name = "benvenutoDataSource")
public DataSource benvenutoDataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(benvenutoUrl);
ds.setUsername(benvenutoUsername);
ds.setPassword(benvenutoPassword);
return ds;
}
@Primary
@Bean(name = "outputJdbcTemplate")
public JdbcTemplate outputJdbcTemplate(DataSource outputDataSource) {
return new JdbcTemplate(outputDataSource);
}
@Primary
@Bean(name = "trimestraleJdbcTemplate")
public JdbcTemplate trimestraleJdbcTemplate(DataSource trimestraleDataSource) {
return new JdbcTemplate(trimestraleDataSource);
}
@Bean(name = "benvenutoJdbcTemplate")
public JdbcTemplate benvenutoJdbcTemplate(DataSource benvenutoDataSource) {
return new JdbcTemplate(benvenutoDataSource);
}
}

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.config;
package com.fideuram.bulk.config;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
@ -17,9 +17,10 @@ import org.springframework.transaction.PlatformTransactionManager;
public class RicodificaMassivaJobConfig extends AbstractBatchConfig {
public RicodificaMassivaJobConfig(
@Qualifier("c6stampeJdbcTemplate") JdbcTemplate c6stampeJdbcTemplate,
@Qualifier("seireportJdbcTemplate") JdbcTemplate seireportJdbcTemplate) {
super(c6stampeJdbcTemplate, seireportJdbcTemplate);
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
super(outputJdbcTemplate, trimestraleJdbcTemplate, benvenutoJdbcTemplate);
}
@Bean
@ -39,7 +40,7 @@ public class RicodificaMassivaJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione srv_change_codfiscaleMassiva_CU su SEIReport");
seireportJdbcTemplate.execute("exec srv_change_codfiscaleMassiva_CU");
benvenutoJdbcTemplate.execute("exec srv_change_codfiscaleMassiva_CU");
logger.info("Completata esecuzione srv_change_codfiscaleMassiva_CU su SEIReport");
return RepeatStatus.FINISHED;
})
@ -53,7 +54,7 @@ public class RicodificaMassivaJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione srv_change_codfiscaleMassiva_CU su C6StampeCentralizzate");
c6stampeJdbcTemplate.execute("exec srv_change_codfiscaleMassiva_CU");
outputJdbcTemplate.execute("exec srv_change_codfiscaleMassiva_CU");
logger.info("Completata esecuzione srv_change_codfiscaleMassiva_CU su C6StampeCentralizzate");
return RepeatStatus.FINISHED;
})

View File

@ -0,0 +1,141 @@
package com.fideuram.bulk.controller;
import org.springframework.batch.core.*;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.*;
@RestController
@RequestMapping("/actuator")
public class BatchController {
@Autowired
private JobExplorer jobExplorer;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/batch/jobs")
public Map<String, Object> getBatchJobs() {
Map<String, Object> response = new HashMap<>();
List<Map<String, Object>> jobs = new ArrayList<>();
try {
// Ottieni tutti i nomi dei job
List<String> jobNames = jobExplorer.getJobNames();
for (String jobName : jobNames) {
// Ottieni le istanze del job
List<JobInstance> jobInstances = jobExplorer.getJobInstances(jobName, 0, 10);
for (JobInstance jobInstance : jobInstances) {
// Ottieni le esecuzioni per ogni istanza
List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(jobInstance);
for (JobExecution jobExecution : jobExecutions) {
Map<String, Object> jobInfo = new HashMap<>();
jobInfo.put("name", jobName);
jobInfo.put("status", jobExecution.getStatus().toString());
jobInfo.put("startTime", jobExecution.getStartTime() != null ?
jobExecution.getStartTime().toString() : "N/A");
jobInfo.put("endTime", jobExecution.getEndTime() != null ?
jobExecution.getEndTime().toString() : "N/A");
jobInfo.put("exitCode", jobExecution.getExitStatus().getExitCode());
jobInfo.put("executionId", jobExecution.getId());
jobs.add(jobInfo);
}
}
}
response.put("jobs", jobs);
response.put("status", "success");
} catch (Exception e) {
response.put("status", "error");
response.put("message", e.getMessage());
response.put("jobs", new ArrayList<>());
}
return response;
}
@GetMapping("/batch/available-jobs")
public Map<String, Object> getAvailableJobs() {
Map<String, Object> response = new HashMap<>();
List<String> availableJobs = new ArrayList<>();
try {
// Ottieni tutti i bean Job dal context Spring
Map<String, Job> jobBeans = applicationContext.getBeansOfType(Job.class);
availableJobs.addAll(jobBeans.keySet());
response.put("availableJobs", availableJobs);
response.put("status", "success");
} catch (Exception e) {
response.put("status", "error");
response.put("message", e.getMessage());
response.put("availableJobs", new ArrayList<>());
}
return response;
}
@PostMapping("/batch/launch/{jobName}")
public ResponseEntity<Map<String, Object>> launchJob(@PathVariable String jobName) {
Map<String, Object> response = new HashMap<>();
try {
// Ottieni il job dal context Spring
Job job = applicationContext.getBean(jobName, Job.class);
// Crea parametri unici per evitare conflitti
JobParameters jobParameters = new JobParametersBuilder()
.addLong("timestamp", System.currentTimeMillis())
.addString("launchedBy", "monitor")
.toJobParameters();
// Avvia il job
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
response.put("status", "success");
response.put("message", "Job '" + jobName + "' avviato con successo");
response.put("executionId", jobExecution.getId());
response.put("jobStatus", jobExecution.getStatus().toString());
return ResponseEntity.ok(response);
} catch (JobExecutionAlreadyRunningException e) {
response.put("status", "error");
response.put("message", "Il job '" + jobName + "' è già in esecuzione");
return ResponseEntity.badRequest().body(response);
} catch (JobRestartException e) {
response.put("status", "error");
response.put("message", "Errore nel riavvio del job '" + jobName + "': " + e.getMessage());
return ResponseEntity.badRequest().body(response);
} catch (JobInstanceAlreadyCompleteException e) {
response.put("status", "error");
response.put("message", "Un'istanza del job '" + jobName + "' è già completata con gli stessi parametri");
return ResponseEntity.badRequest().body(response);
} catch (Exception e) {
response.put("status", "error");
response.put("message", "Errore durante l'avvio del job '" + jobName + "': " + e.getMessage());
return ResponseEntity.internalServerError().body(response);
}
}
}

View File

@ -0,0 +1,18 @@
package com.fideuram.bulk.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class WebMonitorController {
@GetMapping("/")
public String index() {
return "monitor";
}
@GetMapping("/monitor")
public String monitor() {
return "monitor";
}
}

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.mail;
package com.fideuram.bulk.mail;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;

View File

@ -1,9 +1,9 @@
package com.armundia.bulk.monitor;
package com.fideuram.bulk.monitor;
import com.armundia.bulk.monitor.ui.JobMonitorFrame;
import com.fideuram.bulk.monitor.ui.JobMonitorFrame;
public class JobMonitorApplication {
public static void main(String[] args) {
JobMonitorFrame.main(args);
}
}
}

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.monitor.model;
package com.fideuram.bulk.monitor.model;
public class JobStatus {
private String jobName;

View File

@ -1,6 +1,6 @@
package com.armundia.bulk.monitor.service;
package com.fideuram.bulk.monitor.service;
import com.armundia.bulk.monitor.model.JobStatus;
import com.fideuram.bulk.monitor.model.JobStatus;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.client.ResourceAccessException;
@ -13,7 +13,7 @@ import java.util.logging.Logger;
import java.util.logging.Level;
public class JobMonitorService {
private static final String BASE_URL = "http://localhost:8081/actuator";
private static final String BASE_URL = "http://localhost:8080/actuator";
private static final Logger LOGGER = Logger.getLogger(JobMonitorService.class.getName());
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
@ -53,7 +53,7 @@ public class JobMonitorService {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(null,
"Impossibile connettersi al server Spring Batch.\n" +
"Assicurati che l'applicazione sia in esecuzione su localhost:8081",
"Assicurati che l'applicazione sia in esecuzione su localhost:8080",
"Errore di Connessione",
JOptionPane.ERROR_MESSAGE);
});

View File

@ -1,7 +1,7 @@
package com.armundia.bulk.monitor.ui;
package com.fideuram.bulk.monitor.ui;
import com.armundia.bulk.monitor.model.JobStatus;
import com.armundia.bulk.monitor.service.JobMonitorService;
import com.fideuram.bulk.monitor.model.JobStatus;
import com.fideuram.bulk.monitor.service.JobMonitorService;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
@ -9,6 +9,7 @@ import java.awt.*;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class JobMonitorFrame extends JFrame {
@ -17,6 +18,9 @@ public class JobMonitorFrame extends JFrame {
private final DefaultTableModel tableModel;
private final ScheduledExecutorService scheduler;
private final JLabel statusLabel;
private ScheduledFuture<?> autoRefreshTask;
private boolean autoRefreshEnabled = true;
private JButton autoRefreshButton;
public JobMonitorFrame() {
super("Spring Batch Job Monitor");
@ -36,6 +40,10 @@ public class JobMonitorFrame extends JFrame {
// Add refresh button
JButton refreshButton = new JButton("Aggiorna");
refreshButton.addActionListener(e -> refreshJobData());
// Add auto-refresh toggle button
autoRefreshButton = new JButton("Auto-refresh: ON");
autoRefreshButton.addActionListener(e -> toggleAutoRefresh());
// Status label
statusLabel = new JLabel("In attesa...");
@ -45,6 +53,7 @@ public class JobMonitorFrame extends JFrame {
JPanel bottomPanel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttonPanel.add(refreshButton);
buttonPanel.add(autoRefreshButton);
bottomPanel.add(buttonPanel, BorderLayout.WEST);
bottomPanel.add(statusLabel, BorderLayout.CENTER);
@ -54,7 +63,7 @@ public class JobMonitorFrame extends JFrame {
// Setup auto-refresh
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this::refreshJobData, 0, 5, TimeUnit.SECONDS);
startAutoRefresh();
}
private void refreshJobData() {
@ -79,6 +88,34 @@ public class JobMonitorFrame extends JFrame {
}
});
}
private void startAutoRefresh() {
if (autoRefreshTask != null) {
autoRefreshTask.cancel(false);
}
autoRefreshTask = scheduler.scheduleAtFixedRate(this::refreshJobData, 0, 5, TimeUnit.SECONDS);
}
private void stopAutoRefresh() {
if (autoRefreshTask != null) {
autoRefreshTask.cancel(false);
autoRefreshTask = null;
}
}
private void toggleAutoRefresh() {
autoRefreshEnabled = !autoRefreshEnabled;
if (autoRefreshEnabled) {
startAutoRefresh();
autoRefreshButton.setText("Auto-refresh: ON");
statusLabel.setText("Auto-refresh attivato");
} else {
stopAutoRefresh();
autoRefreshButton.setText("Auto-refresh: OFF");
statusLabel.setText("Auto-refresh disattivato - Usa 'Aggiorna' per aggiornare manualmente");
}
}
@Override
public void dispose() {

View File

@ -0,0 +1,122 @@
package com.fideuram.bulk.step;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import com.fideuram.bulk.config.AbstractBatchConfig;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Configuration
public class S0000CopiaDati extends AbstractBatchConfig {
public S0000CopiaDati(
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
super(outputJdbcTemplate, trimestraleJdbcTemplate, benvenutoJdbcTemplate);
}
@Bean
public Job copiaTabelleJob(JobRepository jobRepository, PlatformTransactionManager transactionManager,
Step copiaTabellaVCONTRATTI, Step copiaTabellaCONTRATTOSEI_METADATI) {
return new JobBuilder("copiaTabelleJob")
.repository(jobRepository)
.incrementer(new RunIdIncrementer())
.start(copiaTabellaVCONTRATTI)
.next(copiaTabellaCONTRATTOSEI_METADATI)
.build();
}
@Bean
public Step copiaTabellaVCONTRATTI(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("copiaTabellaVCONTRATTI")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
// Copia della tabella c6mart.VCONTRATTI da trimestraleJdbcTemplate a outputJdbcTemplate
logger.info("Inizio copia tabella c6mart.VCONTRATTI");
copiaTabella("C6mart.VCONTRATTI", trimestraleJdbcTemplate, outputJdbcTemplate);
logger.info("Completata copia tabella C6mart.VCONTRATTI");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step copiaTabellaCONTRATTOSEI_METADATI(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("copiaTabellaCONTRATTOSEI_METADATI")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
// Copia della tabella C6mart.CONTRATTOSEI_METADATI da trimestraleJdbcTemplate a outputJdbcTemplate
logger.info("Inizio copia tabella C6mart.CONTRATTOSEI_METADATI");
copiaTabella("C6mart.CONTRATTOSEI_METADATI", trimestraleJdbcTemplate, outputJdbcTemplate);
logger.info("Completata copia tabella C6mart.CONTRATTOSEI_METADATI");
return RepeatStatus.FINISHED;
})
.build();
}
/**
* Metodo di utilità per copiare una tabella da un database sorgente a uno di destinazione
* @param nomeTabella Nome della tabella da copiare
* @param sourceJdbcTemplate Template JDBC sorgente
* @param targetJdbcTemplate Template JDBC destinazione
*/
private void copiaTabella(String nomeTabella, JdbcTemplate sourceJdbcTemplate, JdbcTemplate targetJdbcTemplate) {
try {
logger.info("Inizio copia tabella: {}", nomeTabella);
// Svuota la tabella di destinazione se esiste
try {
targetJdbcTemplate.execute("TRUNCATE TABLE " + nomeTabella);
logger.info("Tabella di destinazione {} svuotata con successo", nomeTabella);
} catch (Exception e) {
logger.info("Tabella di destinazione {} non esistente o non può essere svuotata: {}", nomeTabella, e.getMessage());
}
// Estrae i dati dalla tabella sorgente
List<Map<String, Object>> datiSorgente = sourceJdbcTemplate.queryForList("SELECT * FROM " + nomeTabella);
logger.info("Estratti {} record dalla tabella sorgente {}", datiSorgente.size(), nomeTabella);
if (!datiSorgente.isEmpty()) {
// Ottiene i nomi delle colonne dal primo record
Set<String> colonne = datiSorgente.get(0).keySet();
String colonneStr = String.join(", ", colonne);
String placeholders = colonne.stream().map(c -> "?").collect(java.util.stream.Collectors.joining(", "));
String insertSql = "INSERT INTO " + nomeTabella + " (" + colonneStr + ") VALUES (" + placeholders + ")";
logger.info("SQL di inserimento: {}", insertSql);
// Inserisce i dati nella tabella di destinazione
for (Map<String, Object> record : datiSorgente) {
Object[] valori = colonne.stream().map(record::get).toArray();
targetJdbcTemplate.update(insertSql, valori);
}
logger.info("Inseriti {} record nella tabella di destinazione {}", datiSorgente.size(), nomeTabella);
} else {
logger.info("Nessun record da copiare dalla tabella {}", nomeTabella);
}
logger.info("Copia tabella {} completata con successo", nomeTabella);
} catch (Exception e) {
logger.error("Errore durante la copia della tabella {}: {}", nomeTabella, e.getMessage(), e);
throw new RuntimeException("Errore durante la copia della tabella " + nomeTabella, e);
}
}
}

View File

@ -0,0 +1,136 @@
package com.fideuram.bulk.step;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import com.fideuram.bulk.config.AbstractBatchConfig;
@Configuration
public class S0200W6catr extends AbstractBatchConfig {
public S0200W6catr(
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
super(outputJdbcTemplate, trimestraleJdbcTemplate, benvenutoJdbcTemplate);
}
@Bean
public Job w6catrJob(JobRepository jobRepository, PlatformTransactionManager transactionManager,
Step apriLogW6catrStep, Step storicizzazioneW6catrStep, Step deleteW6catrStep,
Step replicaW6catrStep, Step chiudiLogW6catrStep) {
return new JobBuilder("w6catrJob")
.repository(jobRepository)
.incrementer(new RunIdIncrementer())
.start(apriLogW6catrStep)
.next(storicizzazioneW6catrStep)
.next(deleteW6catrStep)
.next(replicaW6catrStep)
.next(chiudiLogW6catrStep)
.build();
}
@Bean
public Step apriLogW6catrStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("apriLogW6catrStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Apertura log per Replica_W6Catrf");
outputJdbcTemplate.execute("EXEC [ConsulenzaUnicaFL].[dbo].[Log_InserisciLog] 'Replica_W6Catrf'");
logger.info("Log aperto per Replica_W6Catrf");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step storicizzazioneW6catrStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("storicizzazioneW6catrStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Inizio storicizzazione tabella w6catrf");
// Drop della tabella di storicizzazione se esiste
try {
outputJdbcTemplate.execute("DROP TABLE ConsulenzaUnica..w6catrf_st");
logger.info("Tabella w6catrf_st eliminata");
} catch (Exception e) {
logger.info("Tabella w6catrf_st non esistente, procedo con la creazione");
}
// Creazione della tabella di storicizzazione copiando i dati correnti
outputJdbcTemplate.execute(
"SELECT * INTO ConsulenzaUnica..w6catrf_st FROM ConsulenzaUnica..w6catrf"
);
logger.info("Storicizzazione w6catrf completata con successo");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step deleteW6catrStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("deleteW6catrStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Eliminazione dati dalla tabella PostgreSQL FSEI0_PDC.w6catrf");
// Eliminazione dei dati dalla tabella PostgreSQL prima della replica
benvenutoJdbcTemplate.execute("DELETE FROM FSEI0_PDC.w6catrf");
logger.info("Dati eliminati dalla tabella FSEI0_PDC.w6catrf");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step replicaW6catrStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("replicaW6catrStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Inizio replica dati W6CATRF");
// Esecuzione della replica dei dati da SQL Server a PostgreSQL
// Questo step dovrebbe implementare la logica di estrazione e caricamento
// dei dati nella tabella fsei0_pdc.w6catrf
logger.info("Esecuzione replica W6CATRF da ConsulenzaUnica a PostgreSQL");
// TODO: Implementare la logica di replica specifica
// Per ora, simuliamo l'esecuzione con un log
logger.info("Replica W6CATRF completata con successo");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step chiudiLogW6catrStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("chiudiLogW6catrStep")
.repository(jobRepository)
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Chiusura log per Replica_W6Catrf");
outputJdbcTemplate.execute("EXEC [ConsulenzaUnicaFL].[dbo].[Log_ChiudiLog] 'Replica_W6Catrf'");
logger.info("Log chiuso per Replica_W6Catrf");
return RepeatStatus.FINISHED;
})
.build();
}
}

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.config;
package com.fideuram.bulk.step;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
@ -12,14 +12,16 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import com.fideuram.bulk.config.AbstractBatchConfig;
@Configuration
public class PreTrimestraleJobConfig extends AbstractBatchConfig {
public class S0301StagingPretrimestrale extends AbstractBatchConfig {
public PreTrimestraleJobConfig(
@Qualifier("c6stampeJdbcTemplate") JdbcTemplate c6stampeJdbcTemplate,
@Qualifier("seireportJdbcTemplate") JdbcTemplate seireportJdbcTemplate) {
super(c6stampeJdbcTemplate, seireportJdbcTemplate);
public S0301StagingPretrimestrale(
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
super(outputJdbcTemplate, trimestraleJdbcTemplate, benvenutoJdbcTemplate);
}
@Bean
@ -54,7 +56,7 @@ public class PreTrimestraleJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione truncate table C6MartPeriodico.tab_semaforo");
c6stampeJdbcTemplate.execute("truncate table C6MartPeriodico.tab_semaforo");
outputJdbcTemplate.execute("truncate table C6MartPeriodico.tab_semaforo");
logger.info("Completata esecuzione truncate");
return RepeatStatus.FINISHED;
})
@ -68,7 +70,7 @@ public class PreTrimestraleJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione Avvio Trimestrale");
c6stampeJdbcTemplate.execute(
outputJdbcTemplate.execute(
"exec C6MartPeriodico.SP_Valorizza_Stati_semaforo_TRIM trim_start,SEI; " +
"delete from C6MartPeriodico.tab_semaforo where id_milestone>8");
logger.info("Completata esecuzione Avvio Trimestrale");
@ -84,7 +86,7 @@ public class PreTrimestraleJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione C6StagingPeriodico.RP_ST_CONTRATTIPRETRIMESTRALE");
c6stampeJdbcTemplate.execute("EXEC [C6StagingPeriodico].[RP_ST_CONTRATTIPRETRIMESTRALE]");
outputJdbcTemplate.execute("EXEC [C6StagingPeriodico].[RP_ST_CONTRATTIPRETRIMESTRALE]");
logger.info("Completata esecuzione C6StagingPeriodico.RP_ST_CONTRATTIPRETRIMESTRALE");
return RepeatStatus.FINISHED;
})

View File

@ -1,4 +1,4 @@
package com.armundia.bulk.config;
package com.fideuram.bulk.step;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
@ -13,13 +13,16 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
public class AppoContrattiJobConfig extends AbstractBatchConfig {
import com.fideuram.bulk.config.AbstractBatchConfig;
public AppoContrattiJobConfig(
@Qualifier("c6stampeJdbcTemplate") JdbcTemplate c6stampeJdbcTemplate,
@Qualifier("seireportJdbcTemplate") JdbcTemplate seireportJdbcTemplate) {
super(c6stampeJdbcTemplate, seireportJdbcTemplate);
@Configuration
public class S0303StagingAppoContratti extends AbstractBatchConfig {
public S0303StagingAppoContratti(
@Qualifier("outputJdbcTemplate") JdbcTemplate outputJdbcTemplate,
@Qualifier("trimestraleJdbcTemplate") JdbcTemplate trimestraleJdbcTemplate,
@Qualifier("benvenutoJdbcTemplate") JdbcTemplate benvenutoJdbcTemplate) {
super(outputJdbcTemplate, trimestraleJdbcTemplate, benvenutoJdbcTemplate);
}
@Bean
@ -39,7 +42,7 @@ public class AppoContrattiJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
c6stampeJdbcTemplate.execute("EXEC C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
outputJdbcTemplate.execute("EXEC C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
logger.info("Completata esecuzione C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
return RepeatStatus.FINISHED;
})
@ -53,7 +56,7 @@ public class AppoContrattiJobConfig extends AbstractBatchConfig {
.transactionManager(transactionManager)
.tasklet((contribution, chunkContext) -> {
logger.info("Esecuzione C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
c6stampeJdbcTemplate.execute("EXEC C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
outputJdbcTemplate.execute("EXEC C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
logger.info("Completata esecuzione C6StagingPeriodico.RP_ST_APPO_CONTRATTI");
return RepeatStatus.FINISHED;
})

View File

@ -1,22 +1,54 @@
# Configurazione Spring Batch
spring.batch.job.enabled=true
spring.batch.jdbc.initialize-schema=never
spring.batch.job.enabled=false
spring.batch.jdbc.initialize-schema=always
spring.sql.init.mode=never
spring.main.allow-bean-definition-overriding=true
# Configurazione specifica per SQL Server
spring.batch.jdbc.table-prefix=BATCH_
# Collaudo
# Configurazione Database SQL Server - C6StampeCentralizzate
spring.datasource.c6stampe.url=jdbc:sqlserver://localhost;databaseName=C6StampeCentralizzate;encrypt=false
spring.datasource.c6stampe.username=c6stampa
spring.datasource.c6stampe.password=centrsei
spring.datasource.trimestrale.url=jdbc:sqlserver://bfdskrepsei01c.sysfideuram.sysbancafideuram.it;databaseName=C6StampeCentralizzate;encrypt=false
spring.datasource.trimestrale.username=F701264
spring.datasource.trimestrale.password=contrsei
# Configurazione Database SQL Server - SEIReport
spring.datasource.seireport.url=jdbc:sqlserver://localhost;databaseName=SEIReport;encrypt=false
spring.datasource.seireport.username=c6stampa
spring.datasource.seireport.password=centrsei
spring.datasource.benvenuto.url=jdbc:sqlserver://bfdskrepsei02c.sysfideuram.sysbancafideuram.it;databaseName=SEIReport;encrypt=false
spring.datasource.benvenuto.username=seireport
spring.datasource.benvenuto.password=seireport
# Produzione
# Configurazione Database SQL Server - C6StampeCentralizzate
# spring.datasource.trimestrale.url=jdbc:sqlserver://bfdskreport01p.fideuram.bancafideuram.it;databaseName=C6StampeCentralizzate;encrypt=false
# spring.datasource.trimestrale.username=F701264
# spring.datasource.trimestrale.password=contrsei
# Configurazione Database SQL Server - SEIReport
# spring.datasource.benvenuto.url=jdbc:sqlserver://bfdskreport02p.fideuram.bancafideuram.it;databaseName=SEIReport;encrypt=false
# spring.datasource.benvenuto.username=seireport
# spring.datasource.benvenuto.password=seireport
# Localhost
# Configurazione Database SQL Server - C6StampeCentralizzate
# spring.datasource.trimestrale.url=jdbc:sqlserver://localhost;databaseName=C6StampeCentralizzate;encrypt=false
# spring.datasource.trimestrale.username=F701264
# spring.datasource.trimestrale.password=contrsei
# Configurazione Database SQL Server - SEIReport
# spring.datasource.benvenuto.url=jdbc:sqlserver://localhost;databaseName=SEIReport;encrypt=false
# spring.datasource.benvenuto.username=seireport
# spring.datasource.benvenuto.password=seireport
# Configurazione Database SQL Server - Spring Batch
spring.datasource.batch.url=jdbc:sqlserver://localhost;databaseName=C6StampeCentralizzate;encrypt=false
spring.datasource.batch.username=c6stampa
spring.datasource.batch.password=centrsei
spring.datasource.batch.username=F701264
spring.datasource.batch.password=contrsei
# Configurazione Database SQL Server - output
spring.datasource.output.url=jdbc:sqlserver://localhost;databaseName=C6StampeCentralizzate;encrypt=false
spring.datasource.output.username=F701264
spring.datasource.output.password=contrsei
# Debug e logging
logging.level.root=INFO
@ -29,10 +61,10 @@ logging.level.org.springframework.transaction=INFO
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect
spring.jpa.hibernate.ddl-auto=none
# Forza esecuzione del job all'avvio
spring.batch.job.enabled=true
# Forza esecuzione del job all'avvio (DISABILITATO)
# spring.batch.job.enabled=true
# Specifica quale job eseguire di default
spring.batch.job.name=dispachJob
# spring.batch.job.name=dispachJob
# Email Configuration
spring.mail.host=smtp.gmail.com
@ -44,3 +76,8 @@ spring.mail.properties.mail.smtp.starttls.enable=true
# Batch Mail Configuration
batch.mail.to=g.savo@armundia.com
# Actuator Configuration per Monitor GUI
management.endpoints.web.exposure.include=health,info,batch
management.endpoint.batch.enabled=true
management.endpoints.web.base-path=/actuator

View File

@ -1,141 +1,130 @@
-- Tabelle Spring Batch per SQL Server
USE [C6StampeCentralizzate];
GO
-- Usa il database specificato nella connection string
-- Sequence per BATCH_JOB_SEQ
IF NOT EXISTS (SELECT * FROM sys.sequences WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_SEQ]'))
BEGIN
CREATE SEQUENCE [dbo].[BATCH_JOB_SEQ]
AS [bigint]
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1000;
END;
-- Elimina le tabelle esistenti per forzare la ricreazione con la struttura corretta
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION_CONTEXT]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_STEP_EXECUTION_CONTEXT];
-- Sequence per BATCH_JOB_EXECUTION_SEQ
IF NOT EXISTS (SELECT * FROM sys.sequences WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_SEQ]'))
BEGIN
CREATE SEQUENCE [dbo].[BATCH_JOB_EXECUTION_SEQ]
AS [bigint]
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1000;
END;
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_STEP_EXECUTION];
-- Sequence per BATCH_STEP_EXECUTION_SEQ
IF NOT EXISTS (SELECT * FROM sys.sequences WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION_SEQ]'))
BEGIN
CREATE SEQUENCE [dbo].[BATCH_STEP_EXECUTION_SEQ]
AS [bigint]
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1000;
END;
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_PARAMS]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_JOB_EXECUTION_PARAMS];
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_CONTEXT]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_JOB_EXECUTION_CONTEXT];
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_JOB_EXECUTION];
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_INSTANCE]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_JOB_INSTANCE];
-- Elimina le tabelle incrementer esistenti
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION_SEQ]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_STEP_EXECUTION_SEQ];
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_SEQ]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_JOB_EXECUTION_SEQ];
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_SEQ]') AND type in (N'U'))
DROP TABLE [dbo].[BATCH_JOB_SEQ];
-- Tabella incrementer per BATCH_JOB_SEQ (solo colonna IDENTITY)
CREATE TABLE [dbo].[BATCH_JOB_SEQ] (
[ID] [bigint] IDENTITY(1,1) NOT NULL
);
-- Tabella incrementer per BATCH_JOB_EXECUTION_SEQ (solo colonna IDENTITY)
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION_SEQ] (
[ID] [bigint] IDENTITY(1,1) NOT NULL
);
-- Tabella incrementer per BATCH_STEP_EXECUTION_SEQ (solo colonna IDENTITY)
CREATE TABLE [dbo].[BATCH_STEP_EXECUTION_SEQ] (
[ID] [bigint] IDENTITY(1,1) NOT NULL
);
-- Tabella BATCH_JOB_INSTANCE
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_INSTANCE]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[BATCH_JOB_INSTANCE] (
[JOB_INSTANCE_ID] [bigint] NOT NULL,
[VERSION] [bigint] NULL,
[JOB_NAME] [varchar](100) NOT NULL,
[JOB_KEY] [varchar](32) NOT NULL,
CONSTRAINT [PK_BATCH_JOB_INSTANCE] PRIMARY KEY CLUSTERED ([JOB_INSTANCE_ID] ASC),
CONSTRAINT [JOB_INST_UN] UNIQUE NONCLUSTERED ([JOB_NAME] ASC, [JOB_KEY] ASC)
);
END;
CREATE TABLE [dbo].[BATCH_JOB_INSTANCE] (
[JOB_INSTANCE_ID] [bigint] NOT NULL,
[VERSION] [bigint] NULL,
[JOB_NAME] [varchar](100) NOT NULL,
[JOB_KEY] [varchar](32) NOT NULL,
CONSTRAINT [PK_BATCH_JOB_INSTANCE] PRIMARY KEY CLUSTERED ([JOB_INSTANCE_ID] ASC),
CONSTRAINT [JOB_INST_UN] UNIQUE NONCLUSTERED ([JOB_NAME] ASC, [JOB_KEY] ASC)
);
-- Tabella BATCH_JOB_EXECUTION
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION] (
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[VERSION] [bigint] NULL,
[JOB_INSTANCE_ID] [bigint] NOT NULL,
[CREATE_TIME] [datetime] NOT NULL,
[START_TIME] [datetime] NULL,
[END_TIME] [datetime] NULL,
[STATUS] [varchar](10) NULL,
[EXIT_CODE] [varchar](2500) NULL,
[EXIT_MESSAGE] [varchar](2500) NULL,
[LAST_UPDATED] [datetime] NULL,
[JOB_CONFIGURATION_LOCATION] [varchar](2500) NULL,
CONSTRAINT [PK_BATCH_JOB_EXECUTION] PRIMARY KEY CLUSTERED ([JOB_EXECUTION_ID] ASC),
CONSTRAINT [JOB_INST_EXEC_FK] FOREIGN KEY ([JOB_INSTANCE_ID])
REFERENCES [dbo].[BATCH_JOB_INSTANCE] ([JOB_INSTANCE_ID])
);
END;
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION] (
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[VERSION] [bigint] NULL,
[JOB_INSTANCE_ID] [bigint] NOT NULL,
[CREATE_TIME] [datetime] NOT NULL,
[START_TIME] [datetime] NULL,
[END_TIME] [datetime] NULL,
[STATUS] [varchar](10) NULL,
[EXIT_CODE] [varchar](2500) NULL,
[EXIT_MESSAGE] [varchar](2500) NULL,
[LAST_UPDATED] [datetime] NULL,
[JOB_CONFIGURATION_LOCATION] [varchar](2500) NULL,
CONSTRAINT [PK_BATCH_JOB_EXECUTION] PRIMARY KEY CLUSTERED ([JOB_EXECUTION_ID] ASC),
CONSTRAINT [JOB_INST_EXEC_FK] FOREIGN KEY ([JOB_INSTANCE_ID])
REFERENCES [dbo].[BATCH_JOB_INSTANCE] ([JOB_INSTANCE_ID])
);
-- Tabella BATCH_JOB_EXECUTION_PARAMS
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_PARAMS]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION_PARAMS] (
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[PARAMETER_NAME] [varchar](100) NOT NULL,
[PARAMETER_TYPE] [varchar](100) NOT NULL,
[PARAMETER_VALUE] [varchar](2500) NULL,
[IDENTIFYING] [char](1) NOT NULL,
CONSTRAINT [JOB_EXEC_PARAMS_FK] FOREIGN KEY ([JOB_EXECUTION_ID])
REFERENCES [dbo].[BATCH_JOB_EXECUTION] ([JOB_EXECUTION_ID])
);
END;
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION_PARAMS] (
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[PARAMETER_NAME] [varchar](100) NOT NULL,
[PARAMETER_TYPE] [varchar](100) NOT NULL,
[PARAMETER_VALUE] [varchar](2500) NULL,
[IDENTIFYING] [char](1) NOT NULL,
CONSTRAINT [JOB_EXEC_PARAMS_FK] FOREIGN KEY ([JOB_EXECUTION_ID])
REFERENCES [dbo].[BATCH_JOB_EXECUTION] ([JOB_EXECUTION_ID])
);
-- Tabella BATCH_STEP_EXECUTION
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[BATCH_STEP_EXECUTION] (
[STEP_EXECUTION_ID] [bigint] NOT NULL,
[VERSION] [bigint] NOT NULL,
[STEP_NAME] [varchar](100) NOT NULL,
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[START_TIME] [datetime] NOT NULL,
[END_TIME] [datetime] NULL,
[STATUS] [varchar](10) NULL,
[COMMIT_COUNT] [bigint] NULL,
[READ_COUNT] [bigint] NULL,
[FILTER_COUNT] [bigint] NULL,
[WRITE_COUNT] [bigint] NULL,
[READ_SKIP_COUNT] [bigint] NULL,
[WRITE_SKIP_COUNT] [bigint] NULL,
[PROCESS_SKIP_COUNT] [bigint] NULL,
[ROLLBACK_COUNT] [bigint] NULL,
[EXIT_CODE] [varchar](2500) NULL,
[EXIT_MESSAGE] [varchar](2500) NULL,
[LAST_UPDATED] [datetime] NULL,
CONSTRAINT [PK_BATCH_STEP_EXECUTION] PRIMARY KEY CLUSTERED ([STEP_EXECUTION_ID] ASC),
CONSTRAINT [JOB_EXEC_STEP_FK] FOREIGN KEY ([JOB_EXECUTION_ID])
REFERENCES [dbo].[BATCH_JOB_EXECUTION] ([JOB_EXECUTION_ID])
);
END;
CREATE TABLE [dbo].[BATCH_STEP_EXECUTION] (
[STEP_EXECUTION_ID] [bigint] NOT NULL,
[VERSION] [bigint] NOT NULL,
[STEP_NAME] [varchar](100) NOT NULL,
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[START_TIME] [datetime] NOT NULL,
[END_TIME] [datetime] NULL,
[STATUS] [varchar](10) NULL,
[COMMIT_COUNT] [bigint] NULL,
[READ_COUNT] [bigint] NULL,
[FILTER_COUNT] [bigint] NULL,
[WRITE_COUNT] [bigint] NULL,
[READ_SKIP_COUNT] [bigint] NULL,
[WRITE_SKIP_COUNT] [bigint] NULL,
[PROCESS_SKIP_COUNT] [bigint] NULL,
[ROLLBACK_COUNT] [bigint] NULL,
[EXIT_CODE] [varchar](2500) NULL,
[EXIT_MESSAGE] [varchar](2500) NULL,
[LAST_UPDATED] [datetime] NULL,
CONSTRAINT [PK_BATCH_STEP_EXECUTION] PRIMARY KEY CLUSTERED ([STEP_EXECUTION_ID] ASC),
CONSTRAINT [JOB_EXEC_STEP_FK] FOREIGN KEY ([JOB_EXECUTION_ID])
REFERENCES [dbo].[BATCH_JOB_EXECUTION] ([JOB_EXECUTION_ID])
);
-- Tabella BATCH_STEP_EXECUTION_CONTEXT
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION_CONTEXT]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[BATCH_STEP_EXECUTION_CONTEXT] (
[STEP_EXECUTION_ID] [bigint] NOT NULL,
[SHORT_CONTEXT] [varchar](2500) NOT NULL,
[SERIALIZED_CONTEXT] [text] NULL,
CONSTRAINT [PK_BATCH_STEP_EXECUTION_CONTEXT] PRIMARY KEY CLUSTERED ([STEP_EXECUTION_ID] ASC),
CONSTRAINT [STEP_EXEC_CTX_FK] FOREIGN KEY ([STEP_EXECUTION_ID])
REFERENCES [dbo].[BATCH_STEP_EXECUTION] ([STEP_EXECUTION_ID])
);
END;
CREATE TABLE [dbo].[BATCH_STEP_EXECUTION_CONTEXT] (
[STEP_EXECUTION_ID] [bigint] NOT NULL,
[SHORT_CONTEXT] [varchar](2500) NOT NULL,
[SERIALIZED_CONTEXT] [text] NULL,
CONSTRAINT [PK_BATCH_STEP_EXECUTION_CONTEXT] PRIMARY KEY CLUSTERED ([STEP_EXECUTION_ID] ASC),
CONSTRAINT [STEP_EXEC_CTX_FK] FOREIGN KEY ([STEP_EXECUTION_ID])
REFERENCES [dbo].[BATCH_STEP_EXECUTION] ([STEP_EXECUTION_ID])
);
-- Tabella BATCH_JOB_EXECUTION_CONTEXT
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_CONTEXT]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION_CONTEXT] (
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[SHORT_CONTEXT] [varchar](2500) NOT NULL,
[SERIALIZED_CONTEXT] [text] NULL,
CONSTRAINT [PK_BATCH_JOB_EXECUTION_CONTEXT] PRIMARY KEY CLUSTERED ([JOB_EXECUTION_ID] ASC),
CONSTRAINT [JOB_EXEC_CTX_FK] FOREIGN KEY ([JOB_EXECUTION_ID])
REFERENCES [dbo].[BATCH_JOB_EXECUTION] ([JOB_EXECUTION_ID])
);
END;
CREATE TABLE [dbo].[BATCH_JOB_EXECUTION_CONTEXT] (
[JOB_EXECUTION_ID] [bigint] NOT NULL,
[SHORT_CONTEXT] [varchar](2500) NOT NULL,
[SERIALIZED_CONTEXT] [text] NULL,
CONSTRAINT [PK_BATCH_JOB_EXECUTION_CONTEXT] PRIMARY KEY CLUSTERED ([JOB_EXECUTION_ID] ASC),
CONSTRAINT [JOB_EXEC_CTX_FK] FOREIGN KEY ([JOB_EXECUTION_ID])
REFERENCES [dbo].[BATCH_JOB_EXECUTION] ([JOB_EXECUTION_ID])
);

View File

@ -0,0 +1,361 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spring Batch Job Monitor</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
border-bottom: 3px solid #007bff;
padding-bottom: 10px;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 20px;
align-items: center;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
button.auto-refresh-off {
background-color: #dc3545;
}
button.auto-refresh-off:hover {
background-color: #c82333;
}
.status {
flex-grow: 1;
text-align: right;
color: #666;
font-style: italic;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f8f9fa;
font-weight: 600;
color: #333;
}
tr:hover {
background-color: #f8f9fa;
}
.status-completed {
color: #28a745;
font-weight: bold;
}
.status-failed {
color: #dc3545;
font-weight: bold;
}
.status-running {
color: #007bff;
font-weight: bold;
}
.status-starting {
color: #ffc107;
font-weight: bold;
}
.no-data {
text-align: center;
color: #666;
font-style: italic;
padding: 40px;
}
.error-message {
background-color: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin: 20px 0;
border: 1px solid #f5c6cb;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 Spring Batch Job Monitor</h1>
<div class="controls">
<button id="refreshBtn" onclick="refreshJobs()">🔄 Aggiorna</button>
<button id="autoRefreshBtn" onclick="toggleAutoRefresh()">⏰ Auto-refresh: ON</button>
<div class="status" id="statusLabel">In attesa...</div>
</div>
<div class="job-launcher" id="jobLauncher" style="margin-bottom: 20px; padding: 15px; background-color: #f8f9fa; border-radius: 5px;">
<h3 style="margin-top: 0; color: #333;">🚀 Avvia Job Batch</h3>
<div id="availableJobsContainer">Caricamento job disponibili...</div>
</div>
<div id="errorMessage" class="error-message" style="display: none;"></div>
<table id="jobsTable">
<thead>
<tr>
<th>Nome Job</th>
<th>Stato</th>
<th>Ora Inizio</th>
<th>Ora Fine</th>
<th>Codice Uscita</th>
<th>ID Esecuzione</th>
</tr>
</thead>
<tbody id="jobsTableBody">
<tr>
<td colspan="6" class="no-data">Caricamento dati...</td>
</tr>
</tbody>
</table>
</div>
<script>
let autoRefreshEnabled = true;
let autoRefreshInterval;
// Avvia l'auto-refresh all'avvio
startAutoRefresh();
// Carica i job disponibili
loadAvailableJobs();
function refreshJobs() {
const statusLabel = document.getElementById('statusLabel');
const errorMessage = document.getElementById('errorMessage');
const tableBody = document.getElementById('jobsTableBody');
statusLabel.textContent = 'Aggiornamento in corso...';
errorMessage.style.display = 'none';
fetch('/actuator/batch/jobs')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
})
.then(data => {
updateJobsTable(data.jobs || []);
const now = new Date().toLocaleTimeString();
statusLabel.textContent = `Ultimo aggiornamento: ${now}`;
})
.catch(error => {
console.error('Errore durante il recupero dei job:', error);
showError(`Errore durante il recupero dei dati: ${error.message}`);
statusLabel.textContent = 'Errore durante l\'aggiornamento';
});
}
function updateJobsTable(jobs) {
const tableBody = document.getElementById('jobsTableBody');
if (jobs.length === 0) {
tableBody.innerHTML = '<tr><td colspan="6" class="no-data">Nessun job trovato</td></tr>';
return;
}
tableBody.innerHTML = jobs.map(job => `
<tr>
<td>${escapeHtml(job.name || 'N/A')}</td>
<td><span class="status-${getStatusClass(job.status)}">${escapeHtml(job.status || 'N/A')}</span></td>
<td>${formatDateTime(job.startTime)}</td>
<td>${formatDateTime(job.endTime)}</td>
<td>${escapeHtml(job.exitCode || 'N/A')}</td>
<td>${job.executionId || 'N/A'}</td>
</tr>
`).join('');
}
function getStatusClass(status) {
if (!status) return '';
const statusLower = status.toLowerCase();
if (statusLower.includes('completed')) return 'completed';
if (statusLower.includes('failed')) return 'failed';
if (statusLower.includes('running')) return 'running';
if (statusLower.includes('starting')) return 'starting';
return '';
}
function formatDateTime(dateTime) {
if (!dateTime || dateTime === 'N/A') return 'N/A';
try {
return new Date(dateTime).toLocaleString('it-IT');
} catch (e) {
return dateTime;
}
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function showError(message) {
const errorMessage = document.getElementById('errorMessage');
errorMessage.textContent = message;
errorMessage.style.display = 'block';
}
function toggleAutoRefresh() {
autoRefreshEnabled = !autoRefreshEnabled;
const button = document.getElementById('autoRefreshBtn');
const statusLabel = document.getElementById('statusLabel');
if (autoRefreshEnabled) {
startAutoRefresh();
button.textContent = '⏰ Auto-refresh: ON';
button.classList.remove('auto-refresh-off');
statusLabel.textContent = 'Auto-refresh attivato';
} else {
stopAutoRefresh();
button.textContent = '⏰ Auto-refresh: OFF';
button.classList.add('auto-refresh-off');
statusLabel.textContent = 'Auto-refresh disattivato - Usa "Aggiorna" per aggiornare manualmente';
}
}
function startAutoRefresh() {
// Aggiorna immediatamente
refreshJobs();
// Poi ogni 5 secondi
if (autoRefreshInterval) {
clearInterval(autoRefreshInterval);
}
autoRefreshInterval = setInterval(refreshJobs, 5000);
}
function stopAutoRefresh() {
if (autoRefreshInterval) {
clearInterval(autoRefreshInterval);
autoRefreshInterval = null;
}
}
// Cleanup quando la pagina viene chiusa
window.addEventListener('beforeunload', function() {
stopAutoRefresh();
});
function loadAvailableJobs() {
const container = document.getElementById('availableJobsContainer');
fetch('/actuator/batch/available-jobs')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
})
.then(data => {
if (data.status === 'success' && data.availableJobs && data.availableJobs.length > 0) {
container.innerHTML = data.availableJobs.map(jobName => `
<button onclick="launchJob('${jobName}')"
style="margin: 5px; padding: 8px 15px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;"
onmouseover="this.style.backgroundColor='#218838'"
onmouseout="this.style.backgroundColor='#28a745'">
▶️ ${jobName}
</button>
`).join('');
} else {
container.innerHTML = '<span style="color: #666; font-style: italic;">Nessun job disponibile</span>';
}
})
.catch(error => {
console.error('Errore durante il caricamento dei job:', error);
container.innerHTML = '<span style="color: #dc3545;">Errore nel caricamento dei job disponibili</span>';
});
}
function launchJob(jobName) {
const statusLabel = document.getElementById('statusLabel');
const errorMessage = document.getElementById('errorMessage');
if (!confirm(`Sei sicuro di voler avviare il job '${jobName}'?`)) {
return;
}
statusLabel.textContent = `Avvio del job '${jobName}' in corso...`;
errorMessage.style.display = 'none';
fetch(`/actuator/batch/launch/${jobName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
statusLabel.textContent = `Job '${jobName}' avviato con successo! ID esecuzione: ${data.executionId}`;
// Aggiorna automaticamente la tabella dopo 2 secondi
setTimeout(() => {
refreshJobs();
}, 2000);
} else {
showError(data.message || 'Errore sconosciuto durante l\'avvio del job');
statusLabel.textContent = `Errore nell'avvio del job '${jobName}'`;
}
})
.catch(error => {
console.error('Errore durante l\'avvio del job:', error);
showError(`Errore durante l'avvio del job '${jobName}': ${error.message}`);
statusLabel.textContent = `Errore nell'avvio del job '${jobName}'`;
});
}
</script>
</body>
</html>