Upgrade java 21 e Spring boot 5.1.13

This commit is contained in:
Gaetano Savo 2025-09-09 10:55:07 +02:00
parent 5a924fc3ce
commit f9696c0384
7 changed files with 243 additions and 26 deletions

View File

@ -204,7 +204,7 @@ L'applicazione espone i seguenti endpoint REST:
### Monitoraggio Job
```http
GET /actuator/batch/jobs
GET /api/batch/jobs
```
Restituisce la lista delle esecuzioni job con dettagli completi.
@ -212,7 +212,7 @@ Restituisce la lista delle esecuzioni job con dettagli completi.
### Job Disponibili
```http
GET /actuator/batch/available-jobs
GET /api/batch/available-jobs
```
Restituisce la lista dei job batch disponibili per l'avvio.
@ -220,7 +220,7 @@ Restituisce la lista dei job batch disponibili per l'avvio.
### Avvio Job
```http
POST /actuator/batch/launch/{jobName}
POST /api/batch/launch/{jobName}
```
Avvia un job batch specifico. Parametri automatici:
@ -259,7 +259,7 @@ Gli endpoint di monitoraggio sono abilitati tramite:
# Endpoint Actuator per il monitoraggio
management.endpoints.web.exposure.include=health,info,batch
management.endpoint.batch.enabled=true
management.endpoints.web.base-path=/actuator
management.endpoints.web.base-path=/api
```
### Database Job Repository

View File

@ -2,7 +2,7 @@
setlocal
rem Imposta JAVA_HOME
set JAVA_HOME=C:\Dev2012\BUILDERS\java\jdk-17.0.9
set JAVA_HOME=C:\Dev2012\BUILDERS\java\jdk-21.0.6
rem Aggiungi java al PATH
set PATH=%JAVA_HOME%\bin;%PATH%

View File

@ -13,12 +13,12 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<version>3.3.13</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
<java.version>21</java.version>
</properties>
<dependencies>

View File

@ -15,11 +15,16 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.info.BuildProperties;
import org.springframework.core.SpringVersion;
import java.util.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@RestController
@RequestMapping("/actuator")
@RequestMapping("/api")
public class BatchController {
@Autowired
@ -38,6 +43,9 @@ public class BatchController {
@Autowired
private ApplicationContext applicationContext;
@Autowired(required = false)
private BuildProperties buildProperties;
@Autowired
private com.armundia.bulk.service.ConnectionService connectionService;
@ -86,9 +94,7 @@ public class BatchController {
return response;
}
@PostMapping("/batch/launch/{jobName}")
public ResponseEntity<Map<String, Object>> launchJob(@PathVariable String jobName) {
Map<String, Object> response = new HashMap<>();
@ -637,4 +643,66 @@ public class BatchController {
return ResponseEntity.internalServerError().body(response);
}
}
/**
* Endpoint per ottenere informazioni di versione e sistema
*/
@GetMapping("/info")
public ResponseEntity<Map<String, Object>> getInfo() {
Map<String, Object> response = new HashMap<>();
try {
// Informazioni di build
Map<String, Object> build = new HashMap<>();
if (buildProperties != null) {
build.put("version", buildProperties.getVersion());
build.put("time", buildProperties.getTime());
build.put("artifact", buildProperties.getArtifact());
build.put("name", buildProperties.getName());
build.put("group", buildProperties.getGroup());
} else {
build.put("version", "1.0.0");
build.put("time", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
build.put("artifact", "BatchDataProcessing");
build.put("name", "Spring Batch Data Processing");
build.put("group", "com.fideuram.bulk");
}
response.put("build", build);
// Informazioni Java
Map<String, Object> java = new HashMap<>();
java.put("version", System.getProperty("java.version"));
java.put("vendor", System.getProperty("java.vendor"));
java.put("runtime", System.getProperty("java.runtime.name"));
java.put("vm", System.getProperty("java.vm.name"));
response.put("java", java);
// Informazioni Spring
Map<String, Object> spring = new HashMap<>();
spring.put("version", SpringVersion.getVersion());
response.put("spring", spring);
Map<String, Object> boot = new HashMap<>();
boot.put("version", SpringBootVersion.getVersion());
response.put("boot", boot);
Map<String, Object> batch = new HashMap<>();
batch.put("version", SpringBatchVersion.getVersion());
response.put("batch", batch);
// Informazioni applicazione
Map<String, Object> app = new HashMap<>();
app.put("name", "Spring Batch Job Monitor");
app.put("description", "Sistema di monitoraggio e gestione job Spring Batch");
app.put("encoding", System.getProperty("file.encoding"));
app.put("timezone", System.getProperty("user.timezone"));
response.put("app", app);
return ResponseEntity.ok(response);
} catch (Exception e) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("error", "Errore durante il recupero delle informazioni di sistema: " + e.getMessage());
return ResponseEntity.internalServerError().body(errorResponse);
}
}
}

View File

@ -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:8080/actuator";
private static final String BASE_URL = "http://localhost:8080/api";
private static final Logger LOGGER = Logger.getLogger(JobMonitorService.class.getName());
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;

View File

@ -65,4 +65,5 @@ 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
# Il base-path per gli actuator è stato spostato in Spring Boot 3
management.server.web.base-path=/api

View File

@ -284,12 +284,50 @@
border-left: 4px solid #007bff;
background-color: #f1f3f4;
}
.version-info {
margin-bottom: 20px;
padding: 15px;
background-color: #e9ecef;
border-radius: 5px;
border-left: 4px solid #007bff;
}
.version-info button {
background: none;
border: 1px solid #007bff;
color: #007bff;
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 Spring Batch Job Monitor</h1>
<!-- Sezione informazioni versione -->
<div class="version-info" id="versionInfo" style="margin-bottom: 20px; padding: 15px; background-color: #e9ecef; border-radius: 5px; border-left: 4px solid #007bff;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div>
<h3 style="margin: 0 0 10px 0; color: #333;">📋 Informazioni Sistema</h3>
<div id="versionDetails" style="display: flex; gap: 30px; flex-wrap: wrap;">
<div>📦 <strong>Applicazione:</strong> <span id="appVersion">Caricamento...</span></div>
<div><strong>Java:</strong> <span id="javaVersion">Caricamento...</span></div>
<div>🍃 <strong>Spring:</strong> <span id="springVersion">Caricamento...</span></div>
<div>🍃 <strong>Boot:</strong> <span id="bootVersion">Caricamento...</span></div>
<div>🍃 <strong>Batch:</strong> <span id="batchVersion">Caricamento...</span></div>
<div>⚙️ <strong>Build:</strong> <span id="buildTime">Caricamento...</span></div>
</div>
</div>
<button onclick="toggleVersionInfo()" id="versionToggle" style="background: none; border: 1px solid #007bff; color: #007bff; padding: 5px 10px; border-radius: 3px; cursor: pointer; font-size: 12px;">
🔽 Nascondi
</button>
</div>
</div>
<div class="controls">
<button id="refreshBtn" onclick="refreshJobs()">🔄 Aggiorna</button>
<button id="autoRefreshBtn" onclick="toggleAutoRefresh()">⏰ Auto-refresh: ON</button>
@ -396,6 +434,9 @@
// Carica i job disponibili
loadAvailableJobs();
// Carica le informazioni di versione
loadVersionInfo();
// Carica le connessioni disponibili
loadAvailableConnections();
@ -407,7 +448,7 @@
statusLabel.textContent = 'Aggiornamento in corso...';
errorMessage.style.display = 'none';
fetch('/actuator/batch/jobs')
fetch('/api/batch/jobs')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@ -551,7 +592,7 @@
function loadAvailableJobs() {
const container = document.getElementById('availableJobsContainer');
fetch('/actuator/batch/available-jobs')
fetch('/api/batch/available-jobs')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@ -589,7 +630,7 @@
statusLabel.textContent = `Avvio del job '${jobName}' in corso...`;
errorMessage.style.display = 'none';
fetch(`/actuator/batch/launch/${jobName}`, {
fetch(`/api/batch/launch/${jobName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -626,7 +667,7 @@
statusLabel.textContent = `Arresto del job con ID ${executionId} in corso...`;
errorMessage.style.display = 'none';
fetch(`/actuator/batch/stop/${executionId}`, {
fetch(`/api/batch/stop/${executionId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -680,7 +721,7 @@
// Ferma l'auto-refresh
stopAutoRefresh();
fetch('/actuator/server/shutdown', {
fetch('/api/server/shutdown', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -746,7 +787,7 @@
statusLabel.textContent = `Cancellazione del job con ID ${executionId} in corso...`;
errorMessage.style.display = 'none';
fetch(`/actuator/batch/delete/${executionId}`, {
fetch(`/api/batch/delete/${executionId}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
@ -796,7 +837,7 @@
modalContent.innerHTML = '<p>Caricamento dettagli...</p>';
modal.style.display = 'block';
fetch(`/actuator/batch/job/${executionId}/details`)
fetch(`/api/batch/job/${executionId}/details`)
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
@ -919,11 +960,118 @@
return html;
}
// Carica le informazioni di versione
function loadVersionInfo() {
fetch('/api/info')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
})
.then(data => {
updateVersionInfo(data);
})
.catch(error => {
console.error('Errore durante il caricamento delle informazioni di versione:', error);
updateVersionInfo({
error: 'Informazioni non disponibili'
});
});
}
function updateVersionInfo(data) {
const appVersionEl = document.getElementById('appVersion');
const javaVersionEl = document.getElementById('javaVersion');
const springVersionEl = document.getElementById('springVersion');
const bootVersionEl = document.getElementById('bootVersion');
const batchVersionEl = document.getElementById('batchVersion');
const buildTimeEl = document.getElementById('buildTime');
if (data.error) {
appVersionEl.textContent = 'N/A';
javaVersionEl.textContent = 'N/A';
springVersionEl.textContent = 'N/A';
bootVersionEl.textContent = 'N/A';
batchVersionEl.textContent = 'N/A';
buildTimeEl.textContent = 'N/A';
return;
}
// Informazioni applicazione
if (data.build && data.build.version) {
appVersionEl.textContent = data.build.version;
} else if (data.app && data.app.version) {
appVersionEl.textContent = data.app.version;
} else {
appVersionEl.textContent = '1.0.0';
}
// Informazioni Java
if (data.java && data.java.version) {
javaVersionEl.textContent = data.java.version;
} else {
// Fallback usando system properties se disponibili
javaVersionEl.textContent = 'N/A';
}
// Informazioni Spring
if (data.spring && data.spring.version) {
springVersionEl.textContent = data.spring.version;
} else if (data.build && data.build.springVersion) {
springVersionEl.textContent = data.build.springVersion;
} else {
springVersionEl.textContent = 'N/A';
}
// Informazioni Boot
if (data.boot && data.boot.version) {
bootVersionEl.textContent = data.boot.version;
} else if (data.build && data.build.bootVersion) {
bootVersionEl.textContent = data.build.bootVersion;
} else {
bootVersionEl.textContent = 'N/A';
}
// Informazioni Batch
if (data.batch && data.batch.version) {
batchVersionEl.textContent = data.batch.version;
} else if (data.build && data.build.batchVersion) {
batchVersionEl.textContent = data.build.batchVersion;
} else {
batchVersionEl.textContent = 'N/A';
}
// Tempo di build
if (data.build && data.build.time) {
const buildDate = new Date(data.build.time);
buildTimeEl.textContent = buildDate.toLocaleString('it-IT');
} else if (data.build && data.build.timestamp) {
const buildDate = new Date(data.build.timestamp);
buildTimeEl.textContent = buildDate.toLocaleString('it-IT');
} else {
buildTimeEl.textContent = 'N/A';
}
}
function toggleVersionInfo() {
const versionDetails = document.getElementById('versionDetails');
const toggleButton = document.getElementById('versionToggle');
if (versionDetails.style.display === 'none') {
versionDetails.style.display = 'flex';
toggleButton.textContent = '🔽 Nascondi';
} else {
versionDetails.style.display = 'none';
toggleButton.textContent = '🔼 Mostra';
}
}
// Carica i job disponibili per il lancio
function loadAvailableJobs() {
const jobSelect = document.getElementById('jobSelect');
fetch('/actuator/batch/available-jobs')
fetch('/api/batch/available-jobs')
.then(response => response.json())
.then(data => {
if (data.status === 'success' && data.jobs) {
@ -1010,7 +1158,7 @@
parameters: parameters
};
fetch('/actuator/batch/launch', {
fetch('/api/batch/launch', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -1075,7 +1223,7 @@
// Carica le connessioni disponibili
function loadAvailableConnections() {
// Carica connessioni di input
fetch('/actuator/batch/connections/input')
fetch('/api/batch/connections/input')
.then(response => response.json())
.then(data => {
const inputSelect = document.getElementById('inputConnectionSelect');
@ -1095,7 +1243,7 @@
});
// Carica connessioni di output
fetch('/actuator/batch/connections/output')
fetch('/api/batch/connections/output')
.then(response => response.json())
.then(data => {
const outputSelect = document.getElementById('outputConnectionSelect');
@ -1128,7 +1276,7 @@
showLaunchStatus(`Test connessione ${type} in corso...`, 'info');
fetch(`/actuator/batch/connections/${type}/${connectionId}/test`)
fetch(`/api/batch/connections/${type}/${connectionId}/test`)
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
@ -1178,7 +1326,7 @@
if (outputConnection) params.append('outputConnection', outputConnection);
if (parametersText) params.append('tabelle', parametersText);
const url = `/actuator/batch/launch/${selectedJobName}/with-connections${params.toString() ? '?' + params.toString() : ''}`;
const url = `/api/batch/launch/${selectedJobName}/with-connections${params.toString() ? '?' + params.toString() : ''}`;
fetch(url, {
method: 'POST',