Visualizzazione post con etichetta programmazione java. Mostra tutti i post
Visualizzazione post con etichetta programmazione java. Mostra tutti i post

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


martedì 11 settembre 2018

Java Telegram Bot


Breve appunto di come si ho fatto per fare un bot in java per telegram e di come l'ho fatto funzionare su tomcat8 e su jboss 10 + configurazione proxy.

Prima di tutto perche' un bot? Beh un bot che ti risponde su un'app di messaggistica istantanea ha delle potenzialita' notevoli, per esempio ti permette di interagire con l'applicativo senza essere loggato sull'applicativo stesso direttamente dal cellulare ovunque tu sia, e' una bella comodita'. Mi incuriosivano le potenzialita' del bot quindi mi sono detto: perche' no?

Primo passo:
le dipendenze. Se usate maven

<dependency> <groupId>org.telegram</groupId> <artifactId>telegrambots</artifactId> <version>3.6.1</version> </dependency>
(perche' proprio la 6 e non che ne so la 3? Per via del proxy...)

Secondo passo:
registrarsi usando BotFather
aprite telegram cercate BotFather
/start - per iniziare
BotFather vi dara' tutta una lista di comandi che puo' eseguire manteniamoci sul semplice:
/newbot - vi permette di creare un nuovo bot
vi chiedera' il nome del bot, il nome utente e vi dara' un token segnatevi tutto

Secondo passo:
creare il vostro bot ed estendere TelegramLongPollingBot il nome della classe dev'essere il nome del bot
dovrete estendere due metodi
getBotUsername() che deve restituire l'username scelto
getBotToken() che deve restituire il token che vi ha dato il botdrino
io per comodita' mi creo un metodo statico per registrare il bot in modo da avere tutto il codice relativo al bot in un punto solo

public static void registerBot(){ ApiContextInitializer.init(); TelegramBotsApi papi = new TelegramBotsApi(); //questo serve se la macchina che fa girare il bot e' proxata DefaultBotOptions botOptions = ApiContext.getInstance(DefaultBotOptions.class); HttpHost httpHost = new HttpHost("proxy_address", proxyPortAsInt); botOptions.setHttpProxy(httpHost); //ovviamente devi avere un costruttore con DefaultBotOptions come parametro IlTuoBot bobi = new IlTuoBot(botOptions); try{ papi.registerBot(bobi); }catch(TelegramApiException e){ //TODO faqquacos } }

Terzo passo:
implementare onUpdateReceived
che e' il metodo che vi permette di rispondere a chi vi scrive

bene ragassuoli, questo e' il metodo piu' importante di tutti perche' vi permette di interagire con l'utente
(se lui scrive per primo)

@Override public void onUpdateReceived(Update arg0) { if(arg0.hasMessage() && arg0.getMessage().hasText()){ //qui ho un nuovo messaggio //il chat id serve per poter rispondere ad un client specifico //se avete bisogno di inviare un messaggio automaticamente //salvatevelo da qualche parte (db?) Long chatId = arg0.getMessage().getChatId(); //il messaggio che il bot inviera' come risposta String text = "bot non ancora implementato"; SendMessage sm = new SendMessage(chatId, text); try{ execute(sm); }catch(TelegramApiException e){ //TODO faqcs } } }

Se volete che il bot scriva "suo sponte" a qualcuno dovete salvarvi il chat id da qualche parte
(io per sicurezza me lo faccio comunicare dall'utente che vuole interagire con il bot a mano, il bot su richiesta lo fornisce, l'utente se lo salva me lo da' a me io so chi e' etc)
non e' un metodo "obbligatorio" quindi la signature e' quella che vi pare a voi, basta che poi usiate la classe SendMessage e il metodo execute

Il bot puo' fare molto altro, puo' anche ricevere ed inviare contenuti multimediali tipo file immagini video etc. Quindi sbizzarritevi...

$NON_RICORDO_IL-NUMERO passo:
eseguire il bot.
- tramite main:
registrate il bot se deve solo rispondere non c'e' bisogno di fare altro. Finche' il main gira il bot sta su. - tramite server:
in tomcat8 avevo un filtro dichiarato nel web.xml e il bot lo inizializzo li'
su jboss 10 ho creato un singleton da eseguire allo startup (quindi una sola volta mentre si avvia il server) tramite le annotation

@Startup @Singleton annoti un metodo con @PostConstruct e li' dentro registri il bot

Penso (spero) sia tutto...

mercoledì 2 marzo 2016

Java leggere formattazione da database


Capita in Java, di dover generare dei file, ovviamente ogni file generato deve avere delle specifiche, per esempio un csv, nonostante la "c" stia per "comma" (ovvero virgola) puo' avere come separatore di campo qualsiasi carattere, idem per il fine riga. Puo' essere accapo (\n), ; etc.

Questo non e' un problema se scrivete direttamente nel codice, il che non e' un problema se le specifiche non cambiano mai. Siccome le specifiche cambiano, e le mamme invecchiano, e' bene parametrizzare questi valori e pescarli da qualche parte.

Questo qualche parte puo' essere un file o un database, il problema che si presenta e' lo stesso. Ovvero che java non riconosce o lo "\" e quello che lo segue come un terminatore di riga, ma lo tratta come se fosse un letterale (quindi \\n p.es). Anche se provate in unicode il problema rimane esattamente lo stesso (visto che c'e' \ davanti...).

La soluzione ce la offre Apache con StringEscapeUtils scaricabile da qui con il metodo statico StringEscapeUtils.unescapeJava(String) il quale ci restituisce la stringa "escapata" per java. La classe ne contiene altri ovviamente sia di escape che unescape, per csv, html, sql, xml etc...

Alla prossima!

venerdì 5 febbraio 2016

Java metodi che restituiscono piu' oggetti

C'e' un buon motivo per cui un metodo dovrebbe restituire UN solo tipo. Ma potreste trovarvi nella situazione di dover mettere le mani su un metodo fatto da qualcun altro, p.es che inserisce una riga a db e restituisce una ricevuta (e la usa per mandarla a frontend). Voi dovete fare delle modifiche e prendervi che ne so l'id della riga inserita.

Hibernate avrebbe un comportamento carino, cioe' i metodi save/updaterestituiscono l'id inserito/updatato il metodo save restituisce l'id della riga inserita. Ma il vostro metodo restituisce qualcos'altro e quel qualcosa serve.

a) andate a db e vi rifate una query con tutti gli altri dati e pregate che sia proprio quella che vi serve (in piu' avete il rallentamento dovuto al fatto di riandare a db per niente)

b) modificate il metodo in modo da restituire una mappa: in questo modo non avete bisogno di andare a db una volta di troppo, siete sicuri che quell'id e' proprio quello che volete, non aggiungete rallentamenti e avete tutto quello che vi serve. Ovviamente nei commenti specificate quali chiavi avete usato per mettere cosa, in modo che il povero cogl programmatore che viene dopo sapra' come ripescarseli. Ovviamente avete come effetto collaterale che tutte le chiamate a quel metodo andranno modificate.

c) create un terzo metodo che restituisce una mappa: vantaggi gli stessi di sopra con in piu' il fatto di non dovere modificare tutti i punti del codice ma solo quello dove vi serve a voi.

mercoledì 18 novembre 2015

HIbernate criteria - mini tutorial

Questo post non vuole essere esaustivo nei confronti dei criteria, vuole essere una mini-guida per chi si approccia per la prima volta a questo strumento.

La creazione di un criteria

Hibernate gestisce autonomamente il criterio di sessione e transazionalita' (quindi effettua suo sponte commit&rollback). Per utilizzare i criteria quindi avete bisogno che il vostro ambiente vi fornisca una sessione (di hibernate). Un Criteria si crea chiedendolo all'istanza della sessione che avete in mano e invocando il metodo "createCriteria" e passandogli come parametro la classe dell'entity sulla quale volete effettuare query.

Il metodo list()

Una volta fatto questo potete iniziare a fare query su quella tabella. Se volete tutti gli elementi potete fermarvi qui ed invocare direttamente il metodo list() del criteria. Questo metodo restituisce una List di Object per cui o fate un cast o la lasciate cosi' com'e'. Questo metodo si invoca quando il criteria (e quindi la query) puo' restituire piu' di un oggetto.

Il metodo uniqueResult()

Se invece siete sicuri che il risultato sara' unico (p.e. una count o state andando per id) allora c.uniqueResult() e' quello che fa per voi. Restituisce un object quindi dovrete fare un cast per ottenere la vostra entity.

Aggiungere condizioni

Se non si potessero aggiungere condizioni i criteria servirebbero a ben poco, no? Ecco che la classe Restrictions viene in nostro aiuto. invocando il metodo add del criteria da voi creato potete passargli una Restriction in maniera statica (quindi Restrictions.qualcosa). Che sara' eq se volete l'uguaglianza, analogamente lt/gt se minore/maggiore stretto e le/ge se <= / >= divertitevi ad esplorare tutte le possibilita' di Restrictions ce ne sono un sacco (in + lista etc).

Projections

Analogamente il metodo setProjections del criteria vi permette di aggiungere una "proiezione" - ovvero di modificare la select. Analogamente alle restrictions tutto quello che vi serve e' nella classe Projections. Per esempio .rowCount() vi restituira' un unico risultato contentente un numero con il totale delle righe per quella tabella .property(String property Name) vi permette di effettuare la select di un'unica colonna e cosi' via

La comodita' dei criteria

Rispetto ad altri strumenti (come la Query di hibernate) il criteria ha di comodo che genera automaticamente la query necessaria ad estrarre i dati e quindi il codice e' molto piu' compatto e leggibile, soprattutto se non sappiamo se i parametri del metodo ci verranno passati tutti. Un semplice if ci permette di aggiungere al criteria la restriction solo se il parametro e' valorizzato (evitando per esempio il doppio if delle query, uno per mettere la condizione e uno per valorizzare il parametro). Inoltre riducendo la quantita' di codice scritte minimizza il rischio di errori. Hibernate (e non solo i criteria) trasforma il tipo di dato su db in quello dell'entity. Quindi se su db c'e' un varchar (ma con un numero dentro) perche' il dba non e' un dba voi potete dichiararlo come Integer/Long/che vi pare e hibernate ve lo trasformera'. Analogamente potete farci una count o una sum. Inoltre usando criteria/hql che vengono convertiti da hibernate nel dialetto del db che si sta usando, rende il codice indipendente dal database, permettendo di cambiare db se necessario, semplicemente aggiornando il file persistence.xml

Non e' tutto oro quello che luccica

Per contro non hai il controllo diretto di quello che il framework sta facendo, a volte gli errori possono non essere significativi (ho avuto di recente un "where condition not found where expected" dovuto ad un (ok erano due!) nome di colonna sbagliato nell'entity - ma me ne sono accorto soltanto quando ho modificato il metodo per far eseguire ad hibernate una query sql e poi trasformare il result set derivante in entity. Inoltre ci sono cose che hibernate non gestisce bene (una per tutte le union). O le select di un substring ('pippo' = substring(x,y) di una certa colonna).

Come gia' detto questo articolo non e' per niente esaustivo, e' un primo approccio (veloce) ai criteria. Quando ho tempo approfondiro'

Alla prossima!