Dear Wiki user, You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for change notification.
The following page has been changed by michaelcourcy: http://wiki.apache.org/tapestry/Tapstry5First_project_with_Tapestry5,_Spring_and_Hibernate ------------------------------------------------------------------------------ http://baptiste-meurant.developpez.com/tutoriaux/tapestry5-spring-hibernate/ - This tutorial proposes a blanck application for a Tapestry5-Spring-Hibernate project. It consist on a main page of login that seach for the existence of a user inside a DB. + This tutorial proposes a blanck application for a Tapestry5-Spring-Hibernate project. It consists on a main page of login that seach for the existence of a user inside a DB. This tutorial is in two parts : a blank application with Spring-Hibernate and in the second part we integrate Tapestry 5. With this separation you'll be able to reuse the first part with another front framework. @@ -82, +82 @@ * DAO Layer : this layer manages the access to the database through the Hibernate framework. * Service Layer : The layer represents all the buisness code, it organises the access to the DAO layer and manages all the transactionnal aspects. All of them are organized and manages by the Spring framework. - * MVC Layer : This layer is the IHM, it's the client part of the application. It interacts with the Service layer depending of the client action and retreive the data to show them in well formed way. This layer is undertaken by the Tapestry5 framework. + * MVC Layer : This layer is the IHM, it's the client part of the application. It interacts with the Service layer depending of the client action and retreive the data to show them in a well formed way. This layer is undertaken by the Tapestry5 framework. - Those layers must be decoupled, which means that there should be no dependencies between each other. Pratically this is enabled by having each layer collborating to the other layer through interface. For instance the Service layer only know the interfaces of the DAO layer and the MVC layer only know the interfaces of the Service Layer. This way, each layer publish, through its interfaces, all the treatement that it can offer to the upper layer. And the link between the interface and the implementation, which introduces a technologic dependency (for instance the implementation of the DAO layer uses hibernate) is managed by Spring. + Those layers must be decoupled, which means that there should be no dependencies between each other. Pratically this is possible by having each layer collborating to the other layer through interface. For instance the Service layer only know the interfaces of the DAO layer and the MVC layer only know the interfaces of the Service Layer. This way, each layer publish, through its interfaces, all the treatement that it can offer to the upper layer. And the link between the interface and the implementation, which introduces a technologic dependency (for instance the implementation of the DAO layer uses hibernate) is managed by Spring. - Indeed it's Spring when the application starts who establish the link between the interface and the implementation with its Inversion Of Control and dependencies Injection engine. The developper works only on method call from interface and not directly from the implememntation, which enhances the evolutivity and the loose coupling of the application. + Indeed it's Spring when the application starts who establish the link between the interface and the implementation with its Inversion Of Control and dependencies Injection engine. The developper works only on method call from interface and not directly from the implementation, which enhances the evolutivity and the loose coupling of the application. We notice also a special layer : the model layer. This layer traverses the other three layers because it reflects the buisness entity stored in the DB model. Each layer naturally could manipulate those entities. @@ -94, +94 @@ Let's focus for a little while on the manipulation of the DB. The previous explainations show two aspects : - * The DAO layer publish its access methods to the DB, theses methods can search, create or delete records. Actually they can retreive objects from DB record, create new objects by creating new records in the DB, or delete object by deleting record in the DB. + * The DAO layer publishstransactionnal contexte its access methods to the DB, theses methods can search, create or delete records. Actually they can retreive objects from DB record, create new objects by creating new records in the DB, or delete object by deleting record in the DB. * The object relational mapping and the persistance of datas in a transactionnal context allow any change in the state of an object to be propagated in the DB through UPDATE actions. Thus the DAO layer won't features any methods to update the objects. Thoses aspects will be covered in greater details later on. - Nevertless, the creation of object corresponding to INSERT are still needed, because even if you are in a transactionnal contexte the service layer can't decide on your behalf if a new object of the model layer must be persited. After all it could be a temporary variable. + Nevertless, the creation of object corresponding to INSERT are still needed, because even if you are in a transactionnal context the service layer can't decide on your behalf if a new object of the model layer must be persited. After all it could be a temporary variable. === Setting Hibernate === @@ -111, +111 @@ ==== Install Hibernate tool ==== - Hibernate Tools is an eclipse plugin that make possible to generate classes from the DB model : + Hibernate Tools is an eclipse plugin that make possible to generate classes from the DB model : * Unzip the archive. * You'll find 2 directories : plugins and features, put what they contains respectively in the directory plugins and features of your eclipse installation. * Restart eclipse. - * New elements show up in the interface, provinng that the plugins is well setup : + * New elements show up in the interface, proving that the plugins is well setup : [http://baptiste-meurant.developpez.com/tutoriaux/tapestry5-spring-hibernate/images/fig8.jpg] @@ -672, +672 @@ }}} - Once again we deal with the paradigm interface/implémentation with this time the use of injection through the definition of userDao which reference the bean defined before. : the name of the bean must exactly the name of the property defined in userManager. Spring will use camelise mechanism to invoke the setter : ie set + "U"serDao(userDAO); + Once again we deal with the paradigm interface/implémentation with this time the use of injection through the definition of userDao which reference the bean defined before. : the name of the bean must be exactly the name of the property defined in userManager. Spring will use camelise mechanism to invoke the setter : ie set + "U"serDao(userDAO); ==== Transaction management ==== @@ -735, +735 @@ We put a transactionnal proxy in front of the buisness bean. The transactionManager is passed to the transactionnal proxy and we declare to Spring that the transaction configuration is done with annotation thanks to the property transactionAttributeSource. - Now we need to add the necessary annotation to the interface UserManager to cofigure its transactionnal behavior. Change UserManager : + Now we need to add the necessary annotation to the interface UserManager to configure its transactionnal behavior. Change UserManager : UserManager {{{ @@ -785, +785 @@ }}} - After this Spring will be able to manage on its own all the transaction aspects: commit, rollback and persitence of the attached object as long as they flow of execution is occuring in a transactionnal context. + With this configuration Spring will be able to manage on its own all the transaction aspects: commit, rollback and persitence of the attached object as long as the flow of execution is occuring in a transactionnal context. Let's watch the implementation of the changePassword method and notice the persitent nature of the User object : in this method the user is retreived with the login. Then the password is changed and no access to the DAO layer is needed anymore. Only because this method is in a transactionnal context (and also not read-only), any changed to the object will be propagated to the DB. @@ -936, +936 @@ } String onSuccess() { - //mon code métier + //The buisness code String ret = "Home"; return ret; } @@ -1020, +1020 @@ * Once again, the annotation @ApplicationState will retreive the variable login from the session. * The annotation @Inject let tapestry inject dependencies from third parties source (here J2EE core). - * The method onLogout which thanks to the annotation @onEvent(component="logout") will be invoked every time the component bubble an event. Here, the component is a simple link, so every time one click on it the session is invalidated and the user redircted to the login page. + * The method onLogout which thanks to the annotation @onEvent(component="logout") will be invoked every time the component bubble an event. Here, the component is a simple link, so every time one click on it the session is invalidated and the user comeback to the login page. Edit web.xml to configure the Tapestry filter and the base package from which tapestry knows where to find the pages package that contains page beans. {{{ @@ -1080, +1080 @@ ==== Integration with Spring ==== - If the result is already interesting, it's still not enough. We must now search the user in the DB, check its existence, if it's password is valid, etc. To achieve this we're going to traverse the different application layers, from tapestry to dao passing by the service. + If the result is already interesting, it's still not enough. We must now search the user in the DB, check its existence, if his password is valid, etc. To achieve this we're going to traverse the different application layers, from tapestry to dao passing by the service. As explained before, the communicationship between the different layers - as some advanced functions (transactions, etc.) - are managed by Spring. We must integrate Spring and Tapestry. Tapestry5 propose natively a support to Spring. @@ -1099, +1099 @@ }}} - Once Tapestry is configured to work with Spring, we must inject the Springbeans in the Tapestry pages. change Login.java : + Once Tapestry is configured to work with Spring, we must inject the Spring beans in the Tapestry pages. change Login.java : {{{ @@ -1174, +1174 @@ We notice : - * the annotations @Inject and @Service a bean (Manager) from Spring into Tapestry. We can now use all of the methods defined in the interface here we modify the methode onSucces, when the for is submitted the application called the Spring userManager service to execute the checkLogin method and check that login and password really exist in DB. If yes the user is redirected to the Home page. In the opposite, we initialise an error message variable to be diplayed to the user. + * the annotations @Inject and @Service inject the bean (Manager) from Spring into Tapestry. We can now use all of the methods defined in the interface here we modify the methode onSucces, when the for is submitted the application called the Spring userManager service to execute the checkLogin method and check that login and password really exist in DB. If yes the user is redirected to the Home page. In the opposite, we initialise an error message variable to be diplayed to the user. * The annotation @Persist on error persist the value of error only for this page : instead of the annotation @ApplicationState, @Persist define persistence only for the page not for the whole application. * The getErrorMessage make the property errorMessage available in the Login page. change Login.html : @@ -1224, +1224 @@ As we explained it at the beginning of this tutorial dealing with hibernate, every model object is related to a table in the DB. We therefore get a complete object graph : an entity having a 1,n relation with entity E2 in object realm is going to be object O1 of type T1 hold an object O2 of type collection of T2 ⦠And so on. - We quickly realised that the object graph could be extremely heavy if all collections and children of children collections must be loaded. It's why by default, Hibernate uses "Lazy loading". Lazy loading means that when the object is loaded in memory, only the object is loaded not all it's collections; collections will be loaded when they will first be used. The opposite of lazy loading is eager loading : when the object is loaded all the graph is loaded. You must eplicily annotate your classes to have eager loading (1,n ; n,1 ou n,n) : @OneToMany, @ManyToMany ou @ManyToOne(cascade = {}, fetch = FetchType.EAGER). + We quickly realised that the object graph could be extremely heavy if all collections and children of children collections must be loaded. It's why by default, Hibernate uses "Lazy loading". Lazy loading means that when the object is loaded in memory, only the object is loaded not all its collections; collections will be loaded when they will first be used. The opposite of lazy loading is eager loading : when the object is loaded all the graph is loaded. You must explicitly annotate your classes to have eager loading (1,n ; n,1 ou n,n) : @OneToMany, @ManyToMany ou @ManyToOne(cascade = {}, fetch = FetchType.EAGER). - One very important thing to understand about lazy loading is that you can access to the lazy collections only if the transaction in wich you got this object is not commited yet. Indeed, the lazy loading is possible because the session Hibernate is stil active and opened to be able to complete the graph from the DB when needed. And with the transaction manager we used in this tutorial, the session is closed at the end of the execution of the service method. Thus if we try to access a collection in the view we're going to have a LazyInitializationException. + One very important thing to understand about lazy loading is that you can access to the lazy collections only if the transaction in wich you got this object is not commited yet. Indeed, the lazy loading is possible because the session Hibernate is still active and opened to be able to complete the graph from the DB when needed. And with the transaction manager we used in this tutorial, the session is closed at the end of the execution of the service method. Thus if we try to access a collection in the view we're going to have a LazyInitializationException. But there's a workaround to keep the session Hibernate "alive" until the page renders, with this workaround you only load what's really needed. It doesn't mean that you can do now whatever you want with the session. Indeed the session is alive until the request completes ; it means that we are going to be able to access a lazy collection in the view, but if you decide to put the object you got from a transactionnal context in the http session you won't be able to retreive a lazy collection in the next request. The Hibernate session would have died. @@ -1246, +1246 @@ }}} - Make sure this filter is called before the the tapestry filter. + Make sure this filter is declared before the the tapestry filter. To test this new filter we're going to create a new table 'rights' that will defines the rights of a given user : @@ -1598, +1598 @@ }}} - Here we force the use of the lazy loading thus beacause the object is already loaded, there's no problem anymore : + Here we force the use of the lazy loading thus there's no problem anymore : [http://baptiste-meurant.developpez.com/tutoriaux/tapestry5-spring-hibernate/images/fig34.jpg] - This example show the limitations of lazy loading. Keep now in your mind that lazy loadig is only available inside the scope of the trasactionnal context. So what we did was useless ⦠in this particular case, yes, beside this object is extremly light so we'd better use the EAGER loading. + This example show the limitations of lazy loading. Keep now in your mind that lazy loading is only available inside the scope of the trasactionnal context. So what we did was useless ⦠in this particular case, yes, and even more this object is extremly light so we'd better use the EAGER loading. - Nevertless very often it's useful - especially when you have to manipulate very high data volumes. In the Other hand here chossing the EAGER would have forced ud to define a new method in the Service layer and in the DAO layer to get a given user. + Nevertless very often it's useful - especially when you have to manipulate very high data volumes. In the Other hand chossing the EAGER would have forced us to define a new method in the Service layer and in the DAO layer to get a given user. - To finish about the lazy loading, lazy loadig must be used with extra cautions but once the principles are well understood the advantages are very significant. + To finish about the lazy loading, lazy loadig must be used with extra cautions but once the concepts are well understood the advantages are really significant. === Conclusion === --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
