title: Why doesn't Spring's @Transactional work on protected methods?
body: <p>From <a href="https://stackoverflow.com/questions/4396284/does-spring-transactional-attribute-work-on-a-private-method">Does Spring @Transactional attribute work on a private method?</a></p>
  
  <blockquote>
    <p>When using proxies, you should apply the @Transactional annotation
    only to methods with public visibility. If you do annotate protected,
    private or package-visible methods with the @Transactional annotation,
    no error is raised, but the annotated method does not exhibit the
    configured transactional settings.</p>
  </blockquote>
  
  <p>I can think of good reasons to exclude <code>private</code> and <code>package-private</code> methods, but why won't <code>protected</code> methods behave transactionally? The following stacktrace displays the correct behaviour for a public method (called through an interface proxy):</p>
  
  <pre><code>at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]
  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at com.sun.proxy.$Proxy145.improveType(Unknown Source) ~[na:na]
  </code></pre>
  
  <p>When calling an "identical" protected method (through a non-interface CGLIB proxy), we get the following:</p>
  
  <pre><code>at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]
  at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
  at my.company.webservices.facade.EntityFacade$$EnhancerBySpringCGLIB$$fd77735b.findEntity(&lt;generated&gt;) ~[spring-core-4.2.1.RELEASE.jar:na]
  </code></pre>
  
  <p>This is apparently a design decision (why?), but I consider it rather questionable that it fails silently, when it's clearly a developer error.</p>
  
  <p><strong>Edit</strong>
  This is obviously not an issue when using interfaces (only public methods in interfaces), but as Spring doesn't necessarily need an interface to proxy an object through CGLIB, calling a protected <code>@Transactional</code> method will behave just like a public method (i.e. called through a proxy), except that <em>by design</em> it ignores the transactionality.</p>