Vic, Can you please stop spawning off topic discussions, especially ones which you know are controversial, and at the very least not about Struts. This is not a Struts centric discussion, and if you want to poach newbies, there are better lists to go marauding in.
Arron. Struts Newsgroup (@Basebeans.com) 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]> > > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>