1 2 3 4 5 Previous Next 72 Replies Latest reply on Nov 13, 2009 8:15 PM by gavin.king Go to original post
      • 30. Re: Outjection vs. Producer method
        crazybob.seamframework.crazybob.org

        Definitely not going to re-do this argument which has been more than done to death. Suffice to say that nobody I know agrees with Google on this one. Anyway, I'm very happy to shut up and let the users decide whether they prefer to use JSR-299 or JSR-330. LOL.

        Ha ha. FWIW, I think we've only debated this one-on-one. I'm not sure who you know, but no one I know agrees with you. ;-)


        Rather than wait around to see what users prefer, we design based on objective evidence. It's easy enough to compare code written with each approach and identify which is more readable (hint: if brevity equaled readability, we'd all just program in Ruby).


        In addition to the maintainability concerns I already mentioned, you have the general problems with creating wrapper proxies from concrete classes:


          1. Your class must have no-arg constructors. This precludes immutability and constructor injection.
          2. If you have fields in your class, the fields in the proxy just waste memory because they aren't used. If those fields are initialized by default, you could waste a lot of memory.
          3. You can't store the object for later use. When you need to do this, you must write custom code to capture the object's state.
          4. You're in for a surprise if you try to access private fields in a different instance. We do this from equals() all the time. You'll be accessing the uninitialized state in the proxy, and it won't be clear why your code doesn't work. Maybe this hasn't come up for you yet, but our users do this.
          5. If you pass this from inside your object, you risk unintentionally exposing your unproxied instance.


        This is why Guice AOP only supports the style of class proxying where the proxy and proxied instance are one in the same, i.e. the proxy works by overriding methods, not delegating to methods on a different instance. Users dig the simplicity.

        • 31. Re: Outjection vs. Producer method
          gavin.king

          Blah blah blah. Take it to the Guice forum, please, Bob. I really don't have time for the same tired rubbish over and over again.

          • 32. Re: Outjection vs. Producer method
            asookazian

            Gavin King wrote on Nov 12, 2009 05:02:


            I know that GKing does not think that supporting orthogonal concerns via AOP is necessary, but it's nice to be able to add logging and tx's and security to your app without modifying the classes, no?

            You need AOP to implement logging and transactions and security?! WTF for? What is it you are trying to do that you can't do with a CDI interceptor binding?


            I never said (and most likely never will say) you need AOP for those concerns.  I am quite happy with EJB and Seam interceptors, so far.  They don't seem deficient to me (yet).  It seems to me that in most use cases it's easier to use @AroundInvoke rather than dealing with advices and point cuts, etc.  Seems like overkill to me, AOP, no?


            Plus, how many other frameworks in the Java space actually use AOP other than Spring and AspectJ???

            • 33. Re: Outjection vs. Producer method
              crazybob.seamframework.crazybob.org

              Blah blah blah. Take it to the Guice forum, please, Bob. I really don't have time for the same tired rubbish over and over again.

              Note that I only spoke up to correct your disingenuous statement about Guice.

              • 34. Re: Outjection vs. Producer method
                gavin.king

                Oh, but if others are interested in knowing why we believe that Bob is wrong, take a look at the spec in section 5.4, where we explain the 3 reasons why proxies are needed for the built-in normal scopes.


                Pay special attention to the fact that the session and conversation scopes are passivating scopes in Java EE, and so it's simply not possible for an object in another scope to hold a direct reference to a session or conversation scoped object.


                And by sure to check Bob's total-waffle answers to my three questions on a TSS thread where he started in on this stuff.


                Oh and note that whatever Bob says, the spec is clear that proxies are not needed for pseudo-scopes, so if you don't want them, use a pseudo-scope instead of a normal scope. 299 has an extensible model, so you can support whatever scopes you like.

                • 35. Re: Outjection vs. Producer method
                  gavin.king

                  Note that I only spoke up to correct your disingenuous statement about Guice.

                  This is exactly why I hate discussing technology with you Bob. There was absolutely nothing disingenuous about saying that:



                  [Guice] still [doesn't] support a solution to the problem of cross-scope injection

                  It's a literally true statement, and I didn't say or impute anything negative or positive about Guice. I was merely pointing out ways in which the design of Seam inspired CDI.


                  Now seriously, I really don't want to get into a discussion with you, because they always seem to turn personal.

                  • 36. Re: Outjection vs. Producer method
                    gavin.king

                    They don't seem deficient to me (yet). It seems to me that in most use cases it's easier to use @AroundInvoke rather than dealing with advices and point cuts, etc. Seems like overkill to me, AOP, no?

                    Interceptor binding types are a much simpler construct to deal with than pointcut expressions. AOP is incredible overkill.

                    • 37. Re: Outjection vs. Producer method

                      Arbi Sookazian wrote on Nov 12, 2009 04:51:



                      Gavin King wrote on Nov 12, 2009 03:49:


                      This should be obvious, since CDI was designed mainly by folks who think Spring is a steaming pile of ....



                      I don't understand why the SpringSource and JBoss camps have to be so unfriendly and divided.


                      Me neither. I do remember the time when the Spring guys were happy about supporting Hibernate (and the Hibernate guys were happy about being supported by Spring). Back then, it was Spring and Hibernate against the horrible EJB 2.0... and then something happened...



                      e.g. http://www.jboss.org/index.html?module=bb&op=viewtopic&t=116569 CBauer goes off on RJohnson regarding ORM/DAO.

                      Or maybe it's just GKing b/c at least DAllen wrote a Spring integration chapter in SiA book...


                      Well, Dan wrote the chapter in the book, but I guess the credit should go with whoever wrote the code in Seam that made integration possible...



                      If Seam was released a couple years earlier, would there have been better/more adoption in the industry?


                      Maybe,maybe not, Spring and Seam are very different beasts.



                      Well I'm not sure if Seam 2.x even support EJB 2.x (but I'm pretty sure JEE 5 servers do support them as part of JSR 220).


                      Yes, Seam can deal with EJB 2.x, in fact Spring was created precisely because but EJB 2.x was a real PITA (I am pretty sure that Gavin did not like EJB 2.x, and I also pretty sure that back then, he was really happy about Spring having support for Hibernate). EBJ3 improvements over EJB2 are (even if some do not admit it) a reaction to Spring and Hibernate: Nobody in their right mind would prefer to use EJB 2.x over Spring and Hibernate.



                      If EJB 3.0 was not so late as part of JEE 5, then maybe Spring stack would not have become as popular as it has become...


                      Exactly. IMO Spring and Hibernate success inspired many of the changes of EJB 3.0 and even the creation of Guice and Weld and the opensourcing of TopLink (now EclipseLink). Of course, some may deny it, but that doesn't make any less true.



                      I know that GKing does not think that supporting orthogonal concerns via AOP is necessary, but it's nice to be able to add logging and tx's and security to your app without modifying the classes, no?  Then it's easier to refactor your classes when porting to a different technology stack, no?


                      I am not sure what do you mean by that...

                      • 38. Re: Outjection vs. Producer method

                        Stuart Douglas wrote on Nov 12, 2009 05:14:


                        I don't get why people seem to think that transactions and security are things that can just sort of be stuck on later. When I am writing code I usually know exactly what the transactional behavior should be, and expressing that with an annotation in the actual code makes a lot more sense to me than expressing it in an XML document somewhere else entirely.


                        An expressing it programatically, in completely intuitive way it even better (OMG how much do I miss EOF. Will ever be that easy to deal with transactions again? sigh)

                        • 39. Re: Outjection vs. Producer method
                          gavin.king

                          Back then, it was Spring and Hibernate against the horrible EJB 2.0... and then something happened...

                          Right. What happened was that we decided we should take the work we'd done and use it to improve the standards. Which was inconvenient to some people...



                          EBJ3 improvements over EJB2 are (even if some do not admit it) a reaction to Spring and Hibernate

                          Everybody admits that. Likewise, Spring and Hibernate were a reaction to EJB2. It goes in cycles, you see...



                          Nobody in their right mind would prefer to use EJB 2.x over Spring and Hibernate.

                          Of course not. But the designers of Hibernate and Spring had the benefit of real-world experience with EJB. The designers of EJB 1.x had the benefit of real-world experience with ... CORBA? In C++?


                           

                          • 40. Re: Outjection vs. Producer method

                            Gavin King wrote on Nov 12, 2009 06:31:


                            Of course not. But the designers of Hibernate and Spring had the benefit of real-world experience with EJB. The designers of EJB 1.x had the benefit of real-world experience with ... CORBA? In C++?



                            In an alternative dimension, where Sun bought NextStep, and EJB 1.x had the benefits of real-world experience with WebObjects...sigh, there is no use in crying over the spilt milk...

                            • 41. Re: Outjection vs. Producer method
                              asookazian

                              Stuart Douglas wrote on Nov 12, 2009 05:14:


                              I don't get why people seem to think that transactions and security are things that can just sort of be stuck on later. When I am writing code I usually know exactly what the transactional behavior should be, and expressing that with an annotation in the actual code makes a lot more sense to me than expressing it in an XML document somewhere else entirely.


                              You're right, it's more natural with annotations.  The point is that when I took my Spring training, the instructor pointed out in an example project that you can literally add tx, security or logging support via xml configurations and not change or add a line of code in your classes.  That seems convenient but you're right, it's less natural to do it all at the end that way...

                              • 42. Re: Outjection vs. Producer method
                                asookazian

                                Bob Lee wrote on Nov 12, 2009 05:14:


                                Definitely not going to re-do this argument which has been more than done to death. Suffice to say that nobody I know agrees with Google on this one. Anyway, I'm very happy to shut up and let the users decide whether they prefer to use JSR-299 or JSR-330. LOL.

                                Ha ha. FWIW, I think we've only debated this one-on-one. I'm not sure who you know, but no one I know agrees with you. ;-)

                                Rather than wait around to see what users prefer, we design based on objective evidence. It's easy enough to compare code written with each approach and identify which is more readable (hint: if brevity equaled readability, we'd all just program in Ruby).

                                In addition to the maintainability concerns I already mentioned, you have the general problems with creating wrapper proxies from concrete classes:

                                  1. Your class must have no-arg constructors. This precludes immutability and constructor injection.
                                  2. If you have fields in your class, the fields in the proxy just waste memory because they aren't used. If those fields are initialized by default, you could waste a lot of memory.
                                  3. You can't store the object for later use. When you need to do this, you must write custom code to capture the object's state.
                                  4. You're in for a surprise if you try to access private fields in a different instance. We do this from equals() all the time. You'll be accessing the uninitialized state in the proxy, and it won't be clear why your code doesn't work. Maybe this hasn't come up for you yet, but our users do this.
                                  5. If you pass this from inside your object, you risk unintentionally exposing your unproxied instance.

                                This is why Guice AOP only supports the style of class proxying where the proxy and proxied instance are one in the same, i.e. the proxy works by overriding methods, not delegating to methods on a different instance. Users dig the simplicity.


                                Maybe he has a point here (and honestly I don't understand all the concepts and details of CDI or Guice currently, but whatever).


                                Guice AOP.  why do you say, GKing, that it doesn't belong in this forum?  This is the forum for RI of CDI (dependency injection being the main topic, no?)  And maybe it would be healthy (w/o the vociferous, immature arguments!) to compare/contrast design and implementations of the two frameworks.  So we can understand what works better in what scenarios.


                                so apparently this is an example of Guice AOP:


                                import org.aopalliance.intercept.MethodInterceptor;
                                import org.aopalliance.intercept.MethodInvocation;
                                 
                                import java.util.logging.Level;
                                import java.util.logging.Logger;
                                 
                                public class LoggingInterceptor implements MethodInterceptor {
                                 
                                    private Logger logger = Logger.getLogger(LoggingInterceptor.class.getName());
                                 
                                    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                                        logger.logp(
                                                Level.INFO,
                                                methodInvocation.getClass().getName(),
                                                methodInvocation.getMethod().getName(),
                                                "invocation",
                                                methodInvocation.getArguments());
                                 
                                        Object result = null;
                                 
                                        try {
                                            result = methodInvocation.proceed();
                                        } finally {
                                            logger.logp(
                                                    Level.INFO,
                                                    methodInvocation.getClass().getName(),
                                                    methodInvocation.getMethod().getName(),
                                                    "return",
                                                    result);
                                 
                                            return result;
                                        }
                                    }
                                 
                                }



                                http://jpz-log.info/archives/2009/11/04/guice-it-up-or-aop-can-be-made-simple-sometimes/


                                doesn't look too painful to me...


                                compare to EJB3 interceptor example:


                                @AroundInvoke
                                public Object intercept(InvocationContext ctx) throws Exception
                                {
                                   System.out.println("*** DefaultInterceptor intercepting " + ctx.getMethod().getName());
                                   try
                                   {
                                      return ctx.proceed();
                                   }
                                   finally
                                   {
                                      System.out.println("*** DefaultInterceptor exiting");
                                   }
                                }
                                
                                <assembly-descriptor>
                                   <!-- Default interceptor that will apply to all methods for all beans in deployment -->
                                   <interceptor-binding>
                                      <ejb-name>*</ejb-name>
                                      <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>      
                                </assembly-descriptor>
                                
                                



                                http://www.jboss.org/file-access/default/members/jbossejb3/freezone/docs/tutorial/1.0.7/html/EJB3_Interceptors.html


                                Is there an annotation to replace the xml markup config for interceptor-binding?


                                What is an equivalent Weld example (if this applies to Weld at all)?

                                • 43. Re: Outjection vs. Producer method
                                  gavin.king

                                  Arbi Sookazian wrote on Nov 12, 2009 17:22:



                                  Stuart Douglas wrote on Nov 12, 2009 05:14:


                                  I don't get why people seem to think that transactions and security are things that can just sort of be stuck on later. When I am writing code I usually know exactly what the transactional behavior should be, and expressing that with an annotation in the actual code makes a lot more sense to me than expressing it in an XML document somewhere else entirely.


                                  You're right, it's more natural with annotations.  The point is that when I took my Spring training, the instructor pointed out in an example project that you can literally add tx, security or logging support via xml configurations and not change or add a line of code in your classes.  That seems convenient but you're right, it's less natural to do it all at the end that way...


                                  Arbi, I think you're missing the point. Stuart and I understand that this is a claimed benefit. What we're not sold on is that it's actually possible in most practical cases. The thing is, that without the annotations in your code, you can't apply the interceptors at the appropriate level of granularity. There's no hooks to know where the interception should be activated. Without the annotations, you're left with very crude discriminators like naming conventions in the class and method names, inheritance from base classes, etc. So in practice, you are going to need the annotations after all.


                                  Besides which, the annotations make the code easier to read and understand. You don't need to go off to some XML file to understand what extra hidden semantics a method has.

                                  • 44. Re: Outjection vs. Producer method
                                    asookazian

                                    Gavin King wrote on Nov 12, 2009 17:39:



                                    Arbi Sookazian wrote on Nov 12, 2009 17:22:



                                    Stuart Douglas wrote on Nov 12, 2009 05:14:


                                    I don't get why people seem to think that transactions and security are things that can just sort of be stuck on later. When I am writing code I usually know exactly what the transactional behavior should be, and expressing that with an annotation in the actual code makes a lot more sense to me than expressing it in an XML document somewhere else entirely.


                                    You're right, it's more natural with annotations.  The point is that when I took my Spring training, the instructor pointed out in an example project that you can literally add tx, security or logging support via xml configurations and not change or add a line of code in your classes.  That seems convenient but you're right, it's less natural to do it all at the end that way...


                                    Arbi, I think you're missing the point. Stuart and I understand that this is a claimed benefit. What we're not sold on is that it's actually possible in most practical cases. The thing is, that without the annotations in your code, you can't apply the interceptors at the appropriate level of granularity. There's no hooks to know where the interception should be activated. Without the annotations, you're left with very crude discriminators like naming conventions in the class and method names, inheritance from base classes, etc. So in practice, you are going to need the annotations after all.

                                    Besides which, the annotations make the code easier to read and understand. You don't need to go off to some XML file to understand what extra hidden semantics a method has.



                                    1) I am not advocating extensive or exclusive usage of XML.  I really don't like XML.  I would like to see replacement of annotations and XML in the future from metadata semantics but I can live with minimal XML and heavy annotations like in Seam 2.x.


                                    2) I'm not going to argue with you about what you're not sold on (adding XML for AOP in Spring is not practical) b/c I don't have extensive experience with it, but I'm pretty sure I saw it with my own eyes a few years ago in that Spring training (don't recall if it was logging or tx's or what).


                                    an example of Spring AOP for logging interceptor:


                                    <bean id="maintenanceServiceBean" class="org.springframework.aop.framework.ProxyFactoryBean">
                                                                 <property name="proxyInterfaces">
                                                                               <value>IMaintenanceService</value>
                                                                  </property>
                                              <property name="target">
                                                   <ref bean="maintenanceServiceImpl"/>
                                              </property>
                                              <property name="interceptorNames">
                                                   <list>                    
                                                        <value>loggingInterceptor</value>
                                                   </list>
                                              </property>          
                                    </bean>     
                                    
                                    <bean id=" maintenanceServiceImpl " class="MaintenanceService">
                                    
                                    <bean id=" loggingInterceptor"  class="LoggingInterceptor"/>
                                    



                                    import java.lang.reflect.Method;
                                    import org.apache.commons.logging.Log;
                                    import org.apache.commons.logging.LogFactory;
                                    import org.springframework.aop.AfterReturningAdvice;
                                    import org.springframework.aop.MethodBeforeAdvice;
                                    import org.springframework.aop.ThrowsAdvice;
                                    
                                    public class LoggingInterceptor implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice{
                                         private static Log log = null;
                                         public LoggingInterceptor(){
                                         }
                                         
                                         public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
                                              log = LogFactory.getLog(arg2.getClass());
                                              log.info("Beginning method: "+arg0.getName());
                                         }
                                         
                                         public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {          
                                              log = LogFactory.getLog(arg3.getClass());
                                              log.info("Ending method: "+arg1.getName());          
                                         }
                                         
                                         public void afterThrowing(Method m, Object[] args, Object target, Throwable ex) 
                                         { 
                                              log = LogFactory.getLog(target.getClass());
                                              log.info("Exception in method: "+m.getName()+" Exception is: "+ex.getMessage());     
                                         }
                                    
                                    }
                                    



                                    Note here the finer level of granularity in terms of execution of advice on method calls (before and after advice).  Whereas in EJB3 we simply have the @AroundInvoke AFAIK.


                                    http://www.devx.com/Java/Article/30799/0/page/2


                                    Ok, that article seems way too over-complicated for such a simple implementation of a cross-cutting concern that can be implemented more cleanly/easily with Seam/EJB3 (and maybe even better with CDI?)


                                    But I still think that you should be able to override the annotations in XML like is allowed in JSR 220, no?  Even if the annotations are as fine-grained as parameter level in methods, no?


                                    so you're saying we can't do that?