miercuri, 20 mai 2009

Python mocking __new__

In acest tutorial voi prezenta o facilitate python extrem de interesanta: inlocuirea metodei speciale __new__. Acest lucru mi-a fost util in momentul in care am scris o suita de teste pentru o clasa. Problema era ca aceasta clasa era Singleton si in concluzie era dificil sa ma asigur ca resursele injectate sunt corecte de la un test la altul. Solutia de compromis a fost sa elimin comportamentul Singleton al clasei doar pentru teste.

class TestedClass(float):
def mockedNew(cls, *args, **kwds):
print("Mocked new")
self = float.__new__(*args, **kwds)
return self

def deleteNew(cls):
cls.__new__ = cls.mockedNew

def __new__(cls, arg=0.0):
"Convert from inch to meter"
print("Normal new")
return float.__new__(cls, arg*0.0254)

def __init__(self, arg=0.0):
print("Not working")

deleteNew = classmethod(deleteNew)
mockedNew = classmethod(mockedNew)

if __name__ == "__main__":
TestedClass.deleteNew()
print(TestedClass(12))

In mod normal, in exemplul de mai sus, daca nu as apela deleteNew rezultatul ar fi:
  • Normal new
  • Not working
  • 0.3048
Apeland deleteNew in main obtinem rezultatul:
  • Mocked new
  • Not working
  • 12
In aceasta maniera am reusit sa modific comportamentul metodei speciale __new__ in mod dinamic.

marți, 19 mai 2009

Python si Mocker

In acest tutorial voi prezenta un mod de testare care va ajuta sa eliminati dependentele(de scriere pe disk, de query-uri catre baze de date, etc...) si sa urmariti rularea propriu-zisa a algoritmului. Pentru a putea face acest lucru, trebuie sa permiteti functiei/clasei dumneavoastra sa "injecteze" obiecte in algoritm. In exemplul urmator vom arata cum se poate elimina dependenta de sistemul de fisiere.

def algoritm_complex(objOpen=open):
#aici vine rularea algoritmului

#aici vine partea de dependenta de hdd
f = objOpen("fisier.txt", "w")
f.write("testare simpla")
f.close()

Observam ca in functia de mai sus am furnizat un parametru cu valoare default buitin-ul open. In aceasta maniera in momentul in care functia va fi apelata intr-un mediu de productie nu va fi furnizat nici un parametru in timp ce in momentul in care se va dori testarea algoritmului se fa furniza o functie simulata. In continuare prezint partea de "mocking":

def test_AlgoritmComplex():
controller = Mocker()
objOpen = controller.mock()
fMocked = controller.mock()

objOpen.open("fisier.txt", "w")
controller.result(fMocked)

fMocked.write("testare simpla")

fMocked.close()

controller.replay()

algoritm_complex(objOpen.open)

Asta e tot ce aveti nevoie. Daca functia ar fi returnat un rezultat puteati face un assert pe valoarea returnata doar ca sa va asigurati ca algoritmul a functionat asa cum ati dorit. Pentru mai multe informatii despre acest mod de testare, vizitati site-ul http://labix.org/mocker.

joi, 7 mai 2009

Python si metod statice

Tinand cont ca am fost nevoit sa invat Python la noul loc de munca, am descoperit cateva elemente care se implementeaza un pic mai ciudat decat in Java. Unul din aceste exemple ar fi metodele statice.

In Java, o metoda statica se implementeaza in felul urmator:

public static void helloWorld() { System.out.println("Salutari"); }

In python lucrurile sunt mai complicate si depinde si de versiune folosita. De exemplu, daca folosim o versiune de python anterioara 2.4 atunci vom defini o metoda statica in felul urmator:

def helloWorld(cls):
print("Salutari")

helloWorld = classmethod(helloWorld)

Daca folosim o versiune mai noua de python lucrurile se simplifica deoarece putem folosi un decorator.
@staticmethod
def helloWorld(cls):
print("Salutari")

In ambele cazuri lucrurile sunt mai putin lizibile decat in Java. Oricum, asta este modul de a defini/folosi functii/metode statice in Python.

marți, 21 aprilie 2009

Richfaces panelMenu

Richfaces reprezinta un framework bazat pe JSF extrem de puternic. Pune la dispozitie multe componente si in plus are ajax pentru toate aceste componente. In acest post voi arata cum se poate crea un meniu flotant.

Pasul 1: Se creaza o solutie eclipse de tip Dynamic Web Project versiunea 2.5 si se activeaza JSF 1.2. De asemenea,trebuie sa faceti disponibil framework-ul richfaces asa cum este descris la adresa: http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone/docs/devguide/en/html_single/index.html.

Pasul 2: Se creaza un fisier .jsp si se adauga urmatorul cod:

<%@page pageEncoding="UTF8" contentType="text/html; charset=ISO-8859-2" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j" %>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich" %>

<f:view>
<h:form>

<rich:panelmenu event="onclick" mode="ajax" width="300">
<rich:panelmenugroup label="Meniu test">
<rich:panelmenuitem label="Optiune 1" onclick="window.location.href='test.jsf';">
<rich:panelmenuitem label="Optiune 2" onclick="window.location.href='test.jsf';">
<rich:panelmenuitem label="Optiune 3" onclick="window.location.href='test.jsf';">
</rich:panelMenuGroup>
</rich:panelMenu>

</h:form>
</f:view>


Observatii:

In acest momentant ati obtinut un meniu flotant dar fara nici un fel de functionalitate alta decat fold. De cele mai multe ori veti avea nevoie sa faceti redirectare catre o alta pagina. Cel mai usor este sa folositi: onclick attribute si cod javascript pentru redirectionare. Acestea fiind lamurite ar mai fi de mentionat ce reprezinta: event="onclick" mode="ajax".
Onclick indica framework-ului richfaces sa genereze un meniu flotant care sa faca fold doar in momentul in care se executa click. O alta varianta ar putea fi onmouseover. A doua obtiune tine de modul in care se face submit. Modul predefinit este "server" ceea ce inseamna ca la fiecare click se va face refresh la pagina si se va reface arborele JSF. De asemenea, ca orice componenta din JSF se poate face bind pentru a se face legatura cu un backbean. Tipul de date este de forma: "HtmlPaneMenuXXXXX" unde xxx este: {"", "Group", "Item"}. Pachetul pentru acest tip de date este: org.richfaces.component.html. In acest pachet veti gasi majoritatea componentelor din RichFaces.

luni, 6 aprilie 2009

Configurare subversion + apache2 + ldap

In acest post, descriu cum se poate crea autentificarea pentru un repo de subversion utilizand mod_dav_svn si ldap. Inainte de a descrie in detaliu toti pasii voi presupune ca avem un repo virtual creat cu path-ul: /svn/repos/repo_virtual.

Pe parte de ldap, vom presupune ca avem urmatoarea structura:

dc=example,dc=com
ou=Groups,dc=example,dc=com
cn=group_svn_repo,ou=Groups,dc=example,dc=com
ou=Users,dc=example,dc=com
cn=user1,ou=Users,dc=example,dc=com
cn=user2,ou=Users,dc=example,dc=com

In mod normal asta e tot ce aveti nevoie inainte de configurare apache. Pe scurt, logica este sa facem autentificare pe nodul de users dupa care verificam daca utilizatorul este in grupul specificat. Aici se va descrie configurarea in virtual host, intrucat este cea mai raspandita.


ServerName svn1.example.com
ServerAdmin rcosnita@example.com
ErrorLog /var/log/apache2/error_svn.log
CustomLog /var/log/apache2/access_svn.log combined


DAV svn
SVNPath /svn/repos/repo_virtual/
SVNListParentPath on

AuthBasicProvider ldap

AuthType Basic
AuthName "Example server"
AuthzLDAPAuthoritative off

AuthLDAPURL ldap://svn1.example.com:389/OU=Users,DC=informatix,DC=ro?cn?sub
AuthLDAPBindDN CN=root,DC=example,DC=com
AuthLDAPBindPassword parolamea

AuthLDAPGroupAttribute member
AuthLDAPGroupAttributeIsDN on

Require group cn=group_svn_repo,ou=Groups,dc=informatix,dc=ro



Asta e tot ce trebuie sa faceti. Dupa ce ati terminat dati un restart la serverul de apache si totul ar trebui sa functioneze.

Este important sa tineti minte ca serverul apache face cache in momentul in care se conecteaza la ldap. Asta inseamna ca orice intrare care se adauga in ldap dupa ce apache este conectat nu va fi vazuta pana la restart-ul unuia dintre servere.

Dintr-un motiv care inca mi-e neclar, cand am folosit apache + openldap solutia de mai sus nu a functionat. Din acest motiv, am "trisat" si am adaugat fiecarui utilizator un atribut din schema ldap care sa semnifice grupul. In cazul meu acest atribut a fost labeledURI.

Dupa aceasta am inlocuit: Require group cn=group_svn_repo,ou=Groups,dc=informatix,dc=ro
cu: Require ldap-attribute labeledURI=cn=group_svn_repo,ou=Groups,dc=informatix,dc=ro.

Dupa aceasta modificare totul a functionat fara probleme.

Sper sa gasiti acest post interesant.
Cosnita Radu Viorel!

luni, 9 martie 2009

Configurare Apache2 si Tomcat 6 prin mod_proxy

Această variantă de conectare a celor două servere este una extrem de utilă întrucât folosește doar componente standard fără să fie nevoie să instalați mod_jk. De asemenea, puteți folosi url_rewriting din apache. Acest articol va prezenta in câțiva pași simpli modul în care se poate realiza acest lucru.

1. Configurăm un virtual host în apache

ServerAdmin admin@domeniumeu.ro
ServerName www.domeniumeu.ro
DocumentRoot /calea/catre/site

        
           ProxyRequests off
           ProxyPass / http://server:8081/domeniumeu.ro/
           ProxyPassReverse / http://server:8081/domeniumeu.ro/        

În principiu, în acest moment trebuie doar să restartați serverul de apache și totul este ok. Remarcați faptul că apare portul 8081 în loc de 8080. Acest lucru este datorat faptului că se activează un listener de tomcat pe acel port. Acest lucru este descris în pasul următor al tutorialului. Pe scurt, ceea ce am făcut în acest pas a fost să indicăm serverului web apache să trimită toate requesturile pentru domeniul www.domeniumeu.ro către tomcat.

2. Configurăm un listener în tomcat

      proxyName="www.domeniumeu.ro" 
      proxyPort="80" />

Această configurare se află în secțiunea de din cadrul fișierului $CATALINA_HOME/conf/server.xml. În acest moment tot ce aveți de făcut este să restartați server-ul de tomcat și să accesați din browser: www.domeniumeu.ro. După cum se poate observa, este mult mai ușor să configurați apache 2 + tomcat cu mod_proxy decât prin mod_jk. Singura problema ar fi că prin această metodă se deschid mai multe porturi(câte un port pentru fiecare site găzduit). Această problemă se rezolvă relativ simplu, prin blocare portului din firewall. Este recomandat să procedăm așa întrucât apache-ul va putea să acceseze tomcat-ul întrucât va trimite  un request local.

Sper că acest articol vi se pare interesant,
Coșniță Radu Viorel!

joi, 22 ianuarie 2009

Configurare birt in mediul virtual hosts

In acest post descriu modul in care se poate seta birt-viewer sa functioneze pentru mai multe site-uri gazduite pe acelasi server. Acest lucru este util intrucat administratorul poate administra o singura instanta de birt, si poate face upgrade mult mai usor la mediul de rapoarte. Primul pas ar fi sa instalam runtime-ul pentru birt care poate fi downloadat de pe site-ul: http://download.eclipse.org/birt/downloads/. Dupa ce extragem arhiva downloadata se copiaza folder-ul birt-viewer in $CATALINA_HOME/webapps. In acest moment se poate testa runtime-ul la adresa: http://localhost:8080/birt-viewer. Pentru a putea folosi acest runtime pentru mai multe host-uri virtuale cel mai usor este sa creeam in $CATALINA_HOME/conf/Catalina/<> context.xml.default. Aici se adauga o intrare context asemanatoare cu cea de mai jos:

In acest moment puteti folosi acest context. Asta e tot ce aveti de facut. Intr-un post viitor voi arata cum se pot creea virtual host-uri pentru tomcat.

Cosnita Radu Viorel!