Utilizare port serial în aplicație Java pe Linux
Am nevoie să fac o conexiune pe un port serial din Java, și să comunic both ways prin el. (Eu sunt fericitul posesor al unui laptop generatie relativ noua (Dell Latitude 820) care are inca port serial - si ce bine ca are!). Am googălit puțin, și aici este o soluție, pentru arhivă (pe ubuntu 8.10 x86_64):
Se instalează pachetul oamenilor astora:
sudo apt-get install librxtx-java
Mai trebuie luat, de pe același site, RXTXComm.jar, în funcție de versiunea de rxtx care o are ubuntu vostru în repo (eu am 2.1.7.4).
Apoi, ca să-l folosiți în Eclipse, puteți să urmați ghidul de la ei de pe site. Traducere, pe scurt: adăugați JAR-u în class pathul proiectului, dați click pe el ([+] expand), setați native library location la /usr/lib (la mine), și proiectul vostru are puteri seriale :P. Este la ei pe site exemplu de cod suficient cât să te apuci de treabă.
News Search Engine / Proiect CI
CI este singura materie de an 5 pe care o fac toţi studenţii, indiferent de specializare (though, în funcţie de ce specializare ai, ai un alt profesor). Presupun materia asta are numele pe care îl are ca să ofere flexibilitate şcolii în a pune acolo conţinutul pentru care are profesori la un moment dat, but this is just a wild guess. Motivul care mă face să zic asta este că materia se ocupă cu Information Retrieval, şi numele ei n-are-a face cu asta.
Anyway, întâmplarea fericită a făcut ca specializările C1 şi C2 (eu sunt la C1) să îl aibă ca profesor pe first-time appeareance Paul Chiriţă, care e un meseriaş în domeniu şi care a lucrat pe la tot soiu de meseriaşi (like Yahoo) şi care acum s-a întors în Bucureşti şi lucrează la Adobe. Anyway, cursu a fost interesant, am şi reuşit să merg la câteva, dar era lunea, la 8, în Leu, ceea ce nu este prea compatibil cu mine :).
Am ales, împreună cu Gia, Micvs şi Miki să alegem calea interesantă şi să facem un proiect (alternativa era un referat). Evident, materia a început în octombrie, noi am aproximativ ales tema prin noiembrie şi am avut prima întâlnire pe 17 decembrie, cand deadline-ul era 12 ianuarie. Tema pe care ne-am ales-o a fost un news search engine, adică partea de crawl (spidering), partea de indexare, partea de gestiune a queryurilor, şi chiar şi o interfaţă de test.
Contribuţia mea la proiect nu a fost atât de mare pe cât mi-aş fi dorit, şi am ajuns la Bucureşti la aproape o săptămână dupa ce Micvs şi Gia s-or apucat deja de treabă, dar totuşi sper ca am ajutat :).
So, un pic despre proiectul nostru: ne-am propus sa re-inventăm roata ca să ne dăm seama cam cum era făcută, aşa că părţile esenţiale le-am facut de la 0. Motorul nostru de căutare de ştiri este scris în Java, şi foloseşte RMI între diferitele module (web-crawler, indexer, clienţi) şi JDBC cu baza de date în care menţinem un cache. Practic, ce ne-am pornit la drum să facem a fost o reinventare a roţii (sau, ca să citez din ceva ce-am citit pe net: ce rost are să te apuci să reinventezi roata, hai să reinventăm motorul - de căutare :P).
Crawlerul nostru este antrenat acum pe două site-uri: bbc.co.uk şi theguardian.co.uk. Am mers pe conţinut în engleză pentru că e mai uşor de găsit, mai corect format şi stufos decât ce găseam în română, dar mai ales pentru că anumite componente ale unui SE (stemming, spre exemplu) funcţionează ca în teorie când le aplici pe limba engleză. Practic, un "spider" porneşte de la site-ul principal, şi găseşte link-uri către categoriile principale ale site-ului, de unde obţine linkuri către ştiri. Se extrage textul şi titlul ştirii din pagină (cu o expresie regulată, pentru fiecare site), şi se trimite, printr-un apel RMI, server-ului de indexare. După ce termină toate linkurile, se semnalizează server-ului că s-a încheiat parcurgerea site-urilor şi crawler-ul este apelat din nou după câteva ore.
Server-ul de indexare întreţine, evident :), un inverted index. Index-ul este reprezentat în memorie ca un hashtable, în care cheile sunt hashuri (int) ale cuvintelor trecute printr-un stemmer simplu de limbă engleză, şi valorile sunt liste înlănţuite de referinţe la documente şi un vector de apariţii (poziţii în document în care apare cuvântul respectiv). De fapt, se menţine câte un vector de apariţii pentru titlu, conţinut şi sumar.
În timp ce primeşte toate ştirile dintr-o "transmisie", serverul foloseşte un pachet numit classifier4j pentru a calcula asemănările între două texte pe care le primeşte. Dacă asemănările sunt prea mari ( > 95%), ştirea este considerată duplicată şi se ignoră. Dacă ştirea seamănă în proporţie > 80% cu un text, se consideră ca este despre acelaşi eveniment sau aceeaşi serie de evenimente ca şi ştirea cu care este comparată, astfel făcându-se clustering bazat pe evenimente. Comparaţia se face folosind un motor care se foloseşte de teorema cosinusului într-un vector space de cuvinte (classifier4j mai poate folosi un comparator bazat pe teorema lui bayes, dar nu ştiam despre ce era vorba şi era mai complicat de folosit pentru ce voiam noi). La indexing-time se mai calculează şi un sumar static al textului, reprezentat din cele mai importante două propoziţii din text (calculate şi ele folosind un algoritm bazat pe teorema cosinusului aplicată pe spaţiul documentului respectiv). La fiecare indexare, cache-ul este înlocuit (în mod sincronizat) cu cache-ul nou.
Aspectul la care micvs a insistat la construirea indexului a fost performanţa: parsări minime ( = 1) a oricărei liste, oricărui string, şi optimizări pentru tratare de queryuri, în detrimentul performanţei indexării, dacă a fost cazul.
Pentru tratarea query-urilor, server-ul primeşte de la aplicaţiile client o listă de cuvinte cheie, printr-un apel RMI. Serverul foloseşte inverted index-ul pentru a găsi documentele care conţin cuvintele respective, şi aceste liste sunt apoi intersectate. Fiecare document primeşte o notă, la query-time, bazată pe numărul de apariţii a cuvântului în textul documentului şi pe existenţa sau absenţa cuvântului căutat în titlu şi în sumarul documentului. Dacă căutarea se face după mai multe cuvinte, nota se acordă şi în funcţie de apropierea în cadrul documentului între cuvinte (adică e mai relevant un document care contine termenii de căutare mai apropiaţi - în special unul lângă celălalt).
Pentru prezentare, miki a lucrat la o interfaţă în java, aşa, de POC (proof of concept) ca să putem să arătăm cum se obţin rezultatele şi cum se grupează. Pe mine m-a ros nonstop faptu că nu am făcut ceva webbased pentru căutare, că pentru mine făcea mai mult sens să fie webbased, aşa că, după predarea proiectului, m-am jucat un pic, pentru prima dată ever cu nişte Servlet-uri. Promit că dacă o să chiar termin ceva o să le pun la mine pe site să le poată testa cine vrea :).
Oricum, a fost un proiect instructiv, şi, pe cât îmi displace mie Java, trebuie să recunosc că munca în echipă e mult mai clar definită când se programează în limbaje gen Java. Proiectul ăsta a fost şi primul proiect la care am reuşit să-i conving pe ceilalţi să folosim SVN pentru controlul codului, ceea ce pentru mine a fost o reuşită personală.
Partea mai puţin reuşită a fost prezentarea efectivă a proiectului, unde am mers direct după o noapte nedormită cu o prezentare încropită şi un proiect semi-finalizat. M-am bâlbâit nonstop la prezentare, şi când i s-o terminat la Gia bateria de la laptopu de pe care prezentam I froze. Evident, se pare că prezentările astea erau oarecum mai puţin colegiale şi mai mult "oficiale" aşa ca mi-am luat bobârnacu necesar peste nas, dar îl meritam pentru că am mers, într-adevăr nepregătit pentru o prezentare.
Webservices – Tema3 LPD
LPD (Limbaje de Programare Distribuită) este o materie de an V în facultatea noastră, pe care eu mi-am ales-o ca materie opţională, în mare pentru că am citit în descriere despre chestii gen Servlets şi Java Server Pages şi despre Webservices. În mare, o materie al cărei conţinut (din cuprins) părea cel puţin deosebit. Pentru mine, totuşi, materia asta nu s-a potrivit nicicum. Profesorul de la curs (Florin Pop) mi s-a părut aşa, plin de entuziasm pentru curs, dar cursul a suferit de plasarea în orar vinerea de la 8, aşa că entuziasmul meu nu a putut să fie la fel de mare. Din păcate, teaching assistant-ul cu care am facut laboratorul, un tip al cărui nume nu o să-l postez aici, era perfect pe dinafară. Laboratorul era nepregătit, el era nepregătit, nu aveau locuri suficiente pentru toată lumea. Am participat de câteva ori, şi am renunţat, chiar artistic, aş putea spune.
A treia mare problema a mea cu materia asta, şi unica pe care o chiar regret, a fost că deadline-urile pentru teme s-au potrivit exact peste date când eu aveam alte necazuri (în principiu, UP) şi nu am reuşit să mă ocup de ele cum ar fi trebuit. Se pare însă că o să am ocazia să revin asupra acestei probleme, în sesiunea din aprilie.
Anyway, era vorba despre Tema 3. Tema 2 la LPD s-a ocupat (printre altele) de utilizarea RMI pentru implementarea comunicării între diferitele entităţi. Tema 3 ne-a cerut implementarea unui serviciu web care să ofere unor clienţi posibilitatea să verifice rute de avioane şi să rezerve / cumpere bilete de avion (şi în plus, ceva prostii de administrare, non-interesting). Se cerea ca tema să fie implementată peste Apache Tomcat (5.5) şi Apache Axis (1.4).
Practic, un webservice pune la dispoziţia unor clienţi nişte metode pe care aceştia le pot apela folosind mesaje. Metodele disponibile se pot afla interogând endpoint-ul serviciului, iar mesajele care se pasează sunt în format XML (ceea ce, faţă de RMI, are imensul avantaj că acum participanţii într-o conversaţie pot fi scrişi în orice limbaj). AXIS este un webapp pentru Tomcat, care permite creearea on-the-fly a serviciilor web (automatizează procesul de deployment şi de publicare a serviciului). Practic, tot ce rămâne de făcut programatorului este să scrie o clasă java care implementează metodele pe care vrem ca serviciul să le pună la dispoziţie, şi Axis se ocupă de restul paşilor.
Paranteză: Well, evident, chestia asta sună all-to-familiar: API-urile puse la dispoziţie de aplicaţiile web suna a webservice-uri (Google API, YDN, flickr, twitter, infamul hi5, facebook ...). Well, sună a webservice pentru că asta sunt, de fapt. Diferenţa este că majoritatea API-urilor implementează un protocol de comunicaţie numit REST (RESTfull), pe când webservice-urile "serioase" - java + corporate, spre exemplu, folosesc SOAP.
Înafară de partea de webservice, tema 3 presupune gestionarea în fundal a unei baze de date MySQL cu informaţii despre zboruri. Câteva chestii de notat aici, conexiunile cu baze de date în Java sunt ceva mai rigide decât cu ce eram obişnuit în php, probabil şi din cauză ca Java e considerat un limbaj pentru aplicaţii mai "serioase" (deşi mie mi se pare o prostie ...). Partea de conexiune prin JDBC (Java DataBase Connectivity) este relativ simplă (4 linii :P), dar trebuie să ai un J-Connector de la MySQL (gratis). Totuşi, tema noastră ne cerea să facem uz şi de JDNI (care este o schemă de (re)găsire a chestiilor într-un Directory), pentru partea de serviciu.
Am aplicat ce am învăţat în dezvoltarea yPHP despre baze de date, despre maparea lor pe instanţe de clase, pe păstrarea sincronizării cu baza de date. Şi, am luat din experienţa temei 3 şi idei pe care vreau să le aplic (sau le-am aplicat deja, în parte) în yPHP, în special partea în care poţi avea mai multe surse de date, nu doar o bază de date MySQL, şi implementări de drivere pentru fiecare fel de DataSource.
Mi-e mult prea complicat să fac un deployment să vă arăt exact exact serviciul meu web în acţiune. Ce e important de ştiut (şi ce notez aici) sunt paşii care trebuie urmaţi pentru a putea face deployment-ul unui serviciu web cu Axis (paşii de mai jos nu sunt descoperirea mea, ci a Giei, căreia îi rămân dator pentru ajutorul ăsta care ni l-a dat pentru tema asta). Am modificat putin ca şi formă, dar nu ca şi conţinut:
Instalare server / deployment web service Java cu Axis
1. dezarhivare pachete axis / apache tomcat
2. copiati folderul axis din axis-VERSIUNE/webapps/ in apache-tomcat/webapps
3. setati varibilele de mediu ca in linkul : http://ws.apache.org/axis/java/install.html#Step6DeployingYourWebServiceApoi, ca sa faceţi deployment la un serviciu web folosind jws: clasa .java cu implementarea se redenumeşte Clasa.jws si o copiati in directorul apache-tomcat-5.5.27webappsaxis. Ca sa testati daca e ok, folosiţi url-ul : http://localhost:8080/axis/Clasa.jws Ar trebui să răspundă că acolo locuieşte un serviciu web
Notă: daca folositi clase facute de voi in clasa Clasa.jws trebuie sa copiati fisierele binare in apache-tomcat-5.5.27webappsaxisWEB-INFclasses , altfel o sa dea eroare.
Conexiune cu baza de date MySQL prin JDNI
În apache-tomcat-5.5.27confCatalinalocalhost salvati un fisier axis.xml care sa aiba conţinutul:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/axis" debug="5 reloadable="true" crossContext="true">
<Resource name="jdbc/NUME_JNDI" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="USER_DB" password="PASS_DB" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/NUME_BD?autoReconect=true"/>
</Context>În fişierul apache-tomcat-5.5.27webappsaxisWEB-INFweb.xml trebuie adăugat la sfârşit, înainte de închiderea lui <web-app> :
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/NUME_JDNI</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>Şi apoi vă conectaţi la baza de date, în Clasa.jws , astfel:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/NUME_JDNI");
dbConnection = ds.getConnection();
Înafară de JDBC, JDNI şi Webservices eu am învăţat multe lucruri utile despre ANT (colegii mei învăţaseră deja de la Tema 2). Pe scurt Ant e un build tool, al cărui script de build se scrie în XML. Practic, un fel de make (cu makefile-ul) aferent, doar ca mai flexibil şi mai uşor de utilizat. În ANT, unitatea de execuţie este target-ul. Un target poate conţine mai multe task-uri, în funcţie de task-urile respective, şi poate depinde de alte target-uri.