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:
Uruchamianie powyższych bez prefiksu nazwy grupy i pełnej nazwy pluginu - dopisać do settings.xml:
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):
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.
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
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
Jakub Woźniakowski
Etykiety:
Spring
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:
- URI templates - wsparcie dla REFTful URLs typu /owners/{ownerId}/pets/{petId}
- Content negotiation - ContentNegotiatingViewResolver -> delegacja obsługi widoków do dedykowanego Resolver'a w zależności od rozszerzenia pliku w URI lub nagłówka Accept: HTML, ATOM, RSS, PDF, XML, etc.
- HTTP method conversion - wsparcie dla GET, PUT, POST, DELETE
- ETag - obsługa ETag headers czyli jak graniczyć ruch w sieci za pomocą jednego filtra
- RestTemplate - wsparcie wywołań usług RESTful po stronie klienta
Jakub Woźniakowski
Etykiety:
Spring
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:
Kod tagu /WEB-INF/tags/widgets/tree.tag:
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}:
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:
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;
}
Jakub Woźniakowski
Etykiety:
JSP