This blog is no longer being maintained, please go to The missing link of Agile instead

Friday, May 02, 2008

Blog - reaktywacja

Ostatni post ukazał się w listopadzie zeszłego roku, tak więc trudno mówić o jakiejkolwiek ciągłości :P Tamten okres był jednak stosunkowo pracowity, więc mam nadzieję że kilka miesięcy po jego zakończeniu będę w stanie "zmusić się" do regularnego pisania :) Co więcej odkryłem w tym czasie, że ostatnio zaprezentowany pomysł okazał się reifikacją (hehe Holub rox ;) ) wzorca projektowego State (z domieszką Special Case'a).

A co natchnęło mnie do powrotu na bloga - otóż znalazłem buga w Javie :), a dokładniej w implementacji introspekcji (java.beans.*). Na problem natknąłem się rozwijając aplikację webową, co tylko utrudniło wyodrębnienie go, ale w końcu się udało ! Na początek trochę kodu:

public interface ITest<T> {
public T getDelta();
}

public class Foo implements ITest<String> {
private List<String> alfa;
private String beta;
private String gamma;

public List<String> getAlfa() {
return alfa;
}

public void setAlfa(final List<String> alfa) {
this.alfa = alfa;
}

public String getBeta() {
return beta;
}

public void setBeta(final String beta) {
this.beta = beta;
}

public String getDelta() {
return gamma;
}

public void setDelta(final String gamma) {
this.gamma = gamma;
}
}

public class Bar implements ITest<String> {
private List<String> alfa;
private String beta;
private String gamma;

public List<String> getAlfa() {
return alfa;
}

public void setAlfa(final List<String> alfa) {
this.alfa = alfa;
}

public String getGamma() {
return gamma;
}

public void setGamma(final String gamma) {
this.gamma = gamma;
}

public String getBeta() {
return beta;
}

public void setBeta(final String beta) {
this.beta = beta;
}

public String getDelta() {
return gamma;
}

public void setDelta(String gamma) {
this.gamma = gamma;
}
}


I najważniejsza część - kod testujący. Pobiera deskryptory pól dla każdej z klas, a następnie wypisuje metody zapisu dla poszczególnych deskryptorów. Mowiąc prościej kod wyświetla settery zgodne ze specyfikacją JavaBeans (jeśli nie ma - wypisze 'null'):

Dla ułatwienia będę podawał wartości tylko dla property: "delta".

Po wywołaniu kodu powyżej otrzymamy wynik:

"delta null" (dla Foo)
"delta null" (dla Bar)

Po zamianie wywołań dostaniemy:

"delta public void pl.test.Bar.setDelta(java.lang.String)"
"delta null"

Po zakomentowaniu części "Dla Foo" wynik będzie:

"delta public void pl.test.Bar.setDelta(java.lang.String)"

Natomiast po zakomentowaniu części "Dla Bar" na konsoli pojawi się znowu:

"delta null"

Szczerze mówiąc powyższe wyniki są dla mnie kompletnie niedeterministyczne ;D. Mogę jedynie domniemywać, że ma to jakiś związek z typami generycznymi i cache'owaniem przy introspekcji. Strzelałbym nawet, że w tym przypadku łączy się więcej niż jeden bug, stąd dość "ciekawe" rezultaty". Biorąc nawet pod uwagę, że są znane problemy na styku JavaBeans i generyków1 powyższe wyniki wydają się definitywnie zbyt "pseudo-losowe" ;).

Wszystko będzie ok jeśli:
  • zarówno 'getter' i 'setter' jest generyczny i dziedziczony,
  • i co ciekawe ... 'setter' jest generyczny i dziedziczony
Potencjalny work-around - unikać rozwiązania jak powyżej :P.

1. Warto popatrzeć na następujące zgłoszenia:
http://bugs.sun.com/view_bug.do?bug_id=6422403
http://bugs.sun.com/view_bug.do?bug_id=6473468
http://bugs.sun.com/view_bug.do?bug_id=5098163

No comments:

Post a Comment