You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Cyrille37 <cy...@gmail.com> on 2006/12/06 12:25:15 UTC

about Beanform and JPA (persistence)

Hello,

I'm coming back with a beginner question ;-)

After 3 weeks of Java Web App discovering, I'm actually working with 
Tapestry 4.0.2, Netbeans 5.5 which give me easy data persistence support 
with JPA Toplink essential, and Tomcat5.5 and Mysql5.

So I've finaly got something working with Beanform and JPA and I come to 
you to get comments and ideas and best practice.

For the persistence, the method I've found is to do the following :

* To remember with object I'm playing with :

    @Persist("client")
    public abstract int getProductId();
    public abstract void setProductId(int productId);

* To manage the Beanform's bean :

    private Product _product ;
    public Product getProduct()
    {
        if( this._product==null && this.getProductId()>0 )
        {
            this.setProduct(  this.loadProduct( this.getProductId()) );
        }
        return this._product ;
    }

    public void setProduct( Product product )
    {
        this._product = product ;
    }

* For initializing the page at the first time :

    public void activateExternalPage(Object[] parameters, IRequestCycle 
cycle)
    {
        int pid = Integer.parseInt( parameters[0].toString());
        setProductId( pid );
        this.setProduct( this.loadProduct(pid) );
    }

* And finally to implement the Beanform 'save' listener :

    public String save()
    {
        System.out.println( "ProductEdit.save()" );
        if( this.getDelegate().getHasErrors() )
            return null;
        EntityManager em = getDataManagerFactory().GetEntityManager();
        /*** I find that method a beat strange but it works ! ***/
        em.getTransaction().begin();
        em.flush();
        em.getTransaction().commit();

        return "Home";
    }

Thanks to have read my poetry ;-)
Cyrille.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: about Beanform and JPA (persistence)

Posted by Cyrille37 <cy...@gmail.com>.
Hello professor Sam ;o)

Thank you a lot for you long long course.
I will read it slowly and carefully this morning in the train.

Best Regards,
Cyrille.

Sam Gendler a écrit :
> I'll clarify a little.  In general, you want to keep persistence code,
> ui code, and business rules fairly separate.  This will keep your
> application much more flexible as more and more requirements are added
> over time.
>
> In your example code, you've got persistence embedded directly in ui
> code.  Should you ever decide to replace your perisistence layer with
> something else (say, replace toplink with hibernate, ibatis, or even
> raw jdbc), you will have to go in and modify every page class you've
> built that has persistence code in it.  In a large project, this is
> effectively impossible to do without destabilizing the codebase too
> much to be acceptable.  Therefore, most well architected apps will
> keep all perisistence code in a separate set of interfaces.  So long
> as you can create a persistence layer that maintains the same
> interface, you can replace one with another very simply.  This is
> where dependency injection becomes useful - Instead of injecting a
> toplink data access object into your page, you can inject a hibernate
> one instead.
>
> But wait, did I just say injecting a dao into the page?  Most of us
> would argue you never want to do that, for the following reason.
> Suppose you have a method in your DAO which stores an entity into the
> database.  If you are using your dao directly in your page class, then
> you either have to open and commit a transaction directly in your page
> (violating the rule about keeping persistence code out of your ui
> layer and once again locking you into a particular transaction
> mechanism, preventing you from switching between JDBC transactions,
> JTA transactions, etc), or else your DAO itself has to open the
> transaction, save the entity, and commit the transaction.  This would
> be fine in this circumstance.  Your persistence code would stay in
> your persistence layer, but now you have another problem.  Page1 may
> store just a single instance of the entity, so including transaction
> semantics around that store operation works just fine.  But now you
> have to add Page2, and Page2 wants to store two entities.  But if
> either store() fails (unique column conflict, for instance), you don't
> want to store() either of the entities.  So now your transaction
> within the store method won't work, since the first store() will be
> fully committed before the second store() fails, offering you no way
> to roll back.  So your only option is to implement another DAO method
> - one which takes a collection of entities and stores them all within
> a single transaction.  You can probably see that as your project
> grows, you are going to wind up with a lot of very similar methods,
> each different only in the transaction behaviour.
>
> The rule that you must be able to store both entities if you are going
> to store either one is considered a 'business rule' - an artificial
> constraint on what you are allowed to do.  Business rules frequently
> change over the life of a project, so once again, you want to keep
> your business logic firmly separated from your ui.  Again, this is
> accomplished by shoving your business logic into separate classes with
> a well defined interface and injecting instances of those interfaces
> into your page classes.  Now, your ui code doesn't need to know
> anything about transactions because your service layer is handling
> them.  Your ui can call a method to store() two entities and doesn't
> need to be concerned with the details of how that occurs or what is
> allowed.  All it knows is it either succeeded or failed based on an
> exception may catch. Once again, your ui layer is clean.  It is
> injected only with service interfaces.  Service objects are injected
> with DAO interfaces, and you've got a nice clean layer separation.
>
> Except for one thing.  You've got a bunch of transaction code sitting
> in your service layer, wrapped around calls into your DAOs, which no
> longer have any knowledge of transactions themselves.  This means
> there is still a strong binding between your service layer and your
> perisistence layer, making it very difficult to modify one without
> modifying the other.  That's generally considered a _bad_thing_ and
> should be avoided.  So this is where Spring steps in and provides some
> VERY useful functionality.  Spring gives a nice declarative mechanism
> (ie. you can set it up in a config file or annotation, rather than by
> writing code)  for forcing a transaction around any method of any
> object.  You can define a business method that calls multiple DAO
> methods and you can tell spring that anytime someone calls that
> method, you want a transaction to be started before the method
> executes, and the transaction to be committed when the method is
> completed without throwing an exception, or rolled back if an
> exception is caught.  Now you can remove all of that pesky transaction
> code from your service layer, giving you true independance from your
> persistence layer outside of the persistence interfaces, which should
> be generic across any persistence mechanism.  OK, you've still got a
> dependency in your config, but at least your code, which is the most
> complex and error prone piece of the application, is completely
> independant (that's why I prefer to avoid annotations for transaction
> declarations.  I don't want to recompile to change a transaction)
>
> A side benefit of all of this is that Spring is now responsible for
> all that boilerplate code that gets copied around everywhere for
> opening a connection, catching exceptions, closing the connection,
> catching more exceptions, etc.  Spring is widely used and well tested,
> so you can be confident that the boilerplate code it is using is
> correct.  The one caveat (and it is a small one), is that your
> persistence layer is required to use certain helper methods provided
> by spring which will ensure that your dao uses the connection that has
> the transaction on it.   However, the helper methods are incredibly
> useful and do much of the work involved in communicating with your
> database for you.  I don't know toplink, as I use hibernate, but let
> me give you a quick hibernate example.
>
> In a normal Hibernate DAO, if I wanted to store an object into the db,
> I'd do the following:
>
>    public void store(Event theEvent) {
>
>        Session session = 
> HibernateUtil.getSessionFactory().getCurrentSession();
>
>        try {
>            session.beginTransaction();
>            session.save(theEvent);
>            session.getTransaction().commit();
>        } catch (Exception e) {
>            try {
>                session.getTransaction().rollback();
>            } catch (Exception e2) {
>            }
>        } finally {
>            try {
>                HibernateUtil.getSessionFactory().close();
>            catch (Exception e3) {
>            }
>        }
>    }
>
> That's a lot of code, especially those obnoxious nested
> try...catch..finally blocks that are so common to all db programming
> in java.  Even without the transaction handling, I've still got to get
> the session and execute the store() method.
>
> Using the Spring hibernate helper class and configuration however, I
> can do the same thing in a single line of code:
>
>        public void store(Event theEvent) {
>            getHibernateTemplate().saveOrUpdate(theEvent);
>        }
>
> The HibernateTemplate already knows how to get the current session
> (which will already have a transaction started on it).  If the store
> method throws an exception, it will be propagated up and the
> transaction will automatically be rolledback.  Spring also translates
> database and ORM specific exceptions into nice generalized exceptions
> so that your application exception handling doesn't need to know about
> the ORM or db.  Otherwise, you have to know that error code 6453 in
> oracle is equivalent to error code 1234 in postgres, or else just
> respond to a generic SQLException.  Spring can throw a much more
> meaningul exception that will be the same no matter which db you use,
> allowing your app to respond much more intelligently to exceptions up
> to and including providing much more meaningful error messages to
> users and developers.
>
> There are methods provided for all the basic CRUD operations (create,
> retrieve, update, delete)  as well as various list methods and, of
> course, a mechanism for building complex queries with lots of
> parameters.  It saves an awful lot of code.
>
> So now, if you use all the advice I've offered so far, you've got the 
> following:
>
> a DAO layer which has no transaction semantics and which uses Spring
> DAO base classes to handle all the complexity of db interaction,
> whether you use hibernate, iBatis, JDBC, or toplink.
> (http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/orm/toplink/package-summary.html 
>
> and 
> http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/orm/toplink/support/package-summary.html 
>
> )
>
> You have a business service layer which ensures your application
> adheres to business rules..
>
> You have transactions that are assigned to your service methods
> declaratively (either through the spring config or via annotations.  I
> prefer the config file because I often like to set things up
> differently in a test environment compared to production and I don't
> want to have to recompile)
>
> You have a UI layer that knows nothing about any of this, other than
> the interfaces provided by your business service layer.
>
> You are now free to swap your web ui for a swing ui, WAP ui, command
> line ui, or anything else you care for, without being forced to ensure
> that all your business rules and persistence code is properly copied
> to the new ui layer.  You can also replace your perisistence layer
> with hibernate, jdbc, or anything else without touching a single line
> of code in either your service or web ui layers.  You've coded
> everything to a set of interfaces instead of specific classes.  This
> is important because it means you can easily drop different
> implementations of the same interface into your code via dependency
> injection, including injecting mock objects during testing in order to
> simulate production conditions.
>
> The one complaint I have about a rigidly layered application such as
> this is that it can force you into an unreasonable amount of typing to
> do simple things.  If you add a new DAO method to support some action,
> you've now got to add the method to the dao interface and the dao
> implementation. There is also a high probability you'll be adding a
> corresponding method to your service layer, so you've got to add
> methods to the service interface and the service implementation as
> well.  Then you've got to make sure you've applied the correct
> transaction semantics to the service method in question. It is a fair
> amount of cut and paste typing, which can be error prone, although
> errors are likely to be caught at compile time (unless you screw up
> your transaction declaration, which you won't detect until runtime),
> so it isn't a huge problem, other than the time involved and the
> repetitive stress injuries. I don't use an IDE, so I have some quick
> scripts which dump all the necessary method and transaction
> declarations into a file, and I can then just cut and paste the
> guaranteed correct declarations into the appropriate files (it was
> easier than trying to parse the files and inserting the code directly
> and it means I can relax a little on file/class naming conventions).
> Also, judicious use of base interfaces and base classes with generics
> means that you can often add a single method to a base class in order
> to get the functionality added for every single entity type in your
> application.
>
> OK, that was a ton of information, but hopefully you'll find it very
> useful, since you said you were new to Java web development.
>
> --sam
>
>
> On 12/7/06, Cyrille37 <cy...@gmail.com> wrote:
>> Hello
>>
>> D&J Gredler a écrit :
>> > I haven't used EntityManagers directly, but your code looks fine to 
>> me,
>> > especially if it works ;-)
>> > You may want to wrap your flush( ) call in a try/catch block in case
>> > something goes wrong, and roll back the transaction in the catch 
>> block.
>> It works, but I've made change because I've got only one EntityManager
>> for all the application.
>> In Toplink's examples I see that the create an EntityManager each time
>> they make a query.
>> So I've change flush() to merge(this_product) because object was
>> "detached" ...
>> Sorry, I'm not very clear ...
>>
>> > Once you get more comfortable with things (and if you're using
>> > Hibernate),
>> > you may want to check out some of the integration packages (Tapernate,
>> > Honeycomb, etc) that handle transaction scoping for you.
>> hmmm... Which scope ?
>> I could not imagine what they do. I'm to beginner with Java & Co.
>> Please, can you explain me a beat what a package like Tapernate or
>> Honeycomb will do.
>>
>> For da moment I'm using JPA (TopLink Essential).
>>
>> > Spring might also
>> > be a good option if you end up splitting your app up into 
>> presentation /
>> > service / persistence layers.
>> At the beginning of my exploration, I've try Spring with Tapestry and I
>> did not see what it will bring to me more than Hivemind.
>> Perhaps because I only the the object injection, and not other things
>> that Spring bring to us.
>>
>> Thanks for you support ;o)
>> Cyrille
>>
>>



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Re: about Beanform and JPA (persistence)

Posted by D&J Gredler <dj...@gmail.com>.
Wow. Very good summary of best practices!

On 12/8/06, Sam Gendler <sg...@ideasculptor.com> wrote:
>
> I'll clarify a little.  In general, you want to keep persistence code,
> ui code, and business rules fairly separate.  This will keep your
> application much more flexible as more and more requirements are added
> over time.
>
> In your example code, you've got persistence embedded directly in ui
> code.  Should you ever decide to replace your perisistence layer with
> something else (say, replace toplink with hibernate, ibatis, or even
> raw jdbc), you will have to go in and modify every page class you've
> built that has persistence code in it.  In a large project, this is
> effectively impossible to do without destabilizing the codebase too
> much to be acceptable.  Therefore, most well architected apps will
> keep all perisistence code in a separate set of interfaces.  So long
> as you can create a persistence layer that maintains the same
> interface, you can replace one with another very simply.  This is
> where dependency injection becomes useful - Instead of injecting a
> toplink data access object into your page, you can inject a hibernate
> one instead.
>
> But wait, did I just say injecting a dao into the page?  Most of us
> would argue you never want to do that, for the following reason.
> Suppose you have a method in your DAO which stores an entity into the
> database.  If you are using your dao directly in your page class, then
> you either have to open and commit a transaction directly in your page
> (violating the rule about keeping persistence code out of your ui
> layer and once again locking you into a particular transaction
> mechanism, preventing you from switching between JDBC transactions,
> JTA transactions, etc), or else your DAO itself has to open the
> transaction, save the entity, and commit the transaction.  This would
> be fine in this circumstance.  Your persistence code would stay in
> your persistence layer, but now you have another problem.  Page1 may
> store just a single instance of the entity, so including transaction
> semantics around that store operation works just fine.  But now you
> have to add Page2, and Page2 wants to store two entities.  But if
> either store() fails (unique column conflict, for instance), you don't
> want to store() either of the entities.  So now your transaction
> within the store method won't work, since the first store() will be
> fully committed before the second store() fails, offering you no way
> to roll back.  So your only option is to implement another DAO method
> - one which takes a collection of entities and stores them all within
> a single transaction.  You can probably see that as your project
> grows, you are going to wind up with a lot of very similar methods,
> each different only in the transaction behaviour.
>
> The rule that you must be able to store both entities if you are going
> to store either one is considered a 'business rule' - an artificial
> constraint on what you are allowed to do.  Business rules frequently
> change over the life of a project, so once again, you want to keep
> your business logic firmly separated from your ui.  Again, this is
> accomplished by shoving your business logic into separate classes with
> a well defined interface and injecting instances of those interfaces
> into your page classes.  Now, your ui code doesn't need to know
> anything about transactions because your service layer is handling
> them.  Your ui can call a method to store() two entities and doesn't
> need to be concerned with the details of how that occurs or what is
> allowed.  All it knows is it either succeeded or failed based on an
> exception may catch. Once again, your ui layer is clean.  It is
> injected only with service interfaces.  Service objects are injected
> with DAO interfaces, and you've got a nice clean layer separation.
>
> Except for one thing.  You've got a bunch of transaction code sitting
> in your service layer, wrapped around calls into your DAOs, which no
> longer have any knowledge of transactions themselves.  This means
> there is still a strong binding between your service layer and your
> perisistence layer, making it very difficult to modify one without
> modifying the other.  That's generally considered a _bad_thing_ and
> should be avoided.  So this is where Spring steps in and provides some
> VERY useful functionality.  Spring gives a nice declarative mechanism
> (ie. you can set it up in a config file or annotation, rather than by
> writing code)  for forcing a transaction around any method of any
> object.  You can define a business method that calls multiple DAO
> methods and you can tell spring that anytime someone calls that
> method, you want a transaction to be started before the method
> executes, and the transaction to be committed when the method is
> completed without throwing an exception, or rolled back if an
> exception is caught.  Now you can remove all of that pesky transaction
> code from your service layer, giving you true independance from your
> persistence layer outside of the persistence interfaces, which should
> be generic across any persistence mechanism.  OK, you've still got a
> dependency in your config, but at least your code, which is the most
> complex and error prone piece of the application, is completely
> independant (that's why I prefer to avoid annotations for transaction
> declarations.  I don't want to recompile to change a transaction)
>
> A side benefit of all of this is that Spring is now responsible for
> all that boilerplate code that gets copied around everywhere for
> opening a connection, catching exceptions, closing the connection,
> catching more exceptions, etc.  Spring is widely used and well tested,
> so you can be confident that the boilerplate code it is using is
> correct.  The one caveat (and it is a small one), is that your
> persistence layer is required to use certain helper methods provided
> by spring which will ensure that your dao uses the connection that has
> the transaction on it.   However, the helper methods are incredibly
> useful and do much of the work involved in communicating with your
> database for you.  I don't know toplink, as I use hibernate, but let
> me give you a quick hibernate example.
>
> In a normal Hibernate DAO, if I wanted to store an object into the db,
> I'd do the following:
>
>     public void store(Event theEvent) {
>
>         Session session = HibernateUtil.getSessionFactory
> ().getCurrentSession();
>
>         try {
>             session.beginTransaction();
>             session.save(theEvent);
>             session.getTransaction().commit();
>         } catch (Exception e) {
>             try {
>                 session.getTransaction().rollback();
>             } catch (Exception e2) {
>             }
>         } finally {
>             try {
>                 HibernateUtil.getSessionFactory().close();
>             catch (Exception e3) {
>             }
>         }
>     }
>
> That's a lot of code, especially those obnoxious nested
> try...catch..finally blocks that are so common to all db programming
> in java.  Even without the transaction handling, I've still got to get
> the session and execute the store() method.
>
> Using the Spring hibernate helper class and configuration however, I
> can do the same thing in a single line of code:
>
>         public void store(Event theEvent) {
>             getHibernateTemplate().saveOrUpdate(theEvent);
>         }
>
> The HibernateTemplate already knows how to get the current session
> (which will already have a transaction started on it).  If the store
> method throws an exception, it will be propagated up and the
> transaction will automatically be rolledback.  Spring also translates
> database and ORM specific exceptions into nice generalized exceptions
> so that your application exception handling doesn't need to know about
> the ORM or db.  Otherwise, you have to know that error code 6453 in
> oracle is equivalent to error code 1234 in postgres, or else just
> respond to a generic SQLException.  Spring can throw a much more
> meaningul exception that will be the same no matter which db you use,
> allowing your app to respond much more intelligently to exceptions up
> to and including providing much more meaningful error messages to
> users and developers.
>
> There are methods provided for all the basic CRUD operations (create,
> retrieve, update, delete)  as well as various list methods and, of
> course, a mechanism for building complex queries with lots of
> parameters.  It saves an awful lot of code.
>
> So now, if you use all the advice I've offered so far, you've got the
> following:
>
> a DAO layer which has no transaction semantics and which uses Spring
> DAO base classes to handle all the complexity of db interaction,
> whether you use hibernate, iBatis, JDBC, or toplink.
> (
> http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/orm/toplink/package-summary.html
> and
> http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/orm/toplink/support/package-summary.html
> )
>
> You have a business service layer which ensures your application
> adheres to business rules..
>
> You have transactions that are assigned to your service methods
> declaratively (either through the spring config or via annotations.  I
> prefer the config file because I often like to set things up
> differently in a test environment compared to production and I don't
> want to have to recompile)
>
> You have a UI layer that knows nothing about any of this, other than
> the interfaces provided by your business service layer.
>
> You are now free to swap your web ui for a swing ui, WAP ui, command
> line ui, or anything else you care for, without being forced to ensure
> that all your business rules and persistence code is properly copied
> to the new ui layer.  You can also replace your perisistence layer
> with hibernate, jdbc, or anything else without touching a single line
> of code in either your service or web ui layers.  You've coded
> everything to a set of interfaces instead of specific classes.  This
> is important because it means you can easily drop different
> implementations of the same interface into your code via dependency
> injection, including injecting mock objects during testing in order to
> simulate production conditions.
>
> The one complaint I have about a rigidly layered application such as
> this is that it can force you into an unreasonable amount of typing to
> do simple things.  If you add a new DAO method to support some action,
> you've now got to add the method to the dao interface and the dao
> implementation. There is also a high probability you'll be adding a
> corresponding method to your service layer, so you've got to add
> methods to the service interface and the service implementation as
> well.  Then you've got to make sure you've applied the correct
> transaction semantics to the service method in question. It is a fair
> amount of cut and paste typing, which can be error prone, although
> errors are likely to be caught at compile time (unless you screw up
> your transaction declaration, which you won't detect until runtime),
> so it isn't a huge problem, other than the time involved and the
> repetitive stress injuries. I don't use an IDE, so I have some quick
> scripts which dump all the necessary method and transaction
> declarations into a file, and I can then just cut and paste the
> guaranteed correct declarations into the appropriate files (it was
> easier than trying to parse the files and inserting the code directly
> and it means I can relax a little on file/class naming conventions).
> Also, judicious use of base interfaces and base classes with generics
> means that you can often add a single method to a base class in order
> to get the functionality added for every single entity type in your
> application.
>
> OK, that was a ton of information, but hopefully you'll find it very
> useful, since you said you were new to Java web development.
>
> --sam
>
>
> On 12/7/06, Cyrille37 <cy...@gmail.com> wrote:
> > Hello
> >
> > D&J Gredler a �crit :
> > > I haven't used EntityManagers directly, but your code looks fine to
> me,
> > > especially if it works ;-)
> > > You may want to wrap your flush( ) call in a try/catch block in case
> > > something goes wrong, and roll back the transaction in the catch
> block.
> > It works, but I've made change because I've got only one EntityManager
> > for all the application.
> > In Toplink's examples I see that the create an EntityManager each time
> > they make a query.
> > So I've change flush() to merge(this_product) because object was
> > "detached" ...
> > Sorry, I'm not very clear ...
> >
> > > Once you get more comfortable with things (and if you're using
> > > Hibernate),
> > > you may want to check out some of the integration packages (Tapernate,
> > > Honeycomb, etc) that handle transaction scoping for you.
> > hmmm... Which scope ?
> > I could not imagine what they do. I'm to beginner with Java & Co.
> > Please, can you explain me a beat what a package like Tapernate or
> > Honeycomb will do.
> >
> > For da moment I'm using JPA (TopLink Essential).
> >
> > > Spring might also
> > > be a good option if you end up splitting your app up into presentation
> /
> > > service / persistence layers.
> > At the beginning of my exploration, I've try Spring with Tapestry and I
> > did not see what it will bring to me more than Hivemind.
> > Perhaps because I only the the object injection, and not other things
> > that Spring bring to us.
> >
> > Thanks for you support ;o)
> > Cyrille
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> > For additional commands, e-mail: users-help@tapestry.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: about Beanform and JPA (persistence)

Posted by andyhot <an...@di.uoa.gr>.
Cyrille37 wrote:
> Hello Sam,
>
> Thanks a lot for your long long explanation. It was really wonderfull
> for me.
> Now I've understood some architecture's best practices.

Indeed it was very helpful. Can't wait to see how
http://wiki.apache.org/tapestry/AnnotatedGuideToTapestrySource
develops!

BTW, I've found "Pojos in action" to be
an excellent resource on the subject.

>
> I've applied your methods to my little project using Spring2.
>
> Now I would like to practice the same little project with an
> Application Server. I've installed Glassfish.
> I will use Tapestry for the Web UI and make EJBs for services
> (business layer).
>
> So I've had a look at Hivemind's documentation about accessing EJBs
> from Hivemind to inject theirs references in Tapestry.
> But the service hivemind.lib.EJBProxyFactory Service seems to handle
> only Stateless session bean
> (http://hivemind.apache.org/hivemind-lib/EJBProxyFactory.html).
>
> So is it not possible to integrate Tapestry with EJBs services with
> Hivemind ?
> Have I to integrate Spring to permit Tapestry / EJBs interaction ?
>
> Thanks again to my master ;o)
> Best regards from your disciple.
> Cyrille.
>
>
> Sam Gendler a écrit :
>> I'll clarify a little.  In general, you want to keep persistence code,
> ...
>> OK, that was a ton of information, but hopefully you'll find it very
>> useful, since you said you were new to Java web development.
>>
>> --sam
>>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>
>


-- 
Andreas Andreou - andyhot@apache.org - http://andyhot.di.uoa.gr
Tapestry / Tacos developer
Open Source / J2EE Consulting 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: about Beanform and JPA (persistence)

Posted by Cyrille37 <cy...@gmail.com>.
Hello Sam,

Thanks a lot for your long long explanation. It was really wonderfull 
for me.
Now I've understood some architecture's best practices.

I've applied your methods to my little project using Spring2.

Now I would like to practice the same little project with an Application 
Server. I've installed Glassfish.
I will use Tapestry for the Web UI and make EJBs for services (business 
layer).

So I've had a look at Hivemind's documentation about accessing EJBs from 
Hivemind to inject theirs references in Tapestry.
But the service hivemind.lib.EJBProxyFactory Service seems to handle 
only Stateless session bean 
(http://hivemind.apache.org/hivemind-lib/EJBProxyFactory.html).

So is it not possible to integrate Tapestry with EJBs services with 
Hivemind ?
Have I to integrate Spring to permit Tapestry / EJBs interaction ?

Thanks again to my master ;o)
Best regards from your disciple.
Cyrille.


Sam Gendler a écrit :
> I'll clarify a little.  In general, you want to keep persistence code,
...
> OK, that was a ton of information, but hopefully you'll find it very
> useful, since you said you were new to Java web development.
>
> --sam
>



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Re: about Beanform and JPA (persistence)

Posted by Sam Gendler <sg...@ideasculptor.com>.
I'll clarify a little.  In general, you want to keep persistence code,
ui code, and business rules fairly separate.  This will keep your
application much more flexible as more and more requirements are added
over time.

In your example code, you've got persistence embedded directly in ui
code.  Should you ever decide to replace your perisistence layer with
something else (say, replace toplink with hibernate, ibatis, or even
raw jdbc), you will have to go in and modify every page class you've
built that has persistence code in it.  In a large project, this is
effectively impossible to do without destabilizing the codebase too
much to be acceptable.  Therefore, most well architected apps will
keep all perisistence code in a separate set of interfaces.  So long
as you can create a persistence layer that maintains the same
interface, you can replace one with another very simply.  This is
where dependency injection becomes useful - Instead of injecting a
toplink data access object into your page, you can inject a hibernate
one instead.

But wait, did I just say injecting a dao into the page?  Most of us
would argue you never want to do that, for the following reason.
Suppose you have a method in your DAO which stores an entity into the
database.  If you are using your dao directly in your page class, then
you either have to open and commit a transaction directly in your page
(violating the rule about keeping persistence code out of your ui
layer and once again locking you into a particular transaction
mechanism, preventing you from switching between JDBC transactions,
JTA transactions, etc), or else your DAO itself has to open the
transaction, save the entity, and commit the transaction.  This would
be fine in this circumstance.  Your persistence code would stay in
your persistence layer, but now you have another problem.  Page1 may
store just a single instance of the entity, so including transaction
semantics around that store operation works just fine.  But now you
have to add Page2, and Page2 wants to store two entities.  But if
either store() fails (unique column conflict, for instance), you don't
want to store() either of the entities.  So now your transaction
within the store method won't work, since the first store() will be
fully committed before the second store() fails, offering you no way
to roll back.  So your only option is to implement another DAO method
- one which takes a collection of entities and stores them all within
a single transaction.  You can probably see that as your project
grows, you are going to wind up with a lot of very similar methods,
each different only in the transaction behaviour.

The rule that you must be able to store both entities if you are going
to store either one is considered a 'business rule' - an artificial
constraint on what you are allowed to do.  Business rules frequently
change over the life of a project, so once again, you want to keep
your business logic firmly separated from your ui.  Again, this is
accomplished by shoving your business logic into separate classes with
a well defined interface and injecting instances of those interfaces
into your page classes.  Now, your ui code doesn't need to know
anything about transactions because your service layer is handling
them.  Your ui can call a method to store() two entities and doesn't
need to be concerned with the details of how that occurs or what is
allowed.  All it knows is it either succeeded or failed based on an
exception may catch. Once again, your ui layer is clean.  It is
injected only with service interfaces.  Service objects are injected
with DAO interfaces, and you've got a nice clean layer separation.

Except for one thing.  You've got a bunch of transaction code sitting
in your service layer, wrapped around calls into your DAOs, which no
longer have any knowledge of transactions themselves.  This means
there is still a strong binding between your service layer and your
perisistence layer, making it very difficult to modify one without
modifying the other.  That's generally considered a _bad_thing_ and
should be avoided.  So this is where Spring steps in and provides some
VERY useful functionality.  Spring gives a nice declarative mechanism
(ie. you can set it up in a config file or annotation, rather than by
writing code)  for forcing a transaction around any method of any
object.  You can define a business method that calls multiple DAO
methods and you can tell spring that anytime someone calls that
method, you want a transaction to be started before the method
executes, and the transaction to be committed when the method is
completed without throwing an exception, or rolled back if an
exception is caught.  Now you can remove all of that pesky transaction
code from your service layer, giving you true independance from your
persistence layer outside of the persistence interfaces, which should
be generic across any persistence mechanism.  OK, you've still got a
dependency in your config, but at least your code, which is the most
complex and error prone piece of the application, is completely
independant (that's why I prefer to avoid annotations for transaction
declarations.  I don't want to recompile to change a transaction)

A side benefit of all of this is that Spring is now responsible for
all that boilerplate code that gets copied around everywhere for
opening a connection, catching exceptions, closing the connection,
catching more exceptions, etc.  Spring is widely used and well tested,
so you can be confident that the boilerplate code it is using is
correct.  The one caveat (and it is a small one), is that your
persistence layer is required to use certain helper methods provided
by spring which will ensure that your dao uses the connection that has
the transaction on it.   However, the helper methods are incredibly
useful and do much of the work involved in communicating with your
database for you.  I don't know toplink, as I use hibernate, but let
me give you a quick hibernate example.

In a normal Hibernate DAO, if I wanted to store an object into the db,
I'd do the following:

    public void store(Event theEvent) {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        try {
            session.beginTransaction();
            session.save(theEvent);
            session.getTransaction().commit();
        } catch (Exception e) {
            try {
                session.getTransaction().rollback();
            } catch (Exception e2) {
            }
        } finally {
            try {
                HibernateUtil.getSessionFactory().close();
            catch (Exception e3) {
            }
        }
    }

That's a lot of code, especially those obnoxious nested
try...catch..finally blocks that are so common to all db programming
in java.  Even without the transaction handling, I've still got to get
the session and execute the store() method.

Using the Spring hibernate helper class and configuration however, I
can do the same thing in a single line of code:

        public void store(Event theEvent) {
            getHibernateTemplate().saveOrUpdate(theEvent);
        }

The HibernateTemplate already knows how to get the current session
(which will already have a transaction started on it).  If the store
method throws an exception, it will be propagated up and the
transaction will automatically be rolledback.  Spring also translates
database and ORM specific exceptions into nice generalized exceptions
so that your application exception handling doesn't need to know about
the ORM or db.  Otherwise, you have to know that error code 6453 in
oracle is equivalent to error code 1234 in postgres, or else just
respond to a generic SQLException.  Spring can throw a much more
meaningul exception that will be the same no matter which db you use,
allowing your app to respond much more intelligently to exceptions up
to and including providing much more meaningful error messages to
users and developers.

There are methods provided for all the basic CRUD operations (create,
retrieve, update, delete)  as well as various list methods and, of
course, a mechanism for building complex queries with lots of
parameters.  It saves an awful lot of code.

So now, if you use all the advice I've offered so far, you've got the following:

a DAO layer which has no transaction semantics and which uses Spring
DAO base classes to handle all the complexity of db interaction,
whether you use hibernate, iBatis, JDBC, or toplink.
(http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/orm/toplink/package-summary.html
and http://static.springframework.org/spring/docs/1.2.x/api/org/springframework/orm/toplink/support/package-summary.html
)

You have a business service layer which ensures your application
adheres to business rules..

You have transactions that are assigned to your service methods
declaratively (either through the spring config or via annotations.  I
prefer the config file because I often like to set things up
differently in a test environment compared to production and I don't
want to have to recompile)

You have a UI layer that knows nothing about any of this, other than
the interfaces provided by your business service layer.

You are now free to swap your web ui for a swing ui, WAP ui, command
line ui, or anything else you care for, without being forced to ensure
that all your business rules and persistence code is properly copied
to the new ui layer.  You can also replace your perisistence layer
with hibernate, jdbc, or anything else without touching a single line
of code in either your service or web ui layers.  You've coded
everything to a set of interfaces instead of specific classes.  This
is important because it means you can easily drop different
implementations of the same interface into your code via dependency
injection, including injecting mock objects during testing in order to
simulate production conditions.

The one complaint I have about a rigidly layered application such as
this is that it can force you into an unreasonable amount of typing to
do simple things.  If you add a new DAO method to support some action,
you've now got to add the method to the dao interface and the dao
implementation. There is also a high probability you'll be adding a
corresponding method to your service layer, so you've got to add
methods to the service interface and the service implementation as
well.  Then you've got to make sure you've applied the correct
transaction semantics to the service method in question. It is a fair
amount of cut and paste typing, which can be error prone, although
errors are likely to be caught at compile time (unless you screw up
your transaction declaration, which you won't detect until runtime),
so it isn't a huge problem, other than the time involved and the
repetitive stress injuries. I don't use an IDE, so I have some quick
scripts which dump all the necessary method and transaction
declarations into a file, and I can then just cut and paste the
guaranteed correct declarations into the appropriate files (it was
easier than trying to parse the files and inserting the code directly
and it means I can relax a little on file/class naming conventions).
Also, judicious use of base interfaces and base classes with generics
means that you can often add a single method to a base class in order
to get the functionality added for every single entity type in your
application.

OK, that was a ton of information, but hopefully you'll find it very
useful, since you said you were new to Java web development.

--sam


On 12/7/06, Cyrille37 <cy...@gmail.com> wrote:
> Hello
>
> D&J Gredler a écrit :
> > I haven't used EntityManagers directly, but your code looks fine to me,
> > especially if it works ;-)
> > You may want to wrap your flush( ) call in a try/catch block in case
> > something goes wrong, and roll back the transaction in the catch block.
> It works, but I've made change because I've got only one EntityManager
> for all the application.
> In Toplink's examples I see that the create an EntityManager each time
> they make a query.
> So I've change flush() to merge(this_product) because object was
> "detached" ...
> Sorry, I'm not very clear ...
>
> > Once you get more comfortable with things (and if you're using
> > Hibernate),
> > you may want to check out some of the integration packages (Tapernate,
> > Honeycomb, etc) that handle transaction scoping for you.
> hmmm... Which scope ?
> I could not imagine what they do. I'm to beginner with Java & Co.
> Please, can you explain me a beat what a package like Tapernate or
> Honeycomb will do.
>
> For da moment I'm using JPA (TopLink Essential).
>
> > Spring might also
> > be a good option if you end up splitting your app up into presentation /
> > service / persistence layers.
> At the beginning of my exploration, I've try Spring with Tapestry and I
> did not see what it will bring to me more than Hivemind.
> Perhaps because I only the the object injection, and not other things
> that Spring bring to us.
>
> Thanks for you support ;o)
> Cyrille
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: about Beanform and JPA (persistence)

Posted by Cyrille37 <cy...@gmail.com>.
Hello

D&J Gredler a écrit :
> I haven't used EntityManagers directly, but your code looks fine to me,
> especially if it works ;-)
> You may want to wrap your flush( ) call in a try/catch block in case
> something goes wrong, and roll back the transaction in the catch block.
It works, but I've made change because I've got only one EntityManager 
for all the application.
In Toplink's examples I see that the create an EntityManager each time 
they make a query.
So I've change flush() to merge(this_product) because object was 
"detached" ...
Sorry, I'm not very clear ...

> Once you get more comfortable with things (and if you're using 
> Hibernate),
> you may want to check out some of the integration packages (Tapernate,
> Honeycomb, etc) that handle transaction scoping for you.
hmmm... Which scope ?
I could not imagine what they do. I'm to beginner with Java & Co.
Please, can you explain me a beat what a package like Tapernate or 
Honeycomb will do.

For da moment I'm using JPA (TopLink Essential).

> Spring might also
> be a good option if you end up splitting your app up into presentation /
> service / persistence layers.
At the beginning of my exploration, I've try Spring with Tapestry and I 
did not see what it will bring to me more than Hivemind.
Perhaps because I only the the object injection, and not other things 
that Spring bring to us.

Thanks for you support ;o)
Cyrille



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: about Beanform and JPA (persistence)

Posted by D&J Gredler <dj...@gmail.com>.
I haven't used EntityManagers directly, but your code looks fine to me,
especially if it works ;-)

You may want to wrap your flush( ) call in a try/catch block in case
something goes wrong, and roll back the transaction in the catch block.

Once you get more comfortable with things (and if you're using Hibernate),
you may want to check out some of the integration packages (Tapernate,
Honeycomb, etc) that handle transaction scoping for you. Spring might also
be a good option if you end up splitting your app up into presentation /
service / persistence layers.

On 12/6/06, Cyrille37 <cy...@gmail.com> wrote:
>
> Hello,
>
> I'm coming back with a beginner question ;-)
>
> After 3 weeks of Java Web App discovering, I'm actually working with
> Tapestry 4.0.2, Netbeans 5.5 which give me easy data persistence support
> with JPA Toplink essential, and Tomcat5.5 and Mysql5.
>
> So I've finaly got something working with Beanform and JPA and I come to
> you to get comments and ideas and best practice.
>
> For the persistence, the method I've found is to do the following :
>
> * To remember with object I'm playing with :
>
>     @Persist("client")
>     public abstract int getProductId();
>     public abstract void setProductId(int productId);
>
> * To manage the Beanform's bean :
>
>     private Product _product ;
>     public Product getProduct()
>     {
>         if( this._product==null && this.getProductId()>0 )
>         {
>             this.setProduct(  this.loadProduct( this.getProductId ()) );
>         }
>         return this._product ;
>     }
>
>     public void setProduct( Product product )
>     {
>         this._product = product ;
>     }
>
> * For initializing the page at the first time :
>
>     public void activateExternalPage(Object[] parameters, IRequestCycle
> cycle)
>     {
>         int pid = Integer.parseInt( parameters[0].toString());
>         setProductId( pid );
>         this.setProduct ( this.loadProduct(pid) );
>     }
>
> * And finally to implement the Beanform 'save' listener :
>
>     public String save()
>     {
>         System.out.println( "ProductEdit.save()" );
>         if( this.getDelegate().getHasErrors() )
>             return null;
>         EntityManager em = getDataManagerFactory().GetEntityManager();
>         /*** I find that method a beat strange but it works ! ***/
>         em.getTransaction ().begin();
>         em.flush();
>         em.getTransaction().commit();
>
>         return "Home";
>     }
>
> Thanks to have read my poetry ;-)
> Cyrille.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>