Integracja JSF + Facelets + Spring + JPA + Tomahawk

Posted by wiktor on Aug 5, 2007 in facelets, java, jpa, jsf, spring

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 – będę wykorzystywał implementację Apache MyFaces – jako warstwa prezentacji,
  • Facelets – 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 2 – kontener IoC, będzie on wstrzykiwał beany obsługujące encje JPA (czyli DAO) do JSF (cudowna integracja) oraz obsługiwał transakcje,
  • Java Persistence API – implementacja Toplink – będę wykorzystywał JPA do mapowania obiektowo-relacyjnego,
  • Tomahawk – zestaw komponentów JSF ze stajni Apache.

Do artykułu dołączony jest kod źródłowy całej aplikacji. Można go otworzyć od razu w IntelliJ IDEA, a jeśli używasz innego edytora to musisz jakoś zaimportować projekt :) .

Możesz także przejrzeć pełen kod w subversion pod adresem: http://svn.mocna-kawa.com/jsfcrud/.

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:
[java]
@NamedQueries({
@NamedQuery(name = “findAllUsers”, query = “SELECT user FROM User user”),
@NamedQuery(name = “findUserByLogin”, query = “SELECT user FROM User user WHERE user.login = ?1″)
})
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String login;
private String password;

@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.EAGER)
private List roles;

// gettery i settery dla id, login i password.

// przesłonienie metod hashCode() i equals()

// taka mała sztuczka, bez której t:selectManyCheckbox nie chce działać (opakowanie w tablicę)
public Role[] getRolesAsArray() {
return roles == null ? null : roles.toArray(new Role[0]);
}

public void setRolesAsArray(Role[] roles) {
// błąd Toplinka: https://glassfish.dev.java.net/issues/show_bug.cgi?id=556
this.roles = new ArrayList(Arrays.asList(roles));
}
}
[/java]

Natomiast rola jest również prosta i jest następująca:

[java]
@NamedQueries({
@NamedQuery(name = “findAllRoles”, query = “SELECT role FROM Role role”),
@NamedQuery(name = “findRoleByRoleName”, query = “SELECT role FROM Role role WHERE role.roleName = ?1″)
})
@Entity
public class Role {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String roleName;

// gettery i settery

// przesłonięcie hashCode() i equals()
}
[/java]

Dobrą praktyką jest używanie nazwanych zapytań. W JPA zapisuje się je za pomocą adnotacji @NamedQueries i odpowiednio @NamedQuery.

Teraz zdefiniujmy interfejs do komunikacji między aplikacją a źródłem danych (czyli DAO).
[java]
public interface UserDao {
public List findAll();
public User findById(Integer id);
public User findByLogin(String login);
public void save(User user);
public void delete(User user);
}

public interface RoleDao {
public List findAll();
public Role findById(Integer id);
public Role findByRoleName(String roleName);
public void save(Role role);
public void delete(Role role);
}
[/java]

Teraz implementacja powyższych interfejsów. Będą one dziedziczyć po JpaDaoSupport, która to klasa dostarczona przez Springa zajmuje się komunikacją z EntityManagerem i pozwala na tzw. “jedno-linijkowce” (ang. one-liner).

[java]
public class JpaUserDao extends JpaDaoSupport implements UserDao {

public User findByLogin(String login) {
List users = getJpaTemplate().findByNamedQuery(“findUserByLogin”, login);
if (users.size() > 1) {
throw new DataIntegrityViolationException(“More than one user with the same login.”);
}
return users.size() == 0 ? null : users.get(0);
}

public List findAll() {
return getJpaTemplate().findByNamedQuery(“findAllUsers”);
}

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void save(User user) {
getJpaTemplate().merge(user);
}

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void delete(User user) {
getJpaTemplate().remove(getJpaTemplate().merge(user));
}

public User findById(Integer id) {
return getJpaTemplate().find(User.class, id);
}

}

public class JpaRoleDao extends JpaDaoSupport implements RoleDao {
// implementację można znaleźć w repozytorium lub w załączonym kodzie źródłowym
}
[/java]

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.

[xml]






[/xml]

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’a lub iBatis. Teraz persistence.xml.

[xml]

oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider

com.mocnakawa.jsfcrud.data.domain.Role
com.mocnakawa.jsfcrud.data.domain.User

[/xml]

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).

[java]
// Klasa typowa dla akcji typu CRUD
// Jest to dość proste, więc mam nadzieje, że kod się sam dokumentuje
public class UserController {

// wstrzykniete przez Springa
private UserDao userDao;

private User user;
private boolean editMode = false;

public List getUsers() {
return userDao.findAll();
}

public void editSetup(ActionEvent event) {
user = FacesUtils.getActionAttribute(event, “user”, User.class);
editMode = true;
}

public String update() {
userDao.save(user);
return Constants.USER_AND_ROLE_LIST;
}

public String createSetup() {
user = new User();
editMode = false;
return Constants.USER_FORM;
}

public String create() {
User userToCreate = userDao.findByLogin(user.getLogin());
if (userToCreate == null) {
userDao.save(user);
return Constants.USER_AND_ROLE_LIST;
} else {
FacesUtils.addErrorMessage(“Login already exists”);
return null;
}
}

public void delete(ActionEvent event) {
userDao.delete(FacesUtils.getActionAttribute(event, “user”, User.class));
}

// gettery i settery
}
[/java]

Kontrolera dla ról celowo pominąłem, można go znaleźć w załączonym kodzie źródłowym. Pora na web.xml.

[xml]

org.springframework.web.context.ContextLoaderListener


facelets.REFRESH_PERIOD 2

facelets.DEVELOPMENT true

javax.faces.DEFAULT_SUFFIX .xhtml


contextConfigLocation /WEB-INF/applicationContext*.xml


RequestContextFilter
org.springframework.web.filter.RequestContextFilter


RequestContextFilter
*.jsf



Faces Servlet
javax.faces.webapp.FacesServlet
1


Faces Servlet
*.jsf

[/xml]

Należy nie zapominać, aby podpiąć Springa. Parametr facelets.DEVELOPMENT 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.

Czas na zaprezentowanie potęgi Facelets. Zadeklarujmy szablon dla naszych stron:
[xml]
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">


<br /> <ui:insert name="title">Default title</ui:insert><br />

Default title




[/xml]

Tak ui:include oraz ui:insert 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.

[xml]


Users CRUD






Login
#{user.login}


Password
#{user.password}


Roles

  • #{role.roleName}



Edit





Remove








[/xml]

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 editMode w UserController.

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 t:selectManyCheckbox oraz t:selectItems z biblioteki Tomahawk. t:selectItems 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 t:selectManyCheckbox jest dostarczenie konwertera JSF dla klasy Role. Dlaczego? Jest to związane z cyklem życia JSF i zapisaniem/odbudowaniem modelu strony. Dlatego JSF potrzebuje konwertera, który przekonwertuje obiekt klasy Role do Stringa i vice versa.

[xml]







login: value="#{userController.user.login}"
required="true"/>
password: value="#{userController.user.password}"
required="true" redisplay="true"/>
Roles value="#{userController.user.rolesAsArray}">
itemValue="#{role}"/>
  rendered="#{!userController.editMode}"/>
rendered="#{userController.editMode}"/>
 




[/xml]

Teraz jeszcze prosty konwerter:

[java]
public class RoleConverter implements Converter {

public Object getAsObject(FacesContext facesContext, UIComponent arg1, String stringId) throws ConverterException {
if (stringId == null)
return null;

RoleDao roleDao = (RoleDao) facesContext.getApplication().getVariableResolver().resolveVariable(facesContext, “roleDao”);

return roleDao.findById(Integer.valueOf(stringId));
}

public String getAsString(FacesContext arg0, UIComponent arg1, Object object) throws ConverterException {
if (object == null)
return null;

if (object instanceof Role) {
Role o = (Role) object;
return “” + o.getId();
} else {
throw new IllegalArgumentException(“object:” + object + ” of type:” + object.getClass().getName() + “; expected type: Role”);
}
}

}
[/java]

Teraz czas na ostatnie posunięcie, czyli podłączenie Springa, Facelets do JSF :) .

[xml]



com.sun.facelets.FaceletViewHandler


org.springframework.web.jsf.DelegatingVariableResolver



com.mocnakawa.jsfcrud.data.domain.Role
com.mocnakawa.jsfcrud.web.RoleConverter



userController
com.mocnakawa.jsfcrud.web.controller.UserController
session

userDao #{userDao}


roleController
// podobnie jak wyżej


// nawigacja…


[/xml]

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 userController i wstrzyknięciu mu userDao, który jest zadeklarowany w Springu.

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.

Ściągnij pełen kod źródłowy tutaj (ściągnięto już archiwum [downloadcounter(jsf-crud.zip)] razy) lub obejrzyj go online pod adresem http://svn.mocna-kawa.com/jsfcrud/.

23 Comments

Piotr
Aug 6, 2007 at 12:26 am

Szybki link do dzialajacej aplikacji bylby mile widziany.


 
xyzzyx
Aug 6, 2007 at 7:51 pm

IMHO Transakcje na poziomie obiektow DAO sa bez sensu


 
Wiktor
Aug 6, 2007 at 9:03 pm

Zgadzam się z Tobą, nie pomyślałem o tym. Zrobiłem to przez przypadek. Transakcją powinna być objęta pojedyncza akcja.


 
Grzyb
Aug 6, 2007 at 9:16 pm

No za takie utransakcyjnienie to chyba mozna pojsc do wiezienia;)
Mam takie male pytanko: Na ile jest praktykowane, jak czesto jest uzywane definiowanie nazwanych zapytan w entity, czy tez gdzie kolwiek indziej? Bawilem sie kiedys z hibernate i on tez cos takiego, mial a sie tego nieuzywalo za czesto lub nawet moze wogole sie nieuzywalo. I czy to wogole w czyms pomaga, bo argument w stylu latwo mozemy zmienic jak dla mnie nie wystarcza bo i latwo mozemy zmienic w metodzie dao.


 
admin
Aug 6, 2007 at 9:43 pm

@Grzyb
Wszędzie do tej pory używałem nazwanych zapytań w projektach (w adnotacjach w JPA i w *.hbm.xml w Hibernate’cie). Argument, że trzyma się wszystkie zapytania dotyczące konkretnej encji w jednym miejscu, jest dość dobrym argumentem. Takie zapytania jak findAll, findBySomething itp. dobrze trzymać w jednym miejscu i obok deklaracji modelu. Zapytania dynamiczne i statyczne są sobie równoważne, jednak estetyka i organizacja w kodzie jest bardzo istotna :) .

Oczywiście powstaje pytanie, gdzie umieszczać zapytania, które agregują dane, tworzą raporty…, bo nie są kandydatami do nazwanych zapytań zapisanych przy encji. Bo mogą zwracać bardziej wyrafinowane wyniki (np. projekcie w JPA).

W Hibernate’cie korzysta się często z multi-criteria query, czego w JPA nie ma (pojawi się dopiero w JPA 2.0).


 
Grzyb
Aug 6, 2007 at 11:54 pm

@admin
No ok, ale jesli mamy zapytanie np findAll to metoda wykonujaca to zapytanie znajduje sie w dosc konkretnym dao (np. User UserDAO), moze z pewnymi wyjatkami, takze w ten sposob utrzymujemy porzadek i organizacje kodu. Faktycznie jesli umiescimy nazwane zapytania w deklaracji modelu, to moze sie przydac podczas zmiany modelu, ale i tak najczesciej wiaze sie to ze zmiana w wielu miejscach aplikacji.
A tak poza tym … to jesli bede mial dwa miejsca, w ktorych moga sie znajdowac zapytania (w modelu, czy tez w definicji metody dao), to mam tak naprawde 2 miejsca, w ktorych to moze sie znalesc zapytanie Mimo faktu, ze moge przypuszczac, ze zapytania typu findAll powinny byc obok modelu.
OK A teraz do rzeczy … Kto jeszcze uzywa dosc czesto nazwanych zapytan oraz do jakiego typu zapytan ich uzywa?


 
PTR
Aug 16, 2007 at 10:17 pm

Walidacja nazwanego zapytania przy kompilacji moze byc przydatna. Hibernate’owe kryteria tez sa niczego sobie.


 
Jacek Laskowski
Aug 20, 2007 at 11:28 pm

Artykuł bardzo mi się podoba. Mam kilka uwag, ale nie wpływają one na ogólną ocenę artykułu – 5+.

Uwagi:

Zmieniłbym ?1 na :login – stosowanie parametrów nazwanych zamiast pozycyjnych dodatkowo upraszcza czytelność kodu.
@NamedQuery(name = “findUserByLogin”, query = “SELECT user FROM User user WHERE user.login = ?1″)

@GeneratedValue(strategy = GenerationType.AUTO) jest domyślnym ustawieniem – niepotrzebne

Warto rozważyć uzupełnienie encji User o realizację interfejsu Serializable (jest to zalecane acz jeśli mamy pewność, że User nie będzie przesyłane z jednej JVM do drugiej możemy o tym zapomnieć).

Zalecam uzycie typów generycznych, np.
private List roles;
public List getUsers() w UserController

Podobne uwagi dotyczą encji Role (poza getUsers z UserController)

Nie mogę zgodzić się ze zdaniem:
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’a lub iBatis.

Jest to rezultat skorzystania z interfejsu zamiast bezpośrednio z implementacji, a SF upraszcza skorzystanie z jednej implementacji dostępu do danych na rzecz innej. Niezależność interfejsu DAO od zastosowanej technologii ORM nie wynika więc z możliwości SF.

Pytania:

1/ Czy można zdefiniować źródło danych w SF i skorzystać z niego w persistence.xml (na wzór konfiguracji JPA w serwerach aplikacyjnych)?

Odpowiedzi do pytań z komentarzy:

Odnośnie pytania:
Oczywiście powstaje pytanie, gdzie umieszczać zapytania, które agregują dane, tworzą raporty…, bo nie są kandydatami do nazwanych zapytań zapisanych przy encji. Bo mogą zwracać bardziej wyrafinowane wyniki (np. projekcie w JPA).

Za pomocą deskryptora XML (orm.xml) możemy zdefiniować zapytanie nazwane związane z danym PU zamiast encją.

Gratuluję artykułu i sposobu przedstawienia tematu – lekko, łatwo i przyjemnie. Nie mogę doczekać się kolejnego.

Jacek


 
Marcin
Aug 29, 2007 at 8:06 am

Hej, gratuluję stylu artykułu – bardzo lekko się go czyta i szybko wiadomo o co chodzi.

Mam jedno pytanie i jedno zastrzeżenie.

Pytanie:
Czy jest jakiś powód dla którego kontrolery są zarządzane w JSF, a DAO w Springu? Kontrolery także mogłyby być zarządzane przez Springa i nie potrzeba byłoby deklarować managed beans w faces-config.xml

Zastrzeżenie:
Wydaje mi się, że trzymanie kontrolera w sesji nie jest za dobre, bo np. może być wtedy problem z używaniem aplikacji w dwóch oknach/tabach przeglądarki. Niestety w JSF beany zwykle są benami takimi trochę stanowymi, ze względu na lifecycle JSF i scopy typu session faktycznie ulatwiaja troche napisanie takigo kontrolera, niemniej to mi sie właśnie w JSF nie podoba. Co o tym sądzisz?

Marcin


 
Hubert
Aug 29, 2007 at 4:11 pm

A ja mam takie pytanko odnosnie magicznych Facelets, i ich przewagi nad tiles. Majac strone z ‘Layout’ i strone z ‘Content’, moge je ladnie powiazac dajac w stronie z ‘Content’:

A co w przypadku gdy mam jakis ‘Content’ i chce go uzyc w dwoch roznych ‘layoutach’? W tiles wiazania robie na poziomie pliku konfiguracyjnego. Robiac np dwie podobne aplikacje z kompletnie innymi layoutami, definiuje nowy layout i robie nowy plik powiazan. Jak to rozwiazac w Facelets, bo to wyglada troche jakby trzeba bylo robic copy paste calej strony z zawartoscia ze przypisanym innym layoutem.


 
Hubert
Aug 29, 2007 at 4:13 pm

Zle sie zacytowal przyklad z powiazaniem Layout/Content :) :

ui:composition template=”/pages/layout.xhtml”


 
Mariusz Lipiński
Aug 30, 2007 at 12:40 pm

Witam,

moje 3 grosze ad. nazwanych zapytań. Warto je stosować ponieważ:

- nazwane zapytanie, zdefiniowane gdzieś w kodzie aplikacji można nadpisać w xml’u zapytaniem zoptymalizowanym (chociażby SQL) używając właśnie jego nazwy, bez konieczności jakichkolwiek modyfikacji kodu

- zapytania nazwane są przetwarzane tylko raz, na etapie przetwarzania/ładowania klas/encji, tj. parsowanie JPAQL i generowanie SQL ma miejsce tylko raz


 
admin
Sep 3, 2007 at 10:06 am

@Jacek Laskowski

1/ “Zalecam uzycie typów generycznych, np. private List roles; public List getUsers() w UserController”

Chyba drobna pomyłka, bo wszędzie używam typów generycznych :) .

2/ Czy można zdefiniować źródło danych w SF i skorzystać z niego w persistence.xml (na wzór konfiguracji JPA w serwerach aplikacyjnych)?

Jak najbardziej. Będę leniwy i odeślę do dokumentacji Springa: http://static.springframework.org/spring/docs/2.1.x/reference/orm.html#orm-jpa, gdzie na początku dokumentu jest wszystko jest pokazane.

@Marcin

1/ Czy jest jakiś powód dla którego kontrolery są zarządzane w JSF, a DAO w Springu? Kontrolery także mogłyby być zarządzane przez Springa i nie potrzeba byłoby deklarować managed beans w faces-config.xml

Kontrolery JSF mogłyby być zadeklarowane w Springu, ale odradzałbym to rozwiązanie z przyczyn estetycznych :) . Jeśli wprowadzamy architekturę warstwową to powinniśmy trzymać kontrolery JSF w warstwie prezentacji. Poza tym zysk byłby znikomy, ponieważ deklaracja kontrolerów JSF byłaby w Springu, a reszta konfiguracji JSF nadal zostałaby w faces-config.xml.


 
mkosm
Sep 10, 2007 at 1:58 pm

No fajnie ze to dziala…
Ale pytanie czy zadziala dla jsf1.2??? Bo w moim przypadku np. nie moge wykonac zadnych operacji typu crud poza selectem:(:(


 
admin
Sep 10, 2007 at 2:02 pm

Faktycznie jest problem z biblioteką Tomahawk, ponieważ nie działa ona z JSF 1.2. Więcej o kompatybilności Tomahawk z JSF można znaleźć tutaj http://wiki.apache.org/myfaces/CompatibilityMatrix.


 
mkosm
Sep 10, 2007 at 2:12 pm

nie, nie o to mi chodzilo…
Mam dao w springu 2.0 i wlasnie nie dzialaja mi merge,persist i delete.
Przydziela id obiektowi ale nie utrwala w bazie przy persist:(
(btw. tomakawka inputFileUpload zintegrowalem podejrzewam ze inne tez bym mogl…)


 

[...] to “Integracja JSF + Facelets + Spring + JPA + Tomahawk” i będzie on bazował na moim artykule o tej samej nazwie. Wpis ten stał się dość popularny i stąd pomysł na prezentacje. Poniżej [...]


 
Thomas Roland
Jan 18, 2008 at 10:11 am

Hi boy,

I find the title of your articel is quite interessting. But why don’t you write your artical in English, sothat more people can read it?


 
Marcin Kr
Mar 4, 2008 at 3:07 pm

Odnośnie warstwowości: plik PU ‘persistence.xml’ w /WEB-INF/classes/META-INF/ to dobre rozwiązanie? Rozumiem, iż jest to prosta aplikacja typu CRUD, która zamyka się w jednym war’ze, jednak umieszczanie plików konfiguracyjnych dostępu do danych w części webowej – na pewno istnieje lepsze, bardziej elastyczne rozwiązanie. Wkład przez Ciebie włożony w napisanie oraz udokumentowanie pracy – Best Regards


 
Jacek
Jan 16, 2009 at 9:48 am

Obecnie używam RichFaces ze względu na łatwą i efektywną integrację ze Spring Framework i ajaxowe przetwarzanie. Szkielety Ajax RichFaces, Spring Framework i Hibernate Validator dają się idealnie integrować. W moim artykule opisałem sposób wykorzystania anotacji szkieletu Hibernate Validator w ramach stron jspx wykorzystujacych odpowiedni komponent RichFaces. Dodałem także aplikacje przykładową, może okaże się pomocna.


 
bimki
Mar 22, 2009 at 11:02 pm

hej,

no właśnie ja też mam podobny problem. Zrobiłem prawie identyczną konfigurację na springu 2.5 i hibernate 3.2 – z taką różnicą, ze @Transactional przeniosłem na poziom akcji managed beana i nie działa mi nic oprócz selectów… czy ktoś wie co trzeba zrobić, żeby działo persist, merge? Bede wdzieczny za pomoc

moja konfiguracja b. podobna do tej z artykułu oraz do tego co jest oposisane tutaj: http://www.myeclipseide.com/documentation/quickstarts/jpaspring/#containermanaged

pozdr


 
bimki
Mar 23, 2009 at 8:36 am

już rozwiazałem problem :)
Beana trzeba zadeklarować w applicationcontext.xml a nie w faces-config.xml – wtedy działa insertowanie


 
mario
Apr 22, 2009 at 5:14 am

Tutaj jest opisane połączenie z jsf myfaces. A jakby to wyglądało w połączeniu z Sun jsf? Próbowałem połączyć Tomahawk 1.8 z JSF 1.2. a dokładnie probowałem skonfigurować w web.xml zgodnie z zaleceniami:
http://myfaces.apache.org/tomahawk/extensionsFilter.html
jednak wyskakują mi błędy. Czy to nie jest kompatybilne z Sun JSF?


 

Reply

Copyright © 2010 Mocna Kawa All rights reserved. Theme by Laptop Geek.