Discussions

News: Mandragora framework can be the model for your new MVC project

  1. Typically, with MVC, the Controller has to update or query the Model, and the View can query the Model as well. The Model should be decoupled from Controller or View by a Business Delegate tier. So all accesses to the model should pass trough the BD (Business Delegate). If you use a MVC pattern in the application that you have to design and implement, you can choose between lots of frameworks , as Struts, for the controller and the view; Mandragora framework (http://mandragora.sourceforge.net/) would be the infrastructure for the Model providing more than one hundred of business delegate methods, that your controller, has just to call, without worrying about their implementation, but you can trust that the entire structure follows the J2ee patterns, as suggested by the structure presented at http://www.corej2eepatterns.com/Patterns2ndEd/index.htm . So just do bd.findByPrimarykey(....) or bd.storePathsCascade(...), or bd.addAllToCollection(...), or bd.addTreeToTree(...), bd.addToRetainInCollectionTreeLeaves(...), bd.findCollectionByLogicCondition(..) and much more, to execute very complex operations and queries such storing or modifying very complex objects in one shot. For example if in your controller you do: try { BD bd = ServiceLocator.getInstance().getManagerBD(); AuthorVO authorVO = (AuthorVO)bd.findByPrimaryKey(Author.class,"manzoni"); } catch (ApplicationException e) { //manage the exception } authorVO will be the instance of the Author class with key "manzoni" that is stores in your database. (see http://mandragora.sourceforge.net/quickstart.html to see how to start quickly, and http://mandragora.sourceforge.net/referenceguide/bd-api-guide.html, or /and http://mandragora.sourceforge.net/apidocs/index.html looking for BD to see all the bd methods available). Let's see a bit more in details. --------------------------------- The core of Mandragora are four interfaces: BD, ServiceFacade, ApplicationService and DAO. The methods of the BD implementation use, to do their job, methods of some ServiceFacade implementation, that use some methods of some ApplicationService and DAO implementations; the ApplicationService implementation use method of some DAO implementation. We said ServiceFacade, and not Session Facade, because as suggested in http://www.corej2eepatterns.com/Patterns2ndEd/ServiceFacade.htm when you design enterprise applications that do not use EJB components, you still need to provide a behavior similar to the Session Façades. But, instead of using session beans, one can use POJOs to implement the facades, and in order to provide a common vocabulary to discuss both POJO Facades and Session Façades, they introduce the term service facades. Service facades are business-tier facades that are implemented either as POJOs or session beans. The client of Mandragora accesses the models trough the BD, calling its methods and providing input parameters, that are pushed down into the structure, where each tier does its job to collaborate to the final result. Each tier lookup the right implementation of the next needed tier using the ServiceLocator. The client looks up the right BD implementation with ServiceLocator as well. BD Lookup --------------------------------------- In the above example we saw how the default BD implementation is returned by BD bd = ServiceLocator.getInstance().getManagerBD(); and this default BD implementation is the class it.aco.mandragora.bd.impl.pojo.PojoManagerBD, but this can be changed to have a different default BD. (See http://mandragora.sourceforge.net/referenceguide/lookup-and-mapping.html#Look_up_a_BD_implementation). To lookup a BD implementation there is an other ServiceLocator method: getManagerBD(String bdFactoryClassName, String bdClassName) The ServiceLocator doesn't look up the BD implementation directly, but trough a factory of BD implementation, so bdFactoryClassName specifies which is the BD factory , while bdClassName specifies which BD implementation the specified BD factory has to look up. Both the input string parameter have to be mapped in Mandragora.properties with the real BDFactory and with the real BD. So for example if we do: BD bd = ServiceLocator.getInstance().getManagerBD("myBDFactory", "myImplBD") putting in Mandragora.properties the entries: myBDFactory=myPath.someBDFactory myImplBD=myPath.someImplBD bd will be an instance of myPath.someImplBD and it will be instanced by myPath.someBDFactory. So just changing the mapping we change the implementation without affecting the client. You can choose one of the existing BD implementation, with its 100 methods ready to be used, or write your own implementation, or extending some existing one with some method that you need and not exists, allowing you, if you are generic enough, to reuse more and more time. (See http://mandragora.sourceforge.net/referenceguide/how-to-extend.html). ServiceFacade Lookup ------------------------------------------------ In the same way as just described, BD to do its job needs ServiceFacade, and of course each BD implementation lookup the needed ServiceFacade implementation trough the ServiceLocator with the same mechanism. For example for the BD implementation PojoManagerBD, the ServiceFacadeFactory is specified in Mandragora.properties by the entry PojoManagerBD.ServiceFacadeFactoryClass, while the serviceFacade implementation is specified by PojoManagerBD.ServiceFacadeClass. So in Mandragora.properties (that must be in your classpath of course) there is PojoManagerBD.ServiceFacadeFactoryClass=it.aco.mandragora.serviceFacade.concreteFactory.DefaultServiceFacadeFactory PojoManagerBD.ServiceFacadeClass=it.aco.mandragora.serviceFacade.pojoFacade.PojoFacade But changing it for other mappings you can use other factories and other implementations, that you can write. For example doing: PojoManagerBD.ServiceFacadeFactoryClass=myPath.MyServiceFacadeFactory PojoManagerBD.ServiceFacadeClass=myPath.MyServiceFacade. you are choosing which ServiceFacade factory and implementation PojoFacade has to use, without touching it. We are going now to follow this discussion with ApplicationService and DAO. ApplicationService and DAO lookup ---------------------------------------------- We said before that the ServiceFacade must use ApplicationService and DAO factories and implementations. How to specify them? Well in the same way. In Mandragora.properties (http://mandragora.sourceforge.net/referenceguide/mandragora-properties.html) there are the entries: PojoFacade.ApplicationServiceFactoryClass=it.aco.mandragora.as.concreteFactory.DefaultApplicationServiceFactory PojoFacade.ApplicationServiceClass=it.aco.mandragora.as.impl.ImplApplicationService PojoFacade.DAOFactoryClass=it.aco.mandragora.dao.concreteFactory.DefaultDAOFactory PojoFacade.DAOClass=it.aco.mandragora.dao.impl.ojb.pb.OjbPbDAO Just changing these mappings you decide which ApplicationService and DAO the PojoFacade will have to use. Analogously the chosen it.aco.mandragora.as.impl.ImplApplicationService need a DAO to work as well, and this is specified by the entries: ImplApplicationService.DAOFactoryClass=it.aco.mandragora.dao.concreteFactory.DefaultDAOFactory ImplApplicationService.DAOClass=it.aco.mandragora.dao.impl.ojb.pb.OjbPbDAO So as we stated at the beginning, when you call a business delegate method, for example: bd.createMissingRelationshipElement(aValueObject, "aCollectionName", "anAttributeName") this method will do all your job respecting the structure of the J2ee patterns, and you can configure externally with Mandragora.properties file, at each tier which is the real implementation that have to do the work, and who is the factory responsible to instance. For example, the only DAO implementation coming with Mandragora is it.aco.mandragora.dao.impl.ojb.pb.OjbPbDAO, that is implemented with the O/R mapper Apache Ojb, but if you want to use Hibernate, just get the DAO interface and implement it with Hibernate, specify for example: PojoFacade.DAOClass=myPath.MyHibernateDAO ImplApplicationService.DAOClass=myPath.MyHibernateDAO and if you want you can compare, or improve the existing implementations. The structure already exists, it follow the j2ee patterns, you have ready to be used 100 methods of the most common and reusable ones, so just focus your attention on the core logic of your application, and save the lot of time you use to spend repeating the same annoying things. If you don't find a method. ---------------------------------------------------------- For example, of course in your application you will need some method such: doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...). How can Mandragora help? Easy.(see http://mandragora.sourceforge.net/referenceguide/how-to-extend.html) 1) Write a new interface that extend BD with your method. Let's call it UserBD 2) Write a new class that implements UserBD, extend the BD implementation that you prefer, and of course implement your method doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...). Let's call it ImplUserBD 3) Map it in Mandragora.properties and use it. So, for example, if you want to use as BD factory the class it.aco.mandragora.bd.concreteFactory.DefaultBDFactory just put in Mandragora.properties MyClient.BDFactoryClass=it.aco.mandragora.bd.concreteFactory.DefaultBDFactory MyClient.BDClass=myPath.ImplUserBD then in your client try { ImplUserBD bd = (ImplUserBD)ServiceLocator.getInstance().getManagerBD("MyClient.BDFactoryClass", "MyClient.BDClass"); bd.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...); } catch (ApplicationException e) { //manage the exception } Well, on a side, this keeps very clean your controller, so it can be very useful, but on an other side you could complain that Mandragora is not helpful, when you can't find a method suitable for you in the existing ones, because nothing can't avoid you to write your method. That's true, of course,but let's go on, to see how Mandragora can help you to write you very complex method, core of all your application. How to write the BD method doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) ----------------------------------------------------------------------------------------------------- First of all, your new class myPath.ImplUserBD is a BD class, so it should use a ServiceFacade, and your new method must too. Let's suppose you are extending the it.aco.mandragora.bd.impl.pojo.PojoManagerBD or it.aco.mandragora.security.bd.impl.SecurityManagerImplBD (for the other implementation it.aco.mandragora.bd.impl.SLSB.SLSBManagerBD see http://mandragora.sourceforge.net/referenceguide/ejb.html). Of course you want to use the ServiceFacade in the same above way, forcing your ImplUserBD to read the ServiceFacade to be used, and the factory that have to instance it, in Mandragora.properties. This can be done in two ways: 1) initializing the two protected static variables ServiceFacadeFactoryClassName and ServiceFacadeClassName when ImplUserBD is instanced (see http://mandragora.sourceforge.net/referenceguide/how-to-extend.html#BD) ServiceFacadeFactoryClassName = "ImplUserBD.ServiceFacadeFactoryClass" ; ServiceFacadeClassName = "ImplUserBD.ServiceFacadeClass" ; 2) Overwrite in ImplUserBD the getServiceFacade() method in this way: protected ServiceFacade getServiceFacade()throws ApplicationException{ try{ return ServiceLocator.getInstance().getServiceFacade("ImplUserBD.ServiceFacadeFactoryClass","ImplUserBD.ServiceFacadeClass"); }catch (ServiceLocatorException e) { log.error("ServiceLocatorException caught in ImplUserBD.getContextServiceFacade(): " + e.toString()); throw new ApplicationException("ApplicationException thrown in ImplUserBD.getContextServiceFacade()" + e.toString(),e); } } In both case put in Mandragora.properties ImplUserBD.ServiceFacadeFactoryClass=it.aco.mandragora.serviceFacade.concreteFactory.DefaultServiceFacadeFactory #this is the ServiceFacade implementation you have to write ImplUserBD.ServiceFacadeClass=myPath.ImplUserServiceFacade Now your new method should use some ServiceFacade method to do the job, but if you could not find a BD method suitable, probably there is not a ServiceFacade method too. That's why you have to write a new ServiceFacade implementation, that we call myPath.ImplUserServiceFacade, with the famous method doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten that has to be called by your BD implementation. So the implementation of the your method doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) in your ImplUserBD should just be: public void doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) throws ApplicationException{ try{ UserServiceFacade userServiceFacade = (UserServiceFacade) getServiceFacade(); userServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...); }catch (Exception e) { throw new ApplicationException("Exception thrown in ImplUserBD.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } } You still can't see the benefits of Mandragora, moreover you had to write classes, interfaces, configure a properties file etc.(well if you fix in the job done, you can see it can't take more than 10 minutes, you still didn't do nothing), and you still did not implement the method , as you just delegated to the ServiceFacade (I think this tier is called business delegate because it delegates). How to write the ServiceFacade method doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) ---------------------------------------------------------------------------------------------------------------- We have to write a new ServiceFacade implementation, and let's suppose that we want to do that extending the PojoFacade (if you wish to use the Session Facade have look at http://mandragora.sourceforge.net/referenceguide/ejb.html). So you have to do: 1) Write a new interface that extend ServiceFacade with your method. Let's call it UserServiceFacade 2) Write a new class that implements UserServiceFacade, extends the it.aco.mandragora.serviceFacade.pojoFacade.PojoFacade, and of course implement your method doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...). Let's call it ImplUserServiceFacade 3) We saw above how to map it in Mandragora.properties to use it in ImplUserBD: ImplUserBD.ServiceFacadeFactoryClass=it.aco.mandragora.serviceFacade.concreteFactory.DefaultServiceFacadeFactory ImplUserBD.ServiceFacadeClass=myPath.ImplUserServiceFacade Being ImplUserServiceFacade a ServiceFacade implementation, it will need an ApplicationService implementation and a DAO implementation, with its factory to be specified, and as always, we want such implementations and factories could be specified in Mandragora.properties. This can be done in the now usual two ways : 1) initializing the four protected static variables ApplicationServiceFactoryClassName, ApplicationServiceClassName, DAOFactoryClassName, DAOClassName when ImplUserServiceFacade is instanced (see http://mandragora.sourceforge.net/referenceguide/how-to-extend.html) ApplicationServiceFactoryClassName = "ImplUserServiceFacade.ApplicationServiceFactoryClass" ; ApplicationServiceClassName = "ImplUserServiceFacade.ApplicationServiceClass" ; DAOFactoryClassName = "ImplUserServiceFacade.DAOFactoryClass" ; DAOClassName = "ImplUserServiceFacade.DAOClass" ; 2) Overwrite in ImplUserServiceFacade the getApplicationService() and getDAO() methods in this way: protected ApplicationService getApplicationService()throws ServiceFacadeException{ try{ return ServiceLocator.getInstance().getApplicationService("ImplUserServiceFacade.ApplicationServiceFactoryClass","ImplUserServiceFacade.ApplicationServiceClass"); }catch (ServiceLocatorException e) { log.error("ServiceLocatorException caught in ImplUserServiceFacade.getApplicationService(): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.getApplicationService()" + e.toString(),e); } } protected DAO getDAO()throws ServiceFacadeException{ try{ return ServiceLocator.getInstance().getDAO("ImplUserServiceFacade.DAOFactoryClass","ImplUserServiceFacade.DAOClass"); }catch (ServiceLocatorException e) { log.error("ServiceLocatorException caught in ImplUserServiceFacade.getDAO(): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.getDAO()" + e.toString(),e); } } In both case put in Mandragora.properties ImplUserServiceFacade.ApplicationServiceFactoryClass=it.aco.mandragora.as.concreteFactory.DefaultApplicationServiceFactory ImplUserServiceFacade.ApplicationServiceClass=myPath.ImplUserApplicationService ImplUserServiceFacade.DAOFactoryClass=it.aco.mandragora.dao.concreteFactory.DefaultDAOFactory ImplUserServiceFacade.DAOClass=myPath.ImplUserDAO Note that myPath.ImplUserApplicationService and myPath.ImplUserDAO can be existing implementations coming with Mandragora, or be written by your own. This is the point where Mandragora helps, when you can't find a suitable BD method. Now that in your ServiceFacade implementation you have to write it, probably you don't have to do all the works, because you can write it in terms of the existing ApplicationService and DAO methods. For example it could be that your method could be something like this: public void doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) throws ServiceFacadeException{ try { DAO dao = getDAO(); ApplicationService applicationService = getApplicationService(); applicationService.method1(...); dao.method2(...); .... applicationService.methodN(...); } catch (ApplicationServiceException e) { log.error("ApplicationServiceException caught in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); }catch (DataAccessException e) { log.error("DataAccessException caught in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } catch (Exception e) { log.error("Exception caught in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } } Now, of course you can say that it could be the case you are not so lucky, so it is impossible to express your method just in terms of the existing ones. Right. But this is the point: not just in terms of. I mean that surely the existing methods can do part of your work. Surely, being such methods so usual, and so many, that if you decompose properly the logic of the job you have to do, surely the existing ApplicationService and DAO can do a big part of your work. So probably the doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten in the ServiceFacade tier will be something like this: public void doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) throws ServiceFacadeException{ try { UserDAO userDao = (UserDAO)getDAO(); UserApplicationService userApplicationService = (UserApplicationService)getApplicationService(); userApplicationService.method1(...); userDao.method2(...); .... userApplicationService.methodN(...); userApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten1(....); userDao.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten2(...) ; } catch (ApplicationServiceException e) { log.error("ApplicationServiceException caught in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); }catch (DataAccessException e) { log.error("DataAccessException caught in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } catch (Exception e) { log.error("Exception caught in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserServiceFacade.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } } As you have seen you need some ApplicationService and DAO methods that doesn't exist. To write them you have to do the same done for BD and ServiceFacade. How to write the ApplicationService methods doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten1(....) ---------------------------------------------------------------------- We have to write a new ApplicationService implementation with the new methods, and let's suppose that we want to do that extending it.aco.mandragora.as.impl.ImplApplicationService. 1) Write a new interface that extend ApplicationService with your method. Let's call it UserApplicationService 2) Write a new class that implements UserApplicationService, extends ImplApplicationServiceand and of course implement your methods doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...). Let's call it ImplUserApplicationService 3) We saw above how to map it in Mandragora.properties to use it in ImplUserBD: ImplUserServiceFacade.ApplicationServiceFactoryClassit.aco.mandragora.as.concreteFactory.DefaultApplicationServiceFactory ImplUserServiceFacade.ApplicationServiceClass=myPath.ImplUserApplicationService All ApplicationService implementations, so ImplUserApplicationService as well, need DAO to do the job, and which implementation to use, with its factory, again we want to be configurable in Mandragora.properties. Again this can be done in two ways: 1) initializing the two protected static variables DAOFactoryClassName, DAOClassName when ImplUserApplicationService is instanced (see http://mandragora.sourceforge.net/referenceguide/how-to-extend.html) DAOFactoryClassName = "ImplUserApplicationService.DAOFactoryClass" ; DAOClassName = "ImplUserApplicationService.DAOClass" ; 2) Overwrite in ImplUserApplicationService the getDAO() methods in this way: protected DAO getDAO()throws ServiceFacadeException{ try{ return ServiceLocator.getInstance().getDAO("ImplUserApplicationService.DAOFactoryClass","ImplUserApplicationService.DAOClass"); }catch (ServiceLocatorException e) { log.error("ServiceLocatorException caught in ImplUserApplicationService.getDAO(): " + e.toString()); throw new ServiceFacadeException("ServiceFacadeException thrown in ImplUserApplicationService.getDAO()" + e.toString(),e); } } In both case put in Mandragora.properties ImplUserApplicationService.DAOFactoryClass=it.aco.mandragora.dao.concreteFactory.DefaultDAOFactory ImplUserApplicationService.DAOClass=myPath.ImplUserDAO Again myPath.ImplUserDAO could be the existing it.aco.mandragora.dao.impl.ojb.pb.OjbPbDAO coming with Mandragora or can be a your own DAO implementation. About the DAOFactory, just say that (as we done for the other tiers) we use the existing one, to not complicate to much. Anyway if you want to change it see http://mandragora.sourceforge.net/referenceguide/how-to-extend.html#Write_your_DAO_Factory Let's write now in the ImplUserApplicationService the new methods doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten public void doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) throws ApplicationServiceException{ try{ DAO dao = getDAO(); do a piece of work ...... dao.method1(....); ..... do an other piece of work ..... dao.method2(....); ........ }catch (DataAccessException e) { log.error("DataAccessException caught in ImplUserApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ApplicationServiceException("ApplicationServiceException thrown in ImplUserApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); }catch (Exception e) { log.error("Exception caught in ImplUserApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ApplicationServiceException("ApplicationServiceException thrown in ImplUserApplicationService.rdoPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } } Again you can see, that even if at the ServiceFacade tier I couldn't express the missing ServiceFacade method just in terms of the existing ApplicationService and DAO methods, I could express part of the job in terms of the existing ApplicationService and DAO methods, and to do the other part of the job I need new ApplicationService and DAO methods, but, about the new ApplicationService methods, probably, I don't have to do the whole job, becuase probably I can express the doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten in the ApplicationService in terms of existing DAO methods. Again, it could be I'm not so lucky and the existing DAO methods are not enough for the partial job at ApplicationService tier, but I'm sure that they can give you an hand, and do a part of the job, and for the remaining part, you have to write some DAO methods more. In such case the doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten at the ApplicationService tier would be: public void doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...) throws ApplicationServiceException{ try{ UserDAO userDao = (UserDAO)getDAO(); do a piece of work ...... userDao.existingmethod1(....); ..... do an other piece of work here at ApplicationService tier ..... userDao.existingmethod2(....); do an other piece of work at ApplicationService tier ........ userDao.myNewDAOMethod(....); ......... }catch (DataAccessException e) { log.error("DataAccessException caught in ImplUserApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ApplicationServiceException("ApplicationServiceException thrown in ImplUserApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); }catch (Exception e) { log.error("Exception caught in ImplUserApplicationService.doPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...): " + e.toString()); throw new ApplicationServiceException("ApplicationServiceException thrown in ImplUserApplicationService.rdoPartialPartOfTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...)" + e.toString(),e); } } Let's see now how to write the new DAO methods How to write new DAO methods --------------------------------------- To have more detail about this you can have a look at http://mandragora.sourceforge.net/referenceguide/how-to-extend.html#DAO We have to write a new DAO implementation with the new methods, and let's suppose that we want to do that extending it.aco.mandragora.dao.impl.ojb.pb.OjbPbDAO. 1) Write a new interface that extend DAO with your method. Let's call it UserDAO 2) Write a new class that implements UserDAO, extends OjbPbDAO and of course implement your new methods.Let's call it ImplUserDAO 3) We saw above how to map it in Mandragora.properties to use it in ImplUserApplicationService and in ImplUserServiceFacade: ImplUserApplicationService.DAOFactoryClass=it.aco.mandragora.dao.concreteFactory.DefaultDAOFactory ImplUserApplicationService.DAOClass=myPath.ImplUserDAO ImplUserServiceFacade.DAOFactoryClass=it.aco.mandragora.dao.concreteFactory.DefaultDAOFactory ImplUserServiceFacade.DAOClass=myPath.ImplUserDAO Conclusion ---------------------------------- Resuming a bit, BD uses ServiceFacade, ServiceFacade uses ApplicationService and DAO, ApplicationService uses DAO. When you miss a BD method you have to write a new ServiceFacade method as well, that can be expressed part in terms of existing ApplicationService and DAO methods, and part in terms of new ApplicationService and DAO methods that you have to implement by your own. You will implement the new ApplicationService methods, part in term of the existing DAO methods, and part in terms of the new DAO methods you have to implement. Should be clear now, how Mandragora can help. In the most of cases you will find listed the right method you need, and so just do bd.someBDMethod(...) and forget about implementation details, connections, if used ejb or not, forget about technology and patterns too. Of course forget just in the client using BD, because then you have to configure Mandragora.properties (but if you use default implementation it is already configured), ejb-jar.xml, repository file if you use OjbPbDAO (the mapping file for Apache Ojb) etc. But if you for example are using it in a controller, forget all about that, just fix on your controller logic, you will configure later, or someone else will do. And change configuration when you want without affecting the controller code. If you miss some method, don't worry, decompose the logic of the method you need in smaller units, and try to use the most possible the methods at the different tiers, and you will get part of the job done, and moreover you are keeping the j2ee pattern well done structure. Moreover if you do an effort to write the missing methods at all the tiers as general as possible, you have good chance to reuse them next time, so the list of available methods at all tier will grow up, and if everybody do that and share, we can get a time where we can have available thousands of methods, at all tiers, and above all we could have the interfaces implemented with many technologies, and user must just choose the most suitable for his needing. Alessandro Colantoni IT Engineer
  2. You're kidding me right...first of all another MVC framework and to top it off using J2EE design patterns?!
  3. It is not a MVC framework, as it provides just a solution to easy implement the Model. This is an effort to provide many (nearly 100) business methods ready to be used, implemented following the J2ee patterns. You can see it like a 'catalog' that avoid you to rewrite the same operations. You can use the framework you want, and if you find in the BD 'catalog' something suitable for your needing, just use it. In all the applications I develop, I always try to break down the most possible the job I have to do, in the smallest piece I can and then try to generalize them the most possible to reuse. That for DAO, facade, and all tier I use. So 4 years ago I just organized it in library, so it was easier for me, and in 2005 I just shared it, publishing it in sourceforge, and during these years I have been adding the new methods at all tiers as I needed for my job. Please don't see it as just an other framework, thinking what a bothering, again MVC, again J2ee pattern. Try to see it as a simple catalog of operation. Then if you want you can add your own operations to reuse. Thanks for the comment.
  4. My eyes can't read this right now... sorry. Please next time, if you want people to read your article, format it a bit. Maybe it contains interesting stuff, but I really can't be bothered to read it right now.
  5. Agreed. It would have made sense to just put a quick summary here on ServerSide and link to the full (probably better formatted) text elsewhere. --Matt Passell The Software Grove
  6. Really sorry! Is there someway to modify it?
  7. Hi Alessandro, Sorry, I'm not sure. If you can get in touch with one of the editors, you can probably provide them with new content. --Matt The Software Grove
  8. Not sure why I would want to use this package. No annotations. Property files would proliferate. No dependency injection. No SOA. It looks like the way we coded 5 years ago. I understand from your write up, that you started this 5 years ago. But what about everything that has changed in the last 5 years in best practices?
  9. Hi! thank you to criticize and for ideas. I didn't use annotation, except for test. Should I do? There is no properties file proliferation: the only one is Mandragora.properties. Dependency injection: yes there is. Why do you say no? Each tier uses lower tier interface with IoC. In Mandragora.properties you can choose the implementation to use, as well as the factory that has to instantiate it. It is based on Service Locator.Dependency injection is there since 5 years ago. SOA. Yes you are right. That's the interesting point. Anyway if you have a look you will see that the code written to provide an infrastructure for your model, based on BD, facade, application service and DAO is not so much. The most of the code is for the catalog of operations. There are many DAO methods written, and many generic AS methods reusable. I want to reuse these methods independently from the architecture. Because I don't think to write again a findByPrimaryKey method in my life. How do you suggest to reuse them in a SOA architecture? I had some idea, even if a bit rude, I'd like you tell me your opinion, and of course suggest the most possible. We can think at BD as a service provider(it provides 100 services). Who use these service doesn't know nothing about what in the back side ( session bean?, pojo object? whatever structure ? WebService?). They are just services in its most abstract meaning. The client requests, and it is served. So what do you think about a BD implementation based on Web service? Don't think at BD as the j2ee pattern to hide ejb detail from the client. Think just as if it was a service provider. This BD implementation should connect somewhere, transform parameters in XML and, so on... The same could be done between all the levels. The methods are there, and they are fully tested. We have just to build a new infrastructure around them. I already made something similar, for some method. There was a web service that when received a request tranformed xml in value objects, called BD methods of Mandragora, and then transformed the returned valueobjects in xml, and send them back. Well that's just an idea. The benefit is that even so, we don't have to change the client calling Mandragora BD. just switch to the new implementation in Mandragora.properties (isn't this dependency injection? I don't know maybe I'm wrong) All critics will be accepted as lessons. Thank you to read this. Sorry again for the bad format. Suggestions on how to improve format are welcome. Alessandro
  10. IOC: The code that does a manual lookup: ImplUserBD bd = (ImplUserBD)ServiceLocator.getInstance().getManagerBD("MyClient.BDFactoryClass", "MyClient.BDClass"); bd.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...); Is not IOC. IOC uses a setter that binds the service thus it would allow me to to merely to the following: userBD.doTheCoreJobOfMyApplicationThatItIsImpossibleBeAlreadyWritten(...); In IOC you only set the service once at the for the class that uses it and then just use the variable. Look at Guice, Spring, etc. Creating a factory every time I need to do a service is overkill. With Dependancy Injection uses standard POJO that does not have to come from any other classes. You create a interface that defines the API and then create the class behind the interface. Basic OO programming. Then you use dependancy injection to link the interface to the client code.
  11. Hi again! I don't understand exactly what do you mean with 'every time I need to do a service is overkill'. Anyway I would specify that the implementations are singleton, so I'm actually always using the same instance. The reason I use factory and Service Locator in place of a setter injection style Spring is to give the possibility to use the same BD implementation for example, in some case with a ServiceFacade, and in an other case with an other ServiceFacade. For example in one method of PojoManagerBD do ServiceLocator.getInstance().getServiceFacade("myFact1","mySF1)"); sf.method1(..); and in an other method do: ServiceLocator.getInstance().getServiceFacade("myFact2","mySF2)"); sf.method2(..); That's why I didn't use setter injection like Spring. Then I never used this possibility, but it was just to leave an open door. The initial idea (5 years ago) was to give to each method (service) the possibility to choose the implementation of the interface of the lower layer and configuring it in Mandragora.properties file. I never done because it was too much to configure and I could have a properties file too large. To use setter injection is one of the next thing to do, and it won't take too much work, but it is not so urgent. I'm thinking to mix both technique, because I like to give the possibility to choose not just the implementation, but the way it has to be instanced as well. For this, Service Locator and factory could help. I was thinking in writing a factory that could instance and populate the field with the right implementation. What do you think? Anyway about definitions. I call both technique Dependency Injection, even if it is not exact 100% because the Dependency injection remove the dependency between the caller class and the concrete implementation populating a field with the wanted implementation someway: constructor,setter or interface Injection. But the Service locator removes the dependency as well, and the wanted implementation is injected as well. Anyway in the pure pattern, I think you are right and should have a field to populate. Did you think at a way to reuse the methods in a SOA architecture?. I hope you will take the time to criticize the idea I exposed above. Thanks Alessandro
  12. First thing I did after reading first few paragraphs of this is to check the date of the article. I thought somehow this article wrongly finished on the The Server Side home page. But not, it's from the year 2009. Strange...
  13. Hi Mileta, first of all thanks for reading. I know that discussion about that patterns is many years old. I understand your comment, and maybe I didn't have to focus on them so much. But the point is an other one. I think that an application can be seen as a collection of functionalities or services if you want. On a conceptual point of view each functionality can be break down as a combination of smaller ones, and so on, until reaching very small functional units, that can be easily generalized. Now in my experience, I think that the difference between two applications, except for the business core, is that they are different combination of the same generic functional units. That's they way I work. Mandragora provides many of such units, that can be combined to build the architecture or structure you want. So please have a look down the surface. What I'm very interested to be criticized is about the methods you can find there, above all at DAO layer ane ApplicationService layer. To know if they can be considered useful or not, or if they need to be more generalized to be useful. I would like to discuss about the methods. If some one could be interested of course. Thanks again to loose a bit of your time Alessandro