Page 4 of 5 FirstFirst ... 2345 LastLast
Results 31 to 40 of 45

Thread: Use Hibernate Entities in the web layer?

  1. #31

    Default

    But I am still not convinced why DTOs are being used for same JVM client applications
    I attended Ben's ROO presentation in Stockholm yesterday and he said that one of the main reasons to use DTOs in the same JVM was to make the application more flexible in the face of new requirements i.e. if you use the non-DTO approach and the UI needs to present data in a *totally* different way later on then you're probably going to have to refactor some domain classes. This might have a potential impact on the data store since usually the domain object's lifecycle is tied to it. With the DTO approach the changes would be at least in theory limited to the DTO layer.

    Still...I agree, this smells a bit like YAGNI and is extra boilerplate although it's generated and synchronized automatically for you.

    Overall I thought ROO was a nice framework and the presentation was very good. Ben said that there's a 95% chance that they will open source it by the end of the year.
    Last edited by Manuel Palacio; Jul 3rd, 2007 at 02:41 AM.

  2. #32
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    I think it is also a matter of a design/architecture decision. If you decide to keep your rich domain objects inside the service layer you will have to do something to expose the data/functionality. The same goes for if you develop components which should expose there internals, that way you don't want to expose the domain objects.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #33
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,425

    Default

    Quote Originally Posted by Manuel Palacio View Post
    one of the main reasons to use DTOs in the same JVM was to make the application more flexible in the face of new requirements i.e. if you use the non-DTO approach and the UI needs to present data in a *totally* different way later on then you're probably going to have to refactor some domain classes. This might have a potential impact on the data store since usually the domain object's lifecycle is tied to it. With the DTO approach the changes would be at least in theory limited to the DTO layer.
    That is one of the things that's always concerned me about it, that quick refactoring to give the method a more sensible name breaks the UI. Sure you can fix this with tooling, but even so. I just finished the POJOs in Action book and one thing that talked about was the adapter pattern. I've actually seen this used instead to wrap the entity and there providing a layer of indirection. Would that be a half-way house?
    Last edited by karldmoore; Aug 29th, 2007 at 11:09 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  4. #34
    Join Date
    Jul 2006
    Location
    Kolkata, India
    Posts
    217

    Default

    Quote Originally Posted by karldmoore View Post
    That is one of the things that's always concerned me about it, that quick refactoring to give the method a more sensible name breaks the UI.
    The way I see it, is that, the contract between the domain layer and its clients (service layer, UI layer etc.) is always through the set of published interfaces. And once you have published your interface, it is very difficult to make the quick refactoring of method names. And I would not go for adapters (or DTOs) just to address such a change. As far as the implementation is concerned, they are never exposed to the higher up layers - hence I can make as much changes as I wish without any impact on my UI layer.

    Cheers.
    - Debasish

  5. #35
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    If even with a published interface you expose the real domain object to the outer world, it could introspect it, and call some methods by reflection. However if you do that, and anything goes wrong well you deserved it .

    I think the biggest question to answer is that do you want to couple your domain layer be it directly be it by a set of (published) interfaces to the UI/WebServices?

    Also as we all know (well at least we should I guess) is that a software product is always in a state of flux, it is never (really) finished. Implementations change, properties appear/disappear. And with new requirements and improved insights in the application we might want to refactor our classes. However if my current design decision limits me in refactoring (i.e. published interfaces) then was it a good decision?

    I think in that regard that keeping your domain model inside your service layer and expose only some DTO's is better and more flexible. You could create some conversion (yet another? anti-corruption layer?) inside your service.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  6. #36
    Join Date
    Sep 2006
    Location
    UK
    Posts
    8,425

    Default

    Quote Originally Posted by mdeinum View Post
    Also as we all know (well at least we should I guess) is that a software product is always in a state of flux, it is never (really) finished. Implementations change, properties appear/disappear. And with new requirements and improved insights in the application we might want to refactor our classes. However if my current design decision limits me in refactoring (i.e. published interfaces) then was it a good decision?
    Quite! I hate working with software when you have no idea what this change might break. As I said before tooling can help but when I'm not sure if this property is used or not, it just ends up getting left there............ forever. We can never refactor , or when we do we change something that we never even though of. Granted it's published so that's the price we pay but I'm still undecided if I'm comfortable with that or not. For me there is somewhat of an appeal for DTOs, if I don't have to worry about the maintainance ala ROO.
    Last edited by karldmoore; Aug 29th, 2007 at 11:08 AM.
    Barracuda Networks SSL VPN Lead Developer
    http://pramatr.wordpress.com
    http://twitter.com/karldmoore
    http://www.linkedin.com/in/karldmoore
    Any postings are my own opinion, and should not be attributed to my employer or clients.

  7. #37

    Default A very good technical reason not to use Hibernate entities in your Spring MVC view

    The topic of whether or not to use Hibernate entities in your Spring MVC view layer seems to be one that is based on preference. Granted, I have not read this entire thread, so there may very well be another good technical reason not to do it, but I have stumbled upon one that seems rather problematic. I decided that re-using my Hibernate entities as my Spring MVC command objects had more benefits then drawbacks... but as far as I am into building my application, I now wish I had decided otherwise.

    The story goes like this.... we have two tables....

    COMPANY( ID, some fields )
    ASSIGNMENT( ID, COMPANY_ID, some fields )

    Now, on the assignment adding page, there is a drop down with which you can select a company, and a company can only have one assignment. In order for Spring to bind the company id into the company entity assignment holds, the company entity in assignment must be initialized or else the Spring binder will give you some guff about it being null.

    In order to use HQL to query companies without assignments in a simple way, I added an assignment entity into the company entity. Due to the Spring binder problem, as a rule of thumb I initialize all associated entities. (Turns out in this particular instance I don't need to Initialize assignment in company as I never plan on binding to it with Spring, thus eliminating this problem.) Since the underlying company table doesn't have a foreign key for assignment, I used the mappedBy property of the OneToOne annotation.

    Everything in place, I build, and start Tomcat. During initialization an infinite loop results as it jumps back and forth between assignment and company.

    I may be violating some elementary rule about something you should never do with one of said technologies, but I thought it relevant to bring to the attention of those concerned about the issue regardless.

    -Jeff

    P.S. Try not to flame me too much, I'm only trying to help

  8. #38
    Join Date
    Nov 2005
    Location
    Reutlingen, Germany
    Posts
    2,098

    Default

    Quote Originally Posted by alwaysLearning View Post
    Now, on the assignment adding page, there is a drop down with which you can select a company, and a company can only have one assignment. In order for Spring to bind the company id into the company entity assignment holds, the company entity in assignment must be initialized or else the Spring binder will give you some guff about it being null.

    In order to use HQL to query companies without assignments in a simple way, I added an assignment entity into the company entity. Due to the Spring binder problem, as a rule of thumb I initialize all associated entities. (Turns out in this particular instance I don't need to Initialize assignment in company as I never plan on binding to it with Spring, thus eliminating this problem.) Since the underlying company table doesn't have a foreign key for assignment, I used the mappedBy property of the OneToOne annotation.
    No flaming, but what's the problem? Unfortunately I can't see from your post where you get into an infinite loop.

    Joerg
    This post can contain insufficient information.

  9. #39

    Default Upon further investigation....

    ..It appears the problem starts from a third entity, License, that holds a company reference. Well, the problem doesn't necessarily start there, but thats where this exception chain begins...

    Code:
    @Entity
    @Table(name="LICENSE")
    public class License {
    	...
    	@ManyToOne(cascade = CascadeType.REFRESH)
    	@JoinColumn(name="COMPANYID_FK", referencedColumnName="COMPANYID_PK")
    	private Company company = new Company();
    	...
    }
    Code:
    @Entity
    @Table(name="COMPANY")
    public class Company {
    	...
    	@OneToOne(mappedBy="company",fetch=FetchType.LAZY)
    	private Assignment assignment = new Assignment();
    	...
    }
    Code:
    @Entity
    @Table(name="ASSIGNMENT")
    public class Assignment {
    	...
    	@OneToOne
    	@JoinColumn(name="COMPANYID_FK", referencedColumnName="COMPANYID_PK")
    	private Company company = new Company();
    	...
    }
    And the stack trace that results from the exception generated when starting Tomcat...

    Code:
    2007-12-19 12:13:13,877 ERROR [org.springframework.web.servlet.DispatcherServlet] - Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/dataAccessBeans.xml]: Invocation of init method failed; nested exception is org.hibernate.InstantiationException: could not instantiate test object entity.License
    Caused by: 
    org.hibernate.InstantiationException: could not instantiate test object entity.License
    	at org.hibernate.engine.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:25)
    	at org.hibernate.engine.UnsavedValueFactory.getUnsavedIdentifierValue(UnsavedValueFactory.java:44)
    	at org.hibernate.tuple.PropertyFactory.buildIdentifierProperty(PropertyFactory.java:44)
    	at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:123)
    	at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:434)
    	at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:109)
    	at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55)
    	at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:226)
    	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
    	at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:915)
    	at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:805)
    	at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:745)
    	at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:134)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1201)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1171)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:284)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
    	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:331)
    	at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:265)
    	at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:235)
    	at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:126)
    	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:585)
    	at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:244)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
    	at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:276)
    	at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:162)
    	at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:115)
    	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1155)
    	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:981)
    	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4045)
    	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4351)
    	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
    	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
    	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
    	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
    	at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:585)
    	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
    	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
    Caused by: java.lang.reflect.InvocationTargetException
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    	at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
    	at org.hibernate.engine.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:22)
    	... 53 more
    Caused by: java.lang.StackOverflowError
    	at entity.Assignment.<init>(Assignment.java:36)
    	at entity.Company.<init>(Company.java:34)
    	at entity.Assignment.<init>(Assignment.java:40)
    	at entity.Company.<init>(Company.java:34)
    ...
    	at entity.Assignment.<init>(Assignment.java:40)
    	at entity.Company.<init>(Company.java:34)
    I'll be happy to provide any other information anyone may be interested in.

  10. #40
    Join Date
    Nov 2005
    Location
    Reutlingen, Germany
    Posts
    2,098

    Default

    From the stacktrace I get that it is an error even on the plain Java level: The constructor of Company seems to instantiate an Assignment instance. And the Assignment constructor does the same for the Company. This just can't work.

    Joerg
    This post can contain insufficient information.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •