mercoledì 18 dicembre 2019

Primefaces modificare un tema

Guida velocissima - poi eventualmente aggiorno l'articolo per mettere immagini & co.

Do' per scontato che abbiate scaricato il jar all-themes-jar


    org.primefaces.themes
    all-themes
    1.0.10*

*La versione prendete un po' quella che vi pare eh...

Aprite il jar che trovate sotto
.m2*/repository/org/primefaces/themes/all-themes/$nr_versione/$nome_del_jar
Se non avete un path personalizzato per il repo maven

A questo punto avete 2 possibilita' o modificate un tema esistente
( META-INF/resources/$nome_del_tema_da_modificare)
oppure ve ne create uno vostro. Il consiglio e' "clonare" uno esistente (che vi piace) e poi personalizzarlo - questo perche' sono troppe le variabili in gioco e rischiate di cannare qualcosa (magari di primo acchito vi sembra che funzioni tutto e poi diventa un casino sanare).

a questo punto aprite la directory del tema da modificare. Troverete un foglio di stile che si chiama theme.css
li' dentro fate le vostre modifiche/aggiunte.
Reimpacchettate il jar (oppure sostituite il file theme.css dentro il jar con quello da voi modificato).

Rimettete il jar dentro il vs. applicativo (se non dichiarate la dipendenza come provided se la va a scaricare tutte le volte - quindi dovete poi infilarla nella lib del vostro web-progetto).

Alla prossima!

Annunci strani

Ogni tanto ci si imbatte in "perle" come questa.
Posso capire che sei un'agenzia di ricerca personale e quindi scrivi quello che vuole il cliente,
perche' magari competenze specifiche non ne hai.

Posso capire che anche il cliente sta cercando di rimpiazzare QUELLA persona che guardacaso sapeva un po' di tutto.

Pero' e' un pelo assurdo ricercare una posizione per programmatore COBOL (che e' molto specifica) e nello stesso tempo chiedere di java, spring ed hibernate (che sono framework comuni per chi utilizza Java) e in piu' gia' che ci sei html/css/js (che sono specifici per un'altra posizione ancora).

Il rischio e' che le persone che hanno competenze abbastanza approfondite in un campo verranno scartate perche' non rispondono a tutti i requisiti e ti ritroverai ad assumere una persona che probabilmente sa poco di tutto...

giovedì 12 dicembre 2019

Primefaces fileupload skin simple ma ajax


Allora primefaces e' un framework molto carino - ma sul file upload c'e' un problemino... Ovvero che se si sceglie lo skin simple si perde la capacita' di upload in ajax/automatico. Quindi devi fare una post completa. Questo nella maggioranza degli scenari potrebbe non essere un problema. Anche perche' c'e' il mode "advanced" che permette l'autoupload.

Solo che il mode "advanced" non e' che sia esattamente gradevole. Nel senso va bene se ne hai uno - ma se come in $applicativo i file da caricare sono molteplici e se per ragioni di continuita' con il vecchio non puoi mettere un menu' a tendina per scegliere il tipo di file che stai caricando - fa un po' schifo avere una tabella con decine e decine di righe con tutti 'sti quadratoni.

La soluzione e' andare di css (oppure modificate il vostro tema) - cosa ci dovete scrivere?

.ui-fileupload-content{
     display:none;
}

.ui-fileupload-buttonbar{
     background:none;
     border: none;
}

Fatto - adesso potete usare la modalita' "advanced" ma che assomiglia a quella simple.

ATTENZIONE

Facendo nel modo sopradescritto lo stile si applichera' a tutti i vostri file upload (se modificate il tema solo per quel tema, se aggiungete un css per tutti punto e basta). Se non volete questo dovete crearvi uno styleclass che si applichi solo ai nomi di cui sopra.

martedì 22 ottobre 2019

Perche' non faccio programmi per gli amici

A chi non e' mai capitato? Se hai un amico che si intende di X prima o poi ti capita di chiedergli qualcosa a riguardo di X. E quello non e' un problema.

A volte capita che qualcuno ti chieda di fargli un programma.
Lo so un programma non e' qualcosa di "tangibile" come un mobile pero' e' sempre qualcosa che richiede lavoro per essere fatto.

Siccome non sono un libero professionista ma sono dipendente, le "8 ore" non posso usarle come mi pare a me ma devono essere spese a beneficio del cliente.
Questo vuol dire che qualsiasi altra attivita' deve essere fatta nel mio tempo libero.
Tempo che potrei usare per riposarmi o per stare con i miei figli.

Quindi quando mi chiedi di svilupparti un programma mi stai chiedendo di sottrarre del tempo alla mia famiglia e a me stesso.
Sviluppare un programma e' un processo molto lungo. Non e' un comodino. Che pure richiede lavoro.
Quando mi chiedi un programma io devo sapere su cosa vuoi farlo girare. Lo so che a te ti rompe i coglioni e vorresti una cosa "basta che sia" pero' ci sono cose che ho bisogno di sapere. Tipo come intendi interfacciarti? Vuoi usarlo su tutti i pc? In tal caso mi ci vuole un server. Vuoi un'applicazione da mettere su una macchina? In tal caso i dati non saranno condivisi a meno di non metter su un db-server. ... e cosi' via. La parte requisiti spesso e volentieri e' molto lunga forse anche di piu' dello sviluppo vero e proprio.

Poi una volta deciso l'ambiente bisogna decidere come dev'essere e cosa deve fare. E questo lo sai solo tu. Inutile che tu mi dica "fai te" e quando poi ti presento il prodotto non ti vada bene e volevi che facesse qualcos'altro. Mi hai fatto solo perdere tempo perche' TU non volevi perdere il TUO.

In piu' se dopo mesi di lavoro (magari sottraendo ore al giorno che avrei potuto spendere a giocare con i miei figli) ti porto il prodotto finito e tu, che ti sei stancato di aspettare, hai comprato un sw del cazzo in edicola... Beh allora mi girano pure le palle.

...ecco perche'.

mercoledì 16 ottobre 2019

Tempi Moderni


Assisto a questa conversazione (censurata per privacy & sicurezza). Penso non ci voglia un grandissimo genio per capire come mai il link allegato alla mail non funziona... Il client di posta con la quale la mail e' stata inviata si e' fermato al primo & mentre l'url e' tutto.

Perche' tempi moderni? Perche' la risposta dell'astinenza e' un sintomo di un atteggiamento sempre piu' diffuso.
Non si cerca di capire il problema. Ci si lamenta che non funziona.
Il che e' particolarmente grave se proveniente da un qualcosa che dovrebbe fare assistenza tecnica (e' l'hosting pampers di dove lavoro)

Di piu': e' stata assunta una persona del genere perche' probabilmente chi l'ha selezionato ha un atteggiamento del genere, o non ha le competenze per capire se chi stai assumendo sa fare il suo mestiere oppure no. E ancor peggio e' che la conseguenza e' che non sei nemmeno in grado di formare un futuro "professionista" (a questo punto le virgolette sono d'obbligo).

Se non avesse avuto una mail a cui rispondere probabilmente avrebbe postato la domanda su stack-overflow...

venerdì 4 ottobre 2019

Hard lesson

Allora quando entrai in $POSTO nel lontano 2015 avevano un applicativo J2EE sviluppato per Java 1.6 (rilasciata intorno al 2005) e Jboss 5 (c.ca 2007). Erano gia' all'epoca versioni "diversamente nuove". Oltretutto che java 1.6 e' afflitta da vulnerabilita' parecchio pesanti.

Il mio senso del dovere ha fatto si' che ho iniziato molto presto a fare presente i problemi derivanti da usare roba EOL (quindi non aggiornata ne' aggiornabile) e affinche' si prendesse in considerazione uno svecchiamento. Svecchiamento che consiste in una riscrittura. Perche' se cambi java devi cambiare jboss (non e' certificato). Se cambi jboss devi cambiare struttura al progetto (perche' i wildfly adottano un'architettura modulare) e devi cambiare jsf perche' wildlfy vuole jsf2.

Di conseguenza piu' che un porting e' una riscrittura. Riscrittura che molto pazientemente ho portato avanti in maniera praticamente "carbonara". Senza nessun appoggio di nessuno perche' nessuno ne vede(va) l'utilita'.

Esiste gia' un prodotto che funziona perche' devo spendere tempo e soldi per riscriverlo da capo? - Questo fondamentalmente l'atteggiamento di tutti, dalla responsabile al cliente al Digerente...

A niente e' valso lo spiegare che essendo prodotti EOL il loro supporto da parte di chiunque potrebbe cessare di botto e senza preavviso.

Fast forward ad oggi: l'applicativo non invia piu' la pec.

Mi guardo i log e
La versione del client di posta che stai utilizzando non rispetta i requisiti di sicurezza minimi richiesti dal servizio PEC. Per maggiori dettagli sui requisiti di compatibilita' vai su verifica.pec.it
Aka la versione del client con cui fai hand-shake e' troppo vecchia.

...ma guarda un po'...

Riunione stile Fuher-Bunker con gli alleati alle porte. Non riesco a smettere di ghignare lo ammetto. Ovviamente faccio presente che sul porting (che nessuno s'e' caato da anni) la pec funziona Mi rispondono che c'e' bisogno della pec SUBITO

$ME_PENSA: se mi avevi dato retta in tutti questi anni non ti saresti trovato in questa situazione.

Faccio presente che comunque la colpa e' nostra che usiamo una Java geriatrica e anche se non pronuncio le parole "te lo avevo detto" - il sorriso da stregatto lo fa al posto mio.

Dopo vari ravanamenti, spiego che le nostre macchine di sviluppo sono su jboss 5 + java 1.8 e che se anche se questa soluzione non e' certificata (jboss 5 e' certificato per la 1.6) potrebbe essere un modo per sopravvivere. Anche se per inciso non e' detto che funzioni perche' usiamo un componente "custom" sviluppato per $ENTE per autenticare la gente tramite smart card/spid & co. Questo componente la versione vecchia non funziona con la java 18 e quella nuova non e' detto che funzioni con jboss 5 (il sistemista di $HOSTING_PAMPERS in questo momento sta bestemmiando parecchio)... Vi terro' aggiornati

Quello che spero e' di riuscire a fare capire la necessita' di passare a qualcosa di piu' "nuovo" (java 1.8 e' fra i requisiti minimi e su oracle c'e' la 12 quindi non e' che sia poi cosi' nuova) lasciando perdere totalmente il vecchio, e soprattutto riuscire a far capire la necessita' non solo di aggiornarsi ma anche di rimanere aggiornati.
Tanti piccoli passi costano meno di uno gigantesco...

Aggiornamento (15/08/2021):
Non sono piu' in quella gabbia di matti (grazie a Chtulu). Quando sono andato via (quasi 2 anni fa) erano ancora a madonnare. Avevo anche proposto una soluzione "tampone" che avrebbe permesso di non cambiare la configurazione, in soldoni un applicativo REST da sviluppare su wildfly e che facesse da ponte tra il vecchio e la pec. La risposta era stata che ci sarebbe voluto troppo tempo (secondo la responsabile almeno 1 mese per andare in produzione), sono stati quasi 2 anni senza inviare pec.
Questo per farvi capire come ragiona certa gente...

mercoledì 14 agosto 2019

Statistiche del blog

Estate, caldo giornata light prima delle ferie... Tempo di statistiche.

So che siete in 3 e non ve ne pole frega' de meno, pero' quell'Amiga mi ha fatto sorridere...

Software e Guida Autonoma

Questo tweet di Paolo Attivissimo mi ha spinto a rispondere per scatenare una riflessione.

Ovvero: la guida autonoma e' davvero una buona soluzione all'idiozia umana?

Partiamo dalle premesse, attualmente la guida autonoma e' un pezzo di software. Complesso quanto vuoi ma software tradizionale. Anche perche' l'intelligenza artificiale sembra fare un po' la furbetta (in realta' fa quello per cui e' programmata ovvero per risolvere con minore fatica possibile il problema che le e' stato posto, pero' ancora non sembra essere applicabile a situazioni reali).

Dicevamo e' un pezzo di software. Il software ha sicuramente dei pregi che sono i tempi di risposta ed il rispetto delle regole. Sul contro abbiamo la scarsa flessibilita' e l'adattabilita' (cose in cui noi umani invece siamo piuttosto bravi).

Inoltre essendo codice per sua natura e' pieno zeppo di bug e vulnerabilita'. E' inevitabile.

Inoltre il software ha un difetto: funziona finche' non smette di funzionare (sembra banale detta cosi') e quando questo succede i danni tendono ad essere incalcolabili (ne sa qualcosa at&t)

Lo faccio presente:

Ora non mi ricordo l'ordine preciso anche perche' ci sono stati un paio di "rami" di gente che si accodava ad Attivissimo...

La risposta non mi ha convinto, ma per niente. Gli umani hanno difetti? Verissimo ma provate un attimo a prendere il controllo da remoto di un essere umano...

Perche' e' quello che succede con le auto. E non mi dite che in caso di guida autonoma farebbero piu' attenzione. La pressione del mercato e' troppo alta, succede in praticamente tutti gli ambiti, bisogna uscire ed uscire prima del concorrente. Il resto si vedra'.

Pensateci un attimo: guida autonoma vuol dire che un eventuale attaccante avrebbe il controllo completo di un aggeggio che gira per strada che pesa se va bene 1 tonnellata. Avete idea di cosa potrebbe combinare?

Ma ammettiamo per un attimo che non siano cosi' cazzoni. Anche a scriverlo con le migliori intenzioni possibili il sw contiene da 5 a 50 bug per migliaia di righe di codice (nel tweet avevo scritto per milione). La fonte? Exploiting Software pg. 14 I cui autori sono un ricercatore informatico ed uno scienziato informatico. Non esattamente i primi venuti.

Quindi un eventuale guida autonoma porterebbe con se migliaia di bug potenzialmente sfruttabili da un eventuale attaccante (considerando solo il sw e non le vulnerabilita' dovute ad altro per esempio librerie di terze parti oppure dovute al linguaggio di programmazione o ad una certa versione del compilatore*). Se poi l'auto e' pure connessa ad internet come oggi e' la prassi diciamo che ci sono buone basi per un disastro di proporzioni epiche.

Non metto tutti i tweet perche' non aggiungono niente al mio pensiero ma voglio lasciarvi con la mia conclusione:

Noi umani siamo bravi in compiti "non noiosi", e che richiedono capacita' di adattamento e flessibilita'. Siamo anche (abbastanza) bravi ad interpretare il comportamento delle altre persone, tipo il tizio che mette fuori la mano dal finestrino per indicare una svolta... Mentre il software e' bravo in compiti che richiedono ripetitivita' e tempi di reazione brevi (esattamente dove non siamo forti noi). Inoltre il software funziona bene in situazioni totalmente controllate (es. il sw di volo dove le rotte sono pianificate e se ci sono situazioni impreviste la palla passa ai piloti).

Per come la vedo io bisognerebbe combinare le due cose. Ovvero lasciare all'umano il controllo nella maggioranza delle situazioni, con il software pronto ad intervenire se l'umano sbaglia (p.es se cicca una frenata o se sta andando contro un muro). E non il viceversa (come l'autopilot tesla per intendersi). Inoltre per esempio il sw potrebbe prendere il controllo in situazioni come una coda (dove l'umano tende a distrarsi). Ovviamente il sw di controllo della macchina non deve essere in nessun modo connesso ad internet, deve essere un sistema isolato. Lo so che fa comodo aggiornarlo da remoto ma...

*es. Java 1.6 oppure il vecchio compilatore di C++ quello del buffer overflow per intenderci...

lunedì 15 luglio 2019

HellDesk


Oggi e' giornata di articoli visto che sono al secondo... Ma tant'e'. Ve la faro' molto breve: dobbiamo accedere ai servizi di $HOSTING_PAMPERS per deploy del codice, qualita' dello stesso (un'immane cagata imho) etc. Questi sarchiaponi richiedono l'accesso in vpn tramite il client integrato di windows. Probabilmente c'e' una configurazione di questa macchina o qualche pacchetto che va in conflitto o sonasega per cui come cerco di aprire le impostazioni wpn vpn* di windows si pianta.

Ci son stato dietro per un po', poi ho deciso che siccome abbiamo un'astinenza tecnica e che ci avevo gia' perso troppo tempo dietro (e non mi pagano per questo, mi pagano per fare il mio lavoro) era giunto il momento di contattarli. Quello che seguira' sono le email vere scambiate tra me e l'astinenza. Ho solo cambiato un po' di nomi ma non ho inventato niente.

La mia mail con la quale ho aperto il ticket

Buongiorno,

sono un collega che presso $ENTE a $CITTA'

Scrivo per segnalare che usando il client vpn di windows (che e' necessario per eseguire delle attivita' presso $HOSTING_PAMPERS) il client stesso si blocca

e non mi e' possibile ne' modificare la configurazione VPN attuale, ne' aggiungerne di nuove.

Premetto che
  • la configurazione vpn $DITTONA, usando il client cisco e' perfettamente funzionante e *non deve essere toccata*
  • il client vpn integrato di windows e' richiesto da $HOSTING_PAMPERS per attivita' sui loro server
  • ho effettuato tutti gli aggiornamenti di windows disponibili in data $DATA_MOLTO_RECENTE e che il problema non si e' risolto
pertanto chiedo se e' possibile avere supporto in merito a tale problema.

Saluti

La prima loro "risposta"

Buongiorno, vorremmo chiarimenti in merito al ticket aperto.
ci puo' dire se i problemi di connessione sono sulla vpn1 oppure sulla vpn2?
Saluti

La mia risposta:

Scusate cosa intendete con "vpn1" e "vpn2"?

Non ho problemi di connessione, ho problemi di configurazione. Il client vpn di windows si blocca quando si cerca di aprirlo per modificare le impostazioni oppure per creare una vpn nuova.

Invece il client cisco (quello usato per $DITTONA) funziona correttamente.

Saluti

Altra mail dell'astinenza (evidentemente non sono stato abbastanza chiaro):

Deve collegarsi alla vpn $ALTRA_AZIENDA oppure a quella clienti?

Risposta mia (pazienza in esaurimento)

Il problema nasce cercando di configurare una vpn usando il client integrato di windows.

L'uso di tale client e' richiesto da $HOSTING_PAMPERS (hosting partner di $ENTE)

in nessun caso si tratta di una vpn di $DITTONA.

Ecco la perla dell'astinenza:

Provi a collegarsi ad una vpn per volta .


Al che ho deciso che era inutile proseguire, ho preso le responsabili (che fra parentesi leggevano in copia e si son fatte delle grasse risate) e ho chiesto loro, visto che comunque il mio pc ha un'hdd poco capiente, se era possibile cogliere la palla al balzo e sostituire l'hdd di questa macchina. Loro mi mandano l'hdd e IO faccio tutto il lavoro. Reinstallo la macchina da pulito (ho i dischi di ripristino) e si prova cosi'. Ovviamente ho chiuso il ticket...

Alla prossima!

14/08/2019 ogni tanto mi scappa una "w" al posto di "v" perche' e' un modo di scherzare che usiamo in ufficio (w pronunciata u alla martufello). Per cui un ipotetico "Giovanni" diventerebbe "Giouanni" (scritto "Giowanni")

Java Reflection e CSV

Cosa sono le reflection? Sono sostanzialmente un modo per ottenere tutti i nomi dei metodi, ed eventualmente invocarli, senza sapere quali siano questi metodi. Tutti sanno da codice invocare il metodo "getPippo()" di una certa classe scrivendolo da codice, ed e' quello si fa praticamente di normale. Pero' ci sono delle situazioni per le quali non sai il nome dei metodi da invocare (oppure non li vuoi sapere perche' sono centinaia e devi invocarli tutti).

Java ci mette a disposizione uno strumento potentissimo (se usato bene): le reflections. E' possibile da un oggetto Classe ottenere i nomi dei suoi metodi (come oggetto Method). Tramite questi nomi, e' possibile invocarli per esempio, ma e' necessaria un'istanza di quella classe (ovviamente). E' anche possibile passare argomenti.

Il caso che tratteremo qui e' la generazione di un csv. Il caso che mi ha spinto a creare una classe generica e non una ad hoc e' che la tabella (e quindi l'entity) della quale devo generare il csv ha una pletora di campi (2 o 300 tipo) per cui la decisione era:

  • spendo 2h a fare un csv con possibilita' altissima di sbagliare (visto l'elevato nr. di campi)
  • spendo 10min a farlo con una reflection con la possibilita' poi di usarlo per tutto?

La domanda e' semiretorica anche perche' se non avessi scelto la seconda opzione non sarei qui a scrivere questo articolo. Per arrivarci pero' devo fare un po' di premesse:

La prima e' un metodo "generico" che formatta un oggetto usando istanceof (e restituisce una stringa) controllando pure se e' null o not. Se l'oggetto che mi passo in input e' null restituisco stringa vuota (questo perche' in un csv devi comunque mettere un ; se vuoi un campo vuoto).



Poi ci serve (o almeno a ME!!!) un metodo per convertire il camel case in stringa "normale" - questo perche' uso i nomi dei metodi come nomi di colonne (non vorrai mica fare un csv senza intestazione). Ma questo si fa facile - StringUtils di apache ci viene incontro con splitByCharacterTypeCamelCase il cui risultato passeremo al metodo join sempre di StringUtils (non metto screen abbiate pazienza).

Fatto questo io mi sono fatto un metodo di utilita' che data una classe restituisce tutti i suoi getters (escluso getClass che nel csv non serve)

Poi ci serve un metodo di utilita' che restituisca una stringa csv di una certa istanza (generica). Ho usato i generics perche' voglio potergli passare di tutto. Come si puo' notare per invocare un metodo tramite reflection si invoca il metodo invoke passandogli un'istanza che e' quella sulla quale il metodo verra' eseguito il risultato e' un object. Mi passo anche il separator (perche' voglio essere flessibile).

Come si puo' vedere viene invocato il metodo "formattatore" generico presentato all'inizio, questo evita che nella stringa ci sia il toString degli oggetti (che non e' molto human readable). Inoltre, sempre questo metodo, evita che ci siano dei campi sfalsati nel csv (dovuto alla presenza di campi null).

Vi risparmio la parte di scrittura su file perche' non interessante ai fini di questo articolo.

Alla prossima!

mercoledì 12 giugno 2019

Java get or else get


Quando si ha una lista in mano in Java 1.8 lo stream e' uno strumento molto potente, puo' essere usato per un fracco di cose tra cui la trasformazione della lista in qualcos'altro. Per evitare al programmatroto una .get(0) per prendere il primo (o uno qualsiasi) della lista sempre lo stream ti viene incontro con i metodi findFirst e findAny. La differenza? Il primo ti garantisce che l'elemento sia sempre quello.

Ovviamente suddetti metodi restituisco un Optional - a questo punto avete un po' di possibilita' davanti:

  1. Ve ne battete allegramente e fate la get che c'e' c'e' (non devo dirvi perche' non e' una buona idea)
  2. Fate un ifPresent e nel caso fate la get ma son righe in piu' di codice. Che scherzi?
  3. Invocate uno dei due metodi che sono l'oggetto di questo post

Qual'e' la differenza? orElse restituisce direttamente l'oggetto passato come parametro. Quindi potete tranquillamente passare null. orElseGet (come dice il nome) fa la get su quello che gli passate (quindi dev'essere un Supplier) e non devo dirvi (di nuovo) perche' non e' una buona idea passare null.

Se invece volete lanciare un'eccezione c'e' orElseThrow




Se non sapete cosa c'incastri l'immagine con il post andatevi a cercare cosa vuol dire "stream" in Inglese