Proudly debugging the system since 1981

Tag: java (Pagina 1 di 4)

Ho costruito un selezionatore AI per scegliere le foto migliori da PhotoPrism

Tornare da un viaggio significa quasi sempre ritrovarsi con una quantità ingestibile di foto. Nel caso di Lisbona, il problema non era tanto archiviare gli scatti, quanto riuscire a estrarne una ventina davvero condivisibile: belle, sì, ma anche varie e capaci di raccontare l’esperienza nel suo insieme. PhotoPrism offriva già un’ottima base grazie a geolocalizzazione, riconoscimento facciale, label e strumenti di organizzazione, ma non aveva ancora un modo per comporre automaticamente un album con “le foto più belle” e soprattutto con sufficiente varietà.

Da qui è nata l’idea di un selezionatore AI: una piccola applicazione Java che usa PhotoPrism per recuperare le miniature delle immagini e Ollama per far lavorare due modelli AI, uno multimodale per assegnare un punteggio estetico e produrre una descrizione oggettiva, e un secondo modello testuale per raggruppare semanticamente le foto e selezionarle con più equilibrio.

Il problema vero non era la qualità

Il primo prototipo faceva una cosa molto semplice: prendere le foto da PhotoPrism, inviarle a un modello multimodale su Ollama e chiedere un voto estetico da 1 a 100 insieme a una breve descrizione. Sulla carta sembrava sufficiente, ma in pratica produceva una selezione monotona: immagini molto belle singolarmente, ma spesso troppo simili tra loro.

Era il classico caso in cui un ranking puro ottimizza la qualità locale ma non la copertura narrativa. Se cinque foto dello stesso scorcio o dello stesso momento ricevono voti alti, un algoritmo ingenuo tende a sceglierle tutte. Per costruire un album da condividere, invece, non basta premiare le immagini migliori: bisogna anche evitare la ripetizione.

Continua a leggere

Ha ancora senso usare N8N? Un esperimento con Gemini CLI mi ha fatto cambiare idea

Per chi mi segue da un po’, sa che ho usato N8N come strumento di riferimento ogni volta che volevo integrare l’AI in un processo senza scrivere codice da zero. Workflow visivi, nodi preconfigurati, integrazioni pronte: per prototipare rapidamente è stato spesso la scelta giusta.

Ma ultimamente mi sono fatto una domanda: ha ancora senso usare N8N nel 2026, ora che gli strumenti di codifica AI sono diventati così potenti?

L’esperimento

Avevo un workflow N8N che usavo per trascrivere e sintetizzare registrazioni video — niente di esoterico, ma un processo abbastanza articolato: estrazione audio, chiamata a un modello di trascrizione, sintesi con un LLM, output strutturato. Funzionava, ma con i suoi limiti: dimensione massima dei file in ingresso, dipendenza dall’infrastruttura N8N, e quella sensazione di lavorare “dentro una scatola”.

Ho deciso di provare a riscrivere l’intero flusso come programma standalone. Gli strumenti? Gemini CLI come agente di codifica, il JSON del workflow N8N come specifica di partenza, e un prompt abbastanza dettagliato su cosa volessi ottenere.

Il risultato (che mi ha sorpreso)

In poche decine di minuti avevo un programma funzionante da riga di comando. Non un prototipo traballante: un tool che funziona meglio del workflow N8N originale, senza i limiti sulla dimensione dei file e con un controllo molto più diretto su ogni fase del processo.

Ho scelto deliberatamente la CLI perché l’uso che immagino è locale e sporadico — nessun senso di tirar su un’infrastruttura per qualcosa che uso una volta alla settimana. Ma sarebbe stato altrettanto semplice chiedere a Gemini CLI di generare un’app che espone un webservice: il delta di complessità sarebbe stato minimo.

La cosa che mi ha colpito di più non è tanto la velocità, ma quanto sia stato naturale usare il JSON di N8N come prompt implicito. Il workflow descriveva già la logica del processo in modo strutturato; Gemini ha semplicemente tradotto quella struttura in codice Java coerente e funzionante.

Cosa cambia (e cosa no)

N8N rimane uno strumento valido per certi scenari: team non tecnici, integrazioni con decine di servizi SaaS, processi che devono girare su scheduler senza infrastruttura dedicata. Non sto dicendo che sia morto.

Ma per chi sa usare il terminale e ha accesso a un buon agente di codifica AI, il vantaggio principale di N8N — abbassare la barriera tecnica — si è assottigliato enormemente. Il codice generato è leggibile, manutenibile, e non ha i vincoli architetturali di una piattaforma generalista.

Il codice è pubblico

Ho pubblicato tutto su GitHub: codice sorgente, workflow N8N originale e il prompt iniziale che ho passato a Gemini CLI.

👉 github.com/b0sh-net/VideoToMemo

Se vuoi replicare l’esperimento o adattarlo a un tuo caso d’uso, tutto quello che ti serve è lì. Sono curioso di sapere se anche voi avete fatto ragionamenti simili su N8N o su altri strumenti di automazione visuale — scrivetemi nei commenti.

Plugin gradle per la migrazione da javax a jakarta

Il plugin si trova qua : https://plugins.gradle.org/plugin/com.netflix.nebula.jakartaee-migration

La spiegazione su cosa puo fare e come si usa qua : https://github.com/nebula-plugins/gradle-jakartaee-migration-plugin

Lo scenario in cui l’ho utilizzato e’ quando si devono usare due librerie o framework, una con dipendenze “vecchie” sotto javax e una con dipendenze “nuove” sotto jakarta su un application server “nuovo”.

Il plugin aggiorna automaticamente le dipendenze vecchie, al momento della compilazione, rendendo tutto funzionante e interoperabile.

Un sentito ringraziamento a chi ha reso necessario il cambio di nome.

Proxy Dinamico per logging

Può essere necessario loggare tutto ciò che fa una determinata classe che però fa parte di una libreria e non contiene tutti i log desiderati. Supponendo che non sia necessario debuggare la classe in sè, che fa quello che deve fare nel modo giusto, ma come viene utilizzata all’interno del progetto ho trovato che realizzare un proxy dinamico sia una soluzione efficace e molto versatile. Anche perchè fatto uno, va bene per qualsiasi classe.

La classe che andiamo da realizzare fa due cose :

  • implementa InvocationHandler in modo che venga richiamata tutte le volte che viene chiamato un metodo dall’utilizzatore del target da loggare
  • ha un factory method di comodo che crea una nuova istanza di proxy dinamico attaccando se stessa come InvocationHandler

Implementare InvocationHandler significa implementare il metodo invoke:

invoke di fatto richiama il metodo del target e logga nome del metodo, parametri e risultati. Più la gestione delle eccezioni del metodo target e di tutte le altre possibili eccezioni.

Il metodo wrap permette di avere la nostra classe ben wrappata con un solo comando.

Visto che tutto questo mi ha permesso oggi di scoprire un utilizzo un pò insensato dell’accesso ai dati con conseguente lentezza ho pensato di condividerlo.

Perchè?

Contesto: classe Java, framework Wicket (ma non è significativo), IDE Intellij.

Quale sarà mai il motivo percui, un anonimo programmatore che mi ha preceduto, può aver pensato che avesse senso fare un metodo privato, che nel nome richiama l’idea di un factory method, che ritorna un campo della sua stessa classe?

E poi perchè commentarlo con // (5) ?

Continua a leggere

alibaba/Sentinel

A lightweight powerful flow control component enabling reliability and monitoring for microservices. (????????????? Java ?) – alibaba/Sentinel

As distributed systems become increasingly popular, the reliability between services is becoming more important than ever before. Sentinel takes “flow” as breakthrough point, and works on multiple fields including flow control, circuit breaking and system adaptive protection, to guarantee reliability of microservices.

Sentinel has the following features:

  • Rich applicable scenarios: Sentinel has been wildly used in Alibaba, and has covered almost all the core-scenarios in Double-11 (11.11) Shopping Festivals in the past 10 years, such as “Second Kill” which needs to limit burst flow traffic to meet the system capacity, message peak clipping and valley fills, circuit breaking for unreliable downstream services, cluster flow control, etc. […]

Sorgente: alibaba/Sentinel

Hacking YI Dome / YI Home Ip camera – 4° Puntata

Diversamente da quanto detto nella puntata precedente mi sono concentrato sul verificare l’algoritmo di codifica della password, realizzando un programmino allo scopo:

package net.b0sh.yiCameraClient.test;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public class EncryptionTest {

    public static void main(String[] params) {

        String toBoFound = "OMESSO";
        String cleanPassword = "OMESSO";
        byte[] secret = "secret".getBytes();

        if (digest(cleanPassword, "SHA-256").equals(toBoFound)) {
            System.out.println("success");
        }
        if (digest(cleanPassword, "SHA-1").equals(toBoFound)) {
            System.out.println("success");
        }
        if (digest(cleanPassword, "MD5").equals(toBoFound)) {
            System.out.println("success");
        }
        if (hmac(cleanPassword,"HmacSHA256",secret).equals(toBoFound)) {
            System.out.println("success");
        }
    }

    private static String digest(String password, String alg) {
        try {
            MessageDigest md = MessageDigest.getInstance(alg);
            byte[] bytes = md.digest(password.getBytes());

            System.out.println(alg + " Bytes " + new String(bytes));

            System.out.println(alg + " Base64 " + new String(Base64.getEncoder().encode(bytes)));

            return new String(Base64.getEncoder().encode(bytes));

        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException");
            return "";
        }
    }

    private static String hmac(String password, String alg, byte[] secret) {

        try {
            SecretKeySpec keySpec = new SecretKeySpec(secret, alg);
            Mac mac = Mac.getInstance(alg);
            mac.init(keySpec);
            mac.update(password.getBytes());

            byte[] bytes = mac.doFinal();


            System.out.println(alg + " Bytes " + new String(bytes));

            System.out.println(alg + " Base64 " + new String(Base64.getEncoder().encode(bytes)));

            return new String(Base64.getEncoder().encode(bytes));

        } catch (NoSuchAlgorithmException e) {
            return "";
        } catch (InvalidKeyException i) {
            return "";
        }

    }

}

Avendo definitiva conferma che l’algoritmo utilizzato è HMAC SHA256, quindi un hash “salato” con un segreto. Il problema quindi resta individuare il segreto. HashCat pare supportare il bruteforce del sale dell’HmacSHA256. Qualcuno ha qualche PetaFLOP da prestarmi?

WSO2 Microservices Framework for Java the Spring Way

Spring is a very popular framework among Java developers. Those who are familiar with the Spring framework tend to follow the same practice wherever possible and generally seek Spring integration support from other Java frameworks as well. The ability to use the Spring framework to develop MSF4J services and MSF4J extensions was one of the main objectives of the MSF4J 2.0.0 release.

Sorgente: [Article] WSO2 Microservices Framework for Java the Spring Way – Part 1

« Articoli meno recenti

© 2026 b0sh.net

Tema di Anders NorenSu ↑