I regret that this information was posted before it was finalized.

I will continue research and repost in about a week or so.

My goal was to get input from five to ten people and come to a
consensus for best practices (this should clear up some of the major
disagreements and not waste a great deal of time within the group). 
There really isn't an architectural blueprint on the Struts site and
the BluePrints on the Sun site do not apply specifically to Struts. 
I think a Struts BluePrint and clear reference implementation is
needed.

Mike


--- Struts Newsgroup <[EMAIL PROTECTED]> wrote:
> Subject: Re: Struts Architecture
> From: Vic C <[EMAIL PROTECTED]>
>  ===
> I would call Pet Cemetery "Complexia very BAD Practices for
> suckers". 
> This was designed to make your application need lots of HW and a
> new Sun 
> server for each multiple of  50 users. See 
> http://www.softwarereality.com for 101 reasons why this is bad. 
> This is 
> not something that a production or operational system does, this
> would 
> only work in a lab environment with lots of overhead. Companies
> that do 
> this find Java expensive to develop and operate.
> Java is just fine, blame your software engineer/architect who would
> 
> think of picking this. The best solution is always low tech.
> 
> This would be a good practice IMO:
> 1. Dispatch a "new" parm to action.
> 2. Action asks frmBean.new();
> 3. New in frmBean does DAO.new() to create a row that will hold a
> new 
> row. (It might go to db to get MetaData). Also this same action
> does all 
> CRUD, not just new. Same with DAO and frmBean, they do all the
> CRUD, not 
> just new. (so action has new(); update(); delete(); save(); that
> get 
> dispatched to it; as does the DAO, etc.) Look at my code.
> 4. With the empty rowholder with matching meta data in scope, it
> goes to 
> page.
> 5. Use inputs some date, and submits a save. (Struts auto populates
> setters)
> 6. Action gets a "save" parm.
> 6.a You call frmBean.validate(); and redirecte if any messages.
> 7. Action asks frmBeansave().
> 8. Bean asks DAO to update.
> 9. Update enumerates rows; and columns, construction an insert
> statement.
> 
> Anyway, I have taken above to production just fine.
> 
> Simple MVC, not Complexia. Again new people over engineer. KISS is
> much 
> more powerful and doable in Production.
> I suggest you always unit test a bean to be able to insert to db,
> before 
> placing it in Struts. Write a console app to insert into a bean. If
> it 
> works in console app, it will work in Struts. Oddly, if it does not
> work 
> in a console unit test; it will not work in Struts, and it is not
> Struts 
> fault.  Sun only makes money on J2EE license, and ... news flash,
> sales 
> people lie,  a lot.
> My db sample does exactly above.
> 
> Mike Duffy wrote:
> > Vic,
> > 
> > Please take a few moments to review the following, I would value
> your
> > opinion before I send it to the Struts user group.
> > 
> > Thanks in advance for your time and insight.
> > 
> > Mike
> > 
> >
>
#####################################################################
> > 1. User enters information in an HTML form to create an account. 
> > 
> > 2. Struts Controller creates and populates a new AccountForm with
> > user input.
> > 
> > 3. Controller invokes AccountForm.validate() (assume validation
> > passes).
> > 
> > 4. Controller invokes AccountAction.perform().
> > 
> > 5. From within the method AccountAction.perform(), the form
> argument
> > is cast to an AccountForm object.
> > 
> > 6. From within the method AccountAction.perform(), the method
> > AccountForm.createAccount() is called to create an Account
> object.
> > 
> > The Account object is one of several "ComponentObjects" that
> > represent the data model of the system and contain getters and
> > setters for primitive values and other ComponentObjects (in this
> > example the Account ComponentObject contains an "Address"
> > ComponentObject and a "User" ComponentObject).  The terms
> > "ValueObject" and "DataTransferObject" have been used in this
> thread,
> > but they seem to have conflicting definitions and they seem to be
> > used for transferring data across a network, not for
> communicating
> > between classes.  If you examine the "PetStore" reference
> > implementation you will see that the classes in the "Model"
> > subpackages are named with common names (Category, Page, Item,
> > Product).  
> > 
> > As a comment to my initial question that started this thread, the
> > FormBean never leaves the Action object.  The FormBean is
> decomposed
> > into one or more ComponentObjects that represent the data model
> of
> > the system.
> > 
> > 7. From within the method AccountForm.getAccount() a utility
> method
> > in a mapping class could be called to perform the mapping.
> > 
> > If you coordinate the property names between your FormBeans and
> your
> > ComponentObjects you can use a very handy method,
> copyProperties(),
> > in org.apache.commons.beanutils.PropertyUtils.  In this case you
> can
> > probably do the mapping right in your AccountForm .getAccount()
> > method.
> > 
> > 8. From within the method AccountAction.perform() an instance of
> > AccountDelegate is created.
> > 
> > No business logic processing takes place in AccountAction; this
> class
> > is considered to be in the web layer.  AccountDelegate is located
> in
> > the business logic layer.  The AccountDelegate class does not do
> any
> > "heavy" business logic processing.  This class simply helps
> things
> > along by coordinating the business logic functions at a central
> > point.
> > 
> > If you examine the "PetStore" reference implementation you will
> see
> > that these types of classes are called "Helper" classes (e.g.,
> > "AccountHelper").  I have also seen the term "Worker" used for
> these
> > types of classes.  In my opinion, the term "Delegate" seems more
> > appropriate because the action from AccountAction is delegated to
> > AccountDelegate.
> > 
> > 9. From within the method AccountAction.perform() the method
> > AccountDelegate.createAccount(Account account) is called to
> create an
> > account in the data store.  
> > 
> > If "heavy weight" business logic processing was required the
> method
> > AccountDelegate.createAccount() might call worker methods in
> other
> > classes.  For example, if income information was entered in the
> > original HTML form a method in a UserWorker class could be called
> to
> > evaluate status based on income and zip code.  This status value
> > would then be set in the User object and eventually entered into
> the
> > data store.
> > 
> > 10. From within the method AccountDelegate.createAccount() the
> method
> > AccountDAOImpl.getInstance() is called. 
> > 
> > AccountDAOImpl is a singleton which reduces the creation of
> objects. 
> > The strings for the SQL prepared statements are declared as
> "public
> > static final".
> > 
> > AccountDAOImpl implements the interface AccountDAO.  This
> interface
> > allows for alternate possibilities in retrieving data. 
> > AccountDelegate will be able to use any object that implements
> > AccountDAO.  At some future time there might be an
> AccountDAOSoapImpl
> > or a AccountDAOFutureImpl. 
> > 
> > AccountDAOImpl and its helper classes completely encapsulate the
> data
> > access layer for CRUDing accounts (create, retrieve, update, and
> > delete).  The methods in AccountDAOImpl take ComponentObjects as
> > arguments and return ComponentObjects or void.  Connections and
> > transactions are managed in the data access layer not the
> business
> > logic layer.  The data access layer will have helper classes to
> > manage connections and transactions (any system that has a
> > significant number of transactions should probably use an EJB
> > implementation).
> > 
> > In essence, when a class in the business logic layer calls a
> method
> > in the data access layer, a ComponentObject is sent in and a
> > ComponentObject is returned; the business logic layer does not
> affect
> > any functionality in the data access layer and the data access
> layer
> > does not affect any functionality in the business logic layer. 
> > FormBeans and ComponentObjects should not contain data access
> calls
> > to "create themselves"; they should be created by methods in the
> data
> > access layer.
> > 
> > From the Java BluePrints website:  
> > 
> > "A clear separation of concern between access objects and
> components
> > will enable a component to be adapted to different enterprise
> > information system resources. For example, a component can use an
> > access object to adapt its persistent state management to a
> different
> > database schema or to a different type of database." 
> >
>
http://java.sun.com/blueprints/guidelines/designing_enterprise_applications/eis_tier/programming_access/index.html
> > 
> > 11. From within the method AccountDelegate.createAccount() the
> method
> > AccountDAOImpl.createAccount(Account account) is called. 
> > 
> > 12. From within the method AccountDAOImpl.createAccount() a
> method is
> > called to get a connection from the connection pool.
> > 
> > 13. From within the method AccountDAOImpl.createAccount() the
> method
> > Connection.setAutoCommit(false) is called (we do not want our
> > transaction to commit unless every part of the transaction
> succeeds).
> > 
> > When updating multiple tables in the same transaction the updates
> > must be done through the same connection.  In this example, we
> will
> > assume three tables need to be updated:  tblAccount, tblUser, and
> > tblAddress.
> > 
> > 14. From within the method AccountDAOImpl.createAccount() the
> method
> > account.getUser() is called (the Account object contains a User
> > object).
> > 
> > 15. From within the method AccountDAOImpl.createAccount() the
> method
> > UserDAOImpl.getInstance() is called.
> > 
> > 16. From within the method AccountDAOImpl.createAccount() the
> method
> > UserDAOImpl.createUser(Connection connection, User user) is
> called.
> > 
> > Any exceptions that occur in UserDAOImpl.createUser() are thrown
> to
> > the calling method: AccountDAOImpl.createAccount().  If an
> exception
> > is caught by AccountDAOImpl.createAccount() the method
> > connection.rollback() is called.   
> > 
> > The class UserDAOImpl may also have a method createUser(User
> user)
> > that independently gets a connection and creates a user. 
> > 
> > 17. From within the method AccountDAOImpl.createAccount() the
> method
> > account.getAddress() is called (the Account object contains a
> Address
> > object).
> > 
> > 18. From within the method AccountDAOImpl.createAccount() the
> method
> > AddressDAOImpl.getInstance() is called.
> > 
> > 19. From within the method AccountDAOImpl.createAccount() the
> method
> > AddressDAOImpl.createAddress(Connection connection, Address
> address)
> > is called.
> > 
> > Any exceptions that occur in AddressDAOImpl.createAddress() are
> > thrown to the calling method: AccountDAOImpl.createAccount().  If
> an
> > exception is caught by AccountDAOImpl.createAccount() the method
> > connection.rollback() is called.
> > 
> > The class AddressDAOImpl may also have a method
> createAddress(Address
> > address) that independently gets a connection and creates an
> address.
> > 
> > 20. If no exceptions are caught from the methods
> > UserDAOImpl.createUser() or AddressDAOImpl.createAddress() the
> method
> > AccountDAOImpl.createAccount() creates an entry in tblAccount. 
> If no
> > exception is generate when updating tblAccount the method
> > connection.commit() is called and the connection is released in
> the
> > "Finally" block of AccountDAOImpl.createAccount().  If exceptions
> > occur, the method connection.rollback() is called.
> > 
> > When I catch an SQL exception, I usually wrap it as a RunTime
> > exception and rethrow it.  I'll have my error.jsp display an
> > appropriate message.  As a general rule, when the only thing you
> are
> > going to do is display a message there is no need to create a
> > specific exception.
> > 
> > 21. Assuming nothing has gone wrong, we are now back in our
> > AccountAction.perform() method and Struts will redirect to the
> > appropriate forward page.
> > 
> > When necessary, objects that need to be placed in the session or
> > request are placed from within the perform() method in the Action
> > class, not by methods from classes in the business logic layer;
> the
> > business logic layer does not affect any functionality in the web
> > presentation/management layer and the web presentation/management
> > layer does not affect any functionality in the business logic
> layer.
> > 
> > The general idea is to keep the layers of an application
> separate. 
> >
>
####################################################################
> > 
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! Health - your guide to health and wellness
> > http://health.yahoo.com
> 
> 
> 
> --
> To unsubscribe, e-mail:  
> <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
> 


__________________________________________________
Do You Yahoo!?
Yahoo! Health - your guide to health and wellness
http://health.yahoo.com

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to