The only valid measurement of code quality

12 lutego 2010 | 0 komentarze


http://www.osnews.com/story/19266/WTFs_m

Tag Library Documentation Generator + Maven

25 listopada 2009 | 0 komentarze

Kolejne narzędzie ułatwiające pracę, a właściwie dwa.

Tag Library Documentation Generator potrafi tworzyć javadoc'a bibliotek tagów JSP na podstawie opisów zawartych w plikach .tld i .tag. Obsługuje tagi JSP 1.2 do 2.1 i JSF.


Na dokładkę plugin do Mavena który generuje dokumentację taglibs automatycznie (korzysta z wymienionego wyżej narzędzia) i załącza do strony projektu - maven-taglib-plugin. Wystarczy wpisać do pom.xml:
<reporting>   <plugins>     <plugin>       <groupId>net.sourceforge.maven-taglib</groupId>       <artifactId>maven-taglib-plugin</artifactId>     </plugin>   </plugins> </reporting>
Plugin udostępnia cele (goals):
Uruchamianie powyższych bez prefiksu nazwy grupy i pełnej nazwy pluginu - dopisać do settings.xml:
<settings>   ...  <pluginGroups>   <pluginGroup>net.sourceforge.maven-taglib</pluginGroup>  </pluginGroups>   ... </settings>
Linki:

Cykliczne zależności komponentów w Spring'u

31 października 2009 | 1 komentarze

Cykliczna zależność to sytuacja w której komponent A jest zależny od komponentu B i jednocześnie B jest zależny od A. W przypadku kontenera Spring IoC wzajemna zależność jest wykrywana i zgłaszana w postaci wyjątku BeanCreationException podczas startu aplikacji. Aplikacja oczywiście nie wstaje.

Przykładowy konfig Spring'a z cykliczną zależnością (/WEB-INF/application-context.xml):

<bean id="userService" class="pl.codeservice.service.UserService" >
 <property name="studioService" ref="studioService" />
</bean>

<bean id="studioService" class="pl.codeservice.service.StudioService" >
 <property name="userService" ref="userService" />
</bean>

Zalecane jest pozbycie się cykliczności jako złej praktyki bo:
-zwiększa stopień skomplikowania konfiguracji (OOP principles: loose coupling)
-powoduje problemy architektoniczne: który komponent ma być zniszczony jako pierwszy, istnienie częsciowo zainicjowanych ziaren, itd.
-powiązane komponenty muszą być dystrybuowane w tym samym module/JARze
-trudniej testować
-itd.

O ile generalnie zgadzam sie z powyższym, bywają sytuacje awaryjne kiedy nie ma innego wyjścia. Nie ma czasu i pieniędzy na zmianę architektury a kopiowanie kodu nigdy nie jest dobrym pomysłem.

Rozwiązaniem jest implementacja interfejsu BeanPostProcessor przez jeden z komponentów i przechwycenie referencji do zależnego bean'a w metodzie postProcessAfterInitialization(). Trzeba pamiętać o zwróceniu w obu metodach instancji przekazanego w argumencie ziarna.


public class StudioService implements BeanPostProcessor {
 
  private UserService userService;
  //...
 
  public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
   if("userService".equals(name)){
    userService = (UserService)bean;
   }
   return bean;
  }
 
  public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
   return bean;
  }
}


Jeśli komponent będzie występował jako cross-reference więcej niż raz warto napisać, skonfigurować i używać w jego miejsce proxy - obejście zawsze będzie tylko w jednym miejscu.

Linki:
-Spring Dynamic Modules Reference Guide, 5.3.1. Listener and cyclic dependencies
-The Spring Framework - Reference Documentation, 3.7. Container extension points
-architecturerules.org

Prezentacja: Implementing REST Web Application Architectures

17 września 2009 | 0 komentarze

Na InfoQ pojawiła się prezentacja by Arjen Poutsma zarejestrowana podczas springOne dotycząca obsługi REST w nowym Springu 3.0. Jeśli ominęło was kwietniowe spotkanie organizowane przez warszawski JUG i SpringSource warto poświęcić godzinę i obejrzeć materiał (video + slajdy). Tematem przewodnim jest wsparcie dla RESTful URLs w Spring MVC:
Link do prezentacji: http://www.infoq.com/presentations/rest-web-application-architectures

Kontrolka Drzewka w Tagu JSP

31 sierpnia 2009 | 0 komentarze

Począwszy od JSP 2.0 do dyspozycji programistów dostępne są tagi użytkownika. Tagi posiadają kilka nowych, bardzo ważnych funkcjonalności, których brakowało w starym JSP. Wśród nich są możliwość przekazania referencji obiektów jako atrybuty (nie przez kontekst) i wykonywanie przekazanych w atrybutach fragmentów (fragments).


Napisanie rozsądnej kontrolki drzewka w HTML'u w tagu JSP nie jest banalne ze względu na rekurencję - podstawowym założeniem jest brak ograniczenia liczby poziomów. Dla uproszczenia kodu nie będzie możliwości rozwijania i zwijania gałęzi. Po stronie przeglądarki wykorzystam elementy listy <ul> i <li>. Wnętrze elementu listy będzie przekazywane jako fragment, co umożliwi wykonanie dowolnego zdarzenia javascript lub podpięcie linka w zależności od sposobu wykorzystania drzewka. Model to zwykły POJO:

package pl.publicmethods.model;

public class Group {

private Set<Group> children;

public Set<Group> getChildren() {
return children;
}
public void setChildren(Set<Group> children) {
this.children = children;
}
}


Kod tagu /WEB-INF/tags/widgets/tree.tag:

<%@ tag display-name="" description="" import="pl.publicmethods.model.*"%>
<%@ attribute name="groups" required="true" type="java.util.Collection" %>
<%@ attribute name="level" required="false" type="java.lang.Integer" %>
<%@ attribute name="name" required="true" fragment="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="w" tagdir="/WEB-INF/tags/widgets"%>

<c:if test="${empty level}">
<c:set value="0" var="level" />
</c:if>

<c:if test="${level eq 0}">
<c:set value="class=\"tree\"" var="ulclass" />
</c:if>

<ul ${ulclass}>
<%
for(Object o : groups){
Group group = (Group)o;
request.setAttribute("group",group);
%>
<li>
<jsp:invoke fragment="name"/>
</li>
<w:tree groups="${group.children}" level="${level+1}" name="${name}" />
<%
}
%>
</ul>

Konkretny przypadek użycia na stronie JSP - atrybut name zawiera fragment który zostanie wykonany i wyświetlony dla każdego elementu w kolekcji ${groups}:

<w:tree groups="${groups}">
<jsp:attribute name="name">
<c:url value="/groupform.do?id=${group.id}" var="url" />
<a href="${url}">
<c:out value="${group.name}" />
</a>
</jsp:attribute>
</w:tree>

Czy można przekazać fragment JSP rekurencyjnie w postaci atrybutu? Okazuje się że można. Tag zawiera pętlę rekurencyjną w formie Scriptletu. Alternatywnie można ją napisać w JSTL, pamiętając o przekazaniu zmiennej group do zakresu request - musi być widoczna dla fragmentu.

Atrybut level to nic innego jak piętro drzewka - na zerowym element <ul> dostaje oddzielną klasę stylu. Łatwo można wprowadzić sprawdzanie zapętlonych powiązań - wystarczy wstawić warunek dla level < 1000.

I jeszcze style CSS:

ul.tree {
margin: 0;
padding: 0;
background-color: #f8f8f8;
border-top: 1px solid #888;
border-bottom: 1px solid #444;
}
ul.tree ul {
padding: 0;
margin: 0;
margin-left: 24px;
}
ul.tree li {
list-style-type: none;
border-bottom: 1px dotted #888;
padding: 4px;
}
ul.tree li:hover {
background-color: #f0f0f0;
}