<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mocna Kawa &#187; facelets</title>
	<atom:link href="http://blog.mocna-kawa.com/category/facelets/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mocna-kawa.com</link>
	<description>radosny blog o nowych technologiach</description>
	<lastBuildDate>Tue, 24 Aug 2010 08:47:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Integracja JSF + Facelets + Spring + JPA + Tomahawk</title>
		<link>http://blog.mocna-kawa.com/2007/08/integracja-jsf-facelets-spring-jpa-tomahawk/</link>
		<comments>http://blog.mocna-kawa.com/2007/08/integracja-jsf-facelets-spring-jpa-tomahawk/#comments</comments>
		<pubDate>Sun, 05 Aug 2007 12:40:52 +0000</pubDate>
		<dc:creator>wiktor</dc:creator>
				<category><![CDATA[facelets]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[jsf]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://blog.mocna-kawa.com/2007/08/05/integracja-jsf-facelets-spring-jpa-tomahawk/</guid>
		<description><![CDATA[Dość sporo tych Trzy Literowych Skrótów  . Wszystkie wymienione technologie zostaną połączone w prostej aplikacji typu CRUD.
W tym artykule pokaże jak zintegrować następujące technologie:

JavaServer Faces 1.1 &#8211; będę wykorzystywał implementację Apache MyFaces &#8211; jako warstwa prezentacji,
Facelets &#8211; są one wspaniałym kompanem dla JSF, będę korzystał tylko z szablonów, choć Facelets mają dużo więcej możliwości,
Spring [...]]]></description>
			<content:encoded><![CDATA[<p>Dość sporo tych <b>T</b>rzy <b>L</b>iterowych <b>S</b>krótów <img src='http://blog.mocna-kawa.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Wszystkie wymienione technologie zostaną połączone w <b>prostej aplikacji typu CRUD</b>.</p>
<p>W tym artykule pokaże jak zintegrować następujące technologie:</p>
<ul>
<li><em>JavaServer Faces 1.1</em> &#8211; będę wykorzystywał implementację Apache MyFaces &#8211; jako warstwa prezentacji,</li>
<li><em>Facelets</em> &#8211; są one wspaniałym kompanem dla JSF, będę korzystał tylko z szablonów, choć Facelets mają dużo więcej możliwości,</li>
<li><em>Spring 2</em> &#8211; kontener IoC, będzie on wstrzykiwał beany obsługujące encje JPA (czyli DAO) do JSF (cudowna integracja) oraz obsługiwał transakcje,</li>
<li><em>Java Persistence API</em> &#8211; implementacja Toplink &#8211; będę wykorzystywał JPA do mapowania obiektowo-relacyjnego,</li>
<li><em>Tomahawk</em> &#8211; zestaw komponentów JSF ze stajni Apache.</li>
</ul>
<p>Do artykułu dołączony jest kod źródłowy całej aplikacji. Można go otworzyć od razu w <em>IntelliJ IDEA</em>, a jeśli używasz innego edytora to musisz jakoś zaimportować projekt <img src='http://blog.mocna-kawa.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Możesz także przejrzeć pełen kod w subversion pod adresem: <a href="http://svn.mocna-kawa.com/jsfcrud/">http://svn.mocna-kawa.com/jsfcrud/</a>.</p>
<p><span id="more-27"></span></p>
<p>Zacznijmy od przygotowania modelu. Mamy tylko jedną relację jeden do wielu. Jedna osoba może mieć przypisanych wiele ról. Zatem użytkownik wygląda następująco:<br />
[java]<br />
@NamedQueries({<br />
@NamedQuery(name = &#8220;findAllUsers&#8221;, query = &#8220;SELECT user FROM User user&#8221;),<br />
@NamedQuery(name = &#8220;findUserByLogin&#8221;, query = &#8220;SELECT user FROM User user WHERE user.login = ?1&#8243;)<br />
        })<br />
@Entity<br />
public class User {<br />
    @Id<br />
    @GeneratedValue(strategy = GenerationType.AUTO)<br />
    private Integer id;</p>
<p>    private String login;<br />
    private String password;</p>
<p>    @OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.EAGER)<br />
    private List<role> roles;</p>
<p>    // gettery i settery dla id, login i password.</p>
<p>    // przesłonienie metod hashCode() i equals()</p>
<p>    // taka mała sztuczka, bez której t:selectManyCheckbox nie chce działać (opakowanie w tablicę)<br />
    public Role[] getRolesAsArray() {<br />
        return roles == null ? null : roles.toArray(new Role[0]);<br />
    }</p>
<p>    public void setRolesAsArray(Role[] roles) {<br />
        // błąd Toplinka: https://glassfish.dev.java.net/issues/show_bug.cgi?id=556<br />
        this.roles = new ArrayList(Arrays.asList(roles));<br />
    }<br />
}<br />
[/java]</p>
<p>Natomiast rola jest również prosta i jest następująca:</p>
<p>[java]<br />
@NamedQueries({<br />
@NamedQuery(name = &#8220;findAllRoles&#8221;, query = &#8220;SELECT role FROM Role role&#8221;),<br />
@NamedQuery(name = &#8220;findRoleByRoleName&#8221;, query = &#8220;SELECT role FROM Role role WHERE role.roleName = ?1&#8243;)<br />
        })<br />
@Entity<br />
public class Role {</p>
<p>    @Id<br />
    @GeneratedValue(strategy = GenerationType.AUTO)<br />
    private Integer id;</p>
<p>    private String roleName;</p>
<p>    // gettery i settery</p>
<p>    // przesłonięcie hashCode() i equals()<br />
}<br />
[/java]</p>
<p>Dobrą praktyką jest używanie nazwanych zapytań. W JPA zapisuje się je za pomocą adnotacji <code>@NamedQueries</code> i odpowiednio <code>@NamedQuery</code>.</p>
<p>Teraz zdefiniujmy interfejs do komunikacji między aplikacją a źródłem danych (czyli <a href="http://pl.wikipedia.org/wiki/Data_Access_Object">DAO</a>).<br />
[java]<br />
public interface UserDao {<br />
    public List<user> findAll();<br />
    public User findById(Integer id);<br />
    public User findByLogin(String login);<br />
    public void save(User user);<br />
    public void delete(User user);<br />
}</p>
<p>public interface RoleDao {<br />
    public List<role> findAll();<br />
    public Role findById(Integer id);<br />
    public Role findByRoleName(String roleName);<br />
    public void save(Role role);<br />
    public void delete(Role role);<br />
}<br />
[/java]</p>
<p>Teraz implementacja powyższych interfejsów. Będą one dziedziczyć po <code>JpaDaoSupport</code>, która to klasa dostarczona przez Springa zajmuje się komunikacją z <code>EntityManagerem</code> i pozwala na tzw. &#8220;jedno-linijkowce&#8221; (ang. one-liner).</p>
<p>[java]<br />
public class JpaUserDao extends JpaDaoSupport implements UserDao {</p>
<p>    public User findByLogin(String login) {<br />
        List<user> users = getJpaTemplate().findByNamedQuery(&#8220;findUserByLogin&#8221;, login);<br />
        if (users.size() > 1) {<br />
            throw new DataIntegrityViolationException(&#8220;More than one user with the same login.&#8221;);<br />
        }<br />
        return users.size() == 0 ? null : users.get(0);<br />
    }</p>
<p>    public List<user> findAll() {<br />
        return getJpaTemplate().findByNamedQuery(&#8220;findAllUsers&#8221;);<br />
    }</p>
<p>    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)<br />
    public void save(User user) {<br />
        getJpaTemplate().merge(user);<br />
    }</p>
<p>    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)<br />
    public void delete(User user) {<br />
        getJpaTemplate().remove(getJpaTemplate().merge(user));<br />
    }</p>
<p>    public User findById(Integer id) {<br />
        return getJpaTemplate().find(User.class, id);<br />
    }</p>
<p>}</p>
<p>public class JpaRoleDao extends JpaDaoSupport implements RoleDao {<br />
    // implementację można znaleźć w repozytorium lub w załączonym kodzie źródłowym<br />
}<br />
[/java]</p>
<p>Jak widać z powyższego kodu, transakcje są deklarowane w adnotacjach, co czyni je dość przyjemnymi. Teraz trochę konfiguracji: persistence.xml dla JPA oraz applicationContext.xml dla Springa. Beany Springowe będą widoczne w kontekście JSF i będzie można je także używać w stronach JSF.</p>
<p>[xml]<br />
<!-- Deklaracja beana do obsługi użytkowników --><br />
<bean id="userDao" class="com.mocnakawa.jsfcrud.data.dao.jpa.JpaUserDao"></p>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean></p>
<p><!-- Deklaracja beana do obsługi ról --><br />
<bean id="roleDao" class="com.mocnakawa.jsfcrud.data.dao.jpa.JpaRoleDao"></p>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean></p>
<p><!-- Deklaracja EntityManagera, Spring domyślnie szuka pliku META-INF/persistence.xml i z niego bierze dane --><br />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"></p>
<property name="persistenceUnitName" value="JsfCrudUnit"/>
</bean></p>
<p><!-- Do obsługi transakcji --><br />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"></p>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean></p>
<p><!-- Transakcje będą deklarowane przez adnotacje --><br />
<tx:annotation-driven transaction-manager="transactionManager"/><br />
[/xml]</p>
<p>Zauważmy, że poprzez zastosowanie kontenera wstrzyknięć nie jesteśmy związani z JPA. Interfejs DAO jest niezależny od zastsowanej technologii ORM. Bez problemu moglibyśmy podmienić JPA na Hibernate&#8217;a lub iBatis. Teraz persistence.xml.</p>
<p>[xml]</p>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="JsfCrudUnit" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<p>        <class>com.mocnakawa.jsfcrud.data.domain.Role</class><br />
        <class>com.mocnakawa.jsfcrud.data.domain.User</class></p>
<properties>
<property name="toplink.logging.level" value="OFF"/>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost/jsfcrud"/>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="toplink.jdbc.user" value="root"/>
<property name="toplink.jdbc.password" value="Twoje Hasło"/>
<property name="toplink.ddl-generation" value="create-tables"/>
        </properties>
    </persistence-unit>
</persistence>
[/xml]</p>
<p>Teraz już możemy przejść do warstwy prezentacji, czyli czas na JSF. Czas na to, co tygryski lubią najbardziej, czyli od kontrolera (a dokładnie managed beana JSF).</p>
<p>[java]<br />
// Klasa typowa dla akcji typu CRUD<br />
// Jest to dość proste, więc mam nadzieje, że kod się sam dokumentuje<br />
public class UserController {</p>
<p>    // wstrzykniete przez Springa<br />
    private UserDao userDao;</p>
<p>    private User user;<br />
    private boolean editMode = false;</p>
<p>    public List<user> getUsers() {<br />
        return userDao.findAll();<br />
    }</p>
<p>    public void editSetup(ActionEvent event) {<br />
        user = FacesUtils.getActionAttribute(event, &#8220;user&#8221;, User.class);<br />
        editMode = true;<br />
    }</p>
<p>    public String update() {<br />
        userDao.save(user);<br />
        return Constants.USER_AND_ROLE_LIST;<br />
    }</p>
<p>    public String createSetup() {<br />
        user = new User();<br />
        editMode = false;<br />
        return Constants.USER_FORM;<br />
    }</p>
<p>    public String create() {<br />
        User userToCreate = userDao.findByLogin(user.getLogin());<br />
        if (userToCreate == null) {<br />
            userDao.save(user);<br />
            return Constants.USER_AND_ROLE_LIST;<br />
        } else {<br />
            FacesUtils.addErrorMessage(&#8220;Login already exists&#8221;);<br />
            return null;<br />
        }<br />
    }</p>
<p>    public void delete(ActionEvent event) {<br />
        userDao.delete(FacesUtils.getActionAttribute(event, &#8220;user&#8221;, User.class));<br />
    }</p>
<p>    // gettery i settery<br />
}<br />
[/java]</p>
<p>Kontrolera dla ról celowo pominąłem, można go znaleźć w załączonym kodzie źródłowym. Pora na web.xml.</p>
<p>[xml]<br />
 <!-- Listner dla Springa --></p>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<p><!-- Konfiguracja Facelets --><br />
<context-param></p>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>2</param-value>
</context-param></p>
<p><context-param></p>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param></p>
<p><context-param></p>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param></p>
<p> <!-- Konfiguracja Springa --><br />
<context-param></p>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param></p>
<p><filter><br />
    <filter-name>RequestContextFilter</filter-name><br />
    <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class><br />
</filter></p>
<p><filter-mapping><br />
    <filter-name>RequestContextFilter</filter-name><br />
    <url-pattern>*.jsf</url-pattern><br />
</filter-mapping></p>
<p> <!-- Konfiguracja kontrolera JSF --><br />
<servlet><br />
    <servlet-name>Faces Servlet</servlet-name><br />
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class><br />
    <load-on-startup>1</load-on-startup><br />
</servlet></p>
<p><servlet-mapping><br />
    <servlet-name>Faces Servlet</servlet-name><br />
    <url-pattern>*.jsf</url-pattern><br />
</servlet-mapping><br />
[/xml]</p>
<p>Należy nie zapominać, aby podpiąć Springa. Parametr <code>facelets.DEVELOPMENT</code> w Facelets jest bardzo użytecznym podczas pisania aplikacji. Prezentuje on błędy występujące w bindingach JSF lub o rzucanych wyjątkach w bardzo przystępny sposób.</p>
<p>Czas na zaprezentowanie potęgi <b>Facelets</b>. Zadeklarujmy szablon dla naszych stron:<br />
[xml]<br />
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"<br />
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br />
<html xmlns="http://www.w3.org/1999/xhtml"<br />
      xmlns:h="http://java.sun.com/jsf/html"<br />
      xmlns:f="http://java.sun.com/jsf/core"<br />
      xmlns:ui="http://java.sun.com/jsf/facelets"></p>
<p><head><br />
    <title><br />
        <ui:insert name="title">Default title</ui:insert><br />
    </title><br />
</head><br />
<body></p>
<h1>
    <ui:insert name="title">Default title</ui:insert><br />
</h1>
<p><ui:insert name="content"/><br />
<ui:include src="footer.xhtml"/></p>
<p></body><br />
</html><br />
[/xml]</p>
<p>Tak <code>ui:include</code> oraz <code>ui:insert</code> są raczej zrozumiałe. Szablony Facelets są tak bardzo proste, jak powinny być właśnie. Są dużo bardziej przyjazne od Tilesów. Czas na wypisanie wszystkich użytkowników.</p>
<p>[xml]<br />
<!-- Wskazanie szablonu, z którego będziemy korzystać --><br />
<ui:composition template="/pages/layout.xhtml"></p>
<p>    <!-- definiowanie tytułu, który będzie później wstawiony za pomocą ui:insert --><br />
    <ui:define name="title">Users CRUD</ui:define></p>
<p>    <!-- definiowanie zawartości strony --><br />
    <ui:define name="content"><br />
        <h:form><br />
            <h:dataTable value="#{userController.users}" var="user"><br />
                <h:column><br />
                    <f:facet name="header">Login</f:facet><br />
                    #{user.login}<br />
                </h:column><br />
                <h:column><br />
                    <f:facet name="header">Password</f:facet><br />
                    #{user.password}<br />
                </h:column><br />
                <h:column><br />
                    <f:facet name="header">Roles</f:facet></p>
<ul style="margin: 0">
<p>                        <!-- prosta pętla w JSF - co zawsze było trudne do osiągnięcia przy JSTL --></p>
<p>                        <ui:repeat value="#{user.roles}" var="role"></p>
<li>#{role.roleName}</li>
<p>                        </ui:repeat>
                    </ul>
<p>                </h:column><br />
                <h:column><br />
                    <f:facet name="header">Edit</f:facet><br />
                    <h:commandLink action="userForm" actionListener="#{userController.editSetup}" value="edit"><br />
                        <f:attribute name="user" value="#{user}"/><br />
                    </h:commandLink><br />
                </h:column><br />
                <h:column><br />
                    <f:facet name="header">Remove</f:facet><br />
                    <h:commandLink actionListener="#{userController.delete}" value="remove"><br />
                        <f:attribute name="user" value="#{user}"/><br />
                    </h:commandLink><br />
                </h:column><br />
            </h:dataTable></p>
<p>            <h:commandLink action="#{userController.createSetup}" value="Add new user"/><br />
        </h:form><br />
    </ui:define><br />
</ui:composition><br />
[/xml]</p>
<p>Zauważcie, że Facelets nie wymusza używanie h:outputText. Można po prostu napisać #{bean.tekst}. Teraz formularz dla użytkownika. Jest on wspólny zarówno dla edycji jak i dla dodawania nowego użytkownika. Ich rozróżnienie następuje po wartości zmiennej <code>editMode</code> w <code>UserController</code>.</p>
<p>Przyjrzyjmy się teraz, jak wygląda edytowanie/dodawanie użytkownika. Żeby łatwo użytkownikowi przypisywać role (relacja jeden do wielu), będę używał komponenty <code>t:selectManyCheckbox</code> oraz <code>t:selectItems</code> z biblioteki Tomahawk. <code>t:selectItems</code> pozwala na uprzyjemnienie życia programiście, nie trzeba budować samemu w managed beanie tablicy obiektów SelectItem. Robi on na podstawie dowolnej kolekcji za nas. Warunkiem użycia <code>t:selectManyCheckbox</code> jest dostarczenie konwertera JSF dla klasy <code>Role</code>. Dlaczego? Jest to związane z cyklem życia JSF i zapisaniem/odbudowaniem modelu strony. Dlatego JSF potrzebuje konwertera, który przekonwertuje obiekt klasy <code>Role</code> do <code>Stringa</code> i vice versa.</p>
<p>[xml]<br />
<ui:composition template="/pages/layout.xhtml"><br />
    <ui:define name="title"><br />
        <h:outputText value="new user" rendered="#{!userController.editMode}"/><br />
        <h:outputText value="edit user" rendered="#{userController.editMode}"/><br />
    </ui:define><br />
    <ui:define name="content"><br />
        <h:messages styleClass="errorMsg"/><br />
        <h:form id="userForm"></p>
<table width="100%">
<tr>
<td style="font-size: 12px;" width="120px">login:</td>
<td align="left" width="200px">
                        <h:inputText id="login-user" style="width:100%;"<br />
                                     value="#{userController.user.login}"<br />
                                     required="true"/>
                    </td>
<td><h:message for="login-user" styleClass="errorMsg"/></td>
</tr>
<tr>
<td style="font-size: 12px;" width="120px">password:</td>
<td align="left" width="200px">
                        <h:inputSecret id="login-pass" style="width:100%;"<br />
                                       value="#{userController.user.password}"<br />
                                       required="true" redisplay="true"/>
                    </td>
<td><h:message for="login-pass" styleClass="errorMsg"/></td>
</tr>
<tr>
<td>Roles</td>
<td>
                        <t:selectManyCheckbox id="roles" layout="pageDirection"<br />
                                              value="#{userController.user.rolesAsArray}"><br />
                            <t:selectItems value="#{roleController.roles}" var="role" itemLabel="#{role.roleName}"<br />
                                           itemValue="#{role}"/><br />
                        </t:selectManyCheckbox>
                    </td>
<td><h:message for="roles" styleClass="errorMsg"/></td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="right" style="padding-top: 1em;">
                        <h:commandButton value="Add new user" action="#{userController.create}"<br />
                            rendered="#{!userController.editMode}"/><br />
                        <h:commandButton value="Save changes" action="#{userController.update}"<br />
                            rendered="#{userController.editMode}"/>
                    </td>
<td>&nbsp;</td>
</tr>
</table>
<p>        </h:form><br />
    </ui:define><br />
</ui:composition><br />
[/xml]</p>
<p>Teraz jeszcze prosty konwerter:</p>
<p>[java]<br />
public class RoleConverter implements Converter {</p>
<p>    public Object getAsObject(FacesContext facesContext, UIComponent arg1, String stringId) throws ConverterException {<br />
        if (stringId == null)<br />
            return null;</p>
<p>        RoleDao roleDao = (RoleDao) facesContext.getApplication().getVariableResolver().resolveVariable(facesContext, &#8220;roleDao&#8221;);</p>
<p>        return roleDao.findById(Integer.valueOf(stringId));<br />
    }</p>
<p>    public String getAsString(FacesContext arg0, UIComponent arg1, Object object) throws ConverterException {<br />
        if (object == null)<br />
            return null;</p>
<p>        if (object instanceof Role) {<br />
            Role o = (Role) object;<br />
            return &#8220;&#8221; + o.getId();<br />
        } else {<br />
            throw new IllegalArgumentException(&#8220;object:&#8221; + object + &#8221; of type:&#8221; + object.getClass().getName() + &#8220;; expected type: Role&#8221;);<br />
        }<br />
    }</p>
<p>}<br />
[/java]</p>
<p>Teraz czas na ostatnie posunięcie, czyli podłączenie Springa, Facelets do JSF <img src='http://blog.mocna-kawa.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>[xml]<br />
<faces-config><br />
    <application><br />
        <!-- Podłączenie Facelets --><br />
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler></p>
<p>        <!-- Podłączenie Springa --><br />
        <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver><br />
    </application></p>
<p>    <!-- Deklaracja konwertera --><br />
    <converter><br />
        <converter-for-class>com.mocnakawa.jsfcrud.data.domain.Role</converter-for-class><br />
        <converter-class>com.mocnakawa.jsfcrud.web.RoleConverter</converter-class><br />
    </converter></p>
<p>    <!-- Deklaracja naszego kontrolera --><br />
    <managed-bean><br />
        <managed-bean-name>userController</managed-bean-name><br />
        <managed-bean-class>com.mocnakawa.jsfcrud.web.controller.UserController</managed-bean-class><br />
        <managed-bean-scope>session</managed-bean-scope><br />
        <managed-property></p>
<property-name>userDao</property-name>
            <value>#{userDao}</value><br />
        </managed-property><br />
    </managed-bean></p>
<p>    <managed-bean><br />
        <managed-bean-name>roleController</managed-bean-name><br />
        // podobnie jak wyżej<br />
    </managed-bean></p>
<p>    <navigation-rule><br />
        // nawigacja&#8230;<br />
    </navigation-rule></p>
<p></faces-config><br />
[/xml]</p>
<p>Integracja ze Springiem polega na tym, że jeśli JSF nie jest w stanie odszukać w swoim kontekście #{jakiegośBeana} to deleguje go następnie do Springa. Zauważcie, że posługuję się tym przy deklaracji managed beana <code>userController</code> i wstrzyknięciu mu <code>userDao</code>, który jest zadeklarowany w Springu.</p>
<p>Mam nadzieje, że ten mały artykuł o integracji powyższych technologii się Wam spodobał. Jeśli sądzicie, że za dużo było na raz informacji to dajcie znać. Jeśli chcecie, żeby coś dokładniej wytłumaczyć to napiszcie do mnie.</p>
<p>Ściągnij pełen kod źródłowy <a href="[download(jsf-crud.zip)]">tutaj (ściągnięto już archiwum [downloadcounter(jsf-crud.zip)] razy)</a> lub obejrzyj go online pod adresem <a href="http://svn.mocna-kawa.com/jsfcrud/">http://svn.mocna-kawa.com/jsfcrud/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mocna-kawa.com/2007/08/integracja-jsf-facelets-spring-jpa-tomahawk/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
	</channel>
</rss>
