Proxies and AOP make clustering Spring applications arcane
----------------------------------------------------------

                 Key: CDV-834
                 URL: https://jira.terracotta.org/jira//browse/CDV-834
             Project: Community Development
          Issue Type: Bug
          Components: X-Sample Apps, X-SpringRuntime
    Affects Versions: 2.7.0-stable0
            Reporter: Geert Bevin
            Assignee: Issue Review Board


Consider this class:

public class UserDetailsWrapper implements UserDetails {
  private final StandardAuthoritiesService service;
  private final User                       delegate;

  public UserDetailsWrapper(final StandardAuthoritiesService service, final 
User delegate) {
    this.service = service;
    this.delegate = delegate;
  }
  // ...
}

When this enters a clustered graph, the service field is clustered by default. 
However, you might not want to cluster it if the Spring bean for the service 
isn't clustered. Terracotta will spit out a TCNonPortableObjectError like the 
one below if an instance of UserDetailsWrapper is for example stored in a 
clustered session. Nothing whatshowever in this output refers to the class 
above, hence making it virtually impossible for the user to know what to do. 
They will just add JdkDynamicAopProxy to the included classes and start to pull 
in any possible class that is used by the service and Spring AOP. This actually 
happened to me and it took me hours of searching and backing up to figure out 
where to cut the shared graph.

[INFO] [cargo0] com.tc.exception.TCNonPortableObjectError: 
[INFO] [cargo0] 
*******************************************************************************
[INFO] [cargo0] Attempt to share an instance of a non-portable class referenced 
by a portable class. This
[INFO] [cargo0] unshareable class has not been included for sharing in the 
configuration.
[INFO] [cargo0] 
[INFO] [cargo0] For more information on this issue, please visit our 
Troubleshooting Guide at:
[INFO] [cargo0] http://terracotta.org/kit/troubleshooting
[INFO] [cargo0] 
[INFO] [cargo0] Referring class   : $Proxy20
[INFO] [cargo0] Thread            : http-8080-1
[INFO] [cargo0] JVM ID            : VM(1)
[INFO] [cargo0] Non-included class: 
org.springframework.aop.framework.JdkDynamicAopProxy
[INFO] [cargo0] 
[INFO] [cargo0] Action to take:
[INFO] [cargo0] 
[INFO] [cargo0] 1) Reconfigure to include the unshareable classes
[INFO] [cargo0]    * edit your tc-config.xml file
[INFO] [cargo0]    * locate the <dso> element
[INFO] [cargo0]    * add this snippet inside the <dso> element
[INFO] [cargo0] 
[INFO] [cargo0]        <instrumented-classes>
[INFO] [cargo0]          <include>
[INFO] [cargo0]            
<class-expression>org.springframework.aop.framework.JdkDynamicAopProxy</class-expression>
[INFO] [cargo0]          </include>
[INFO] [cargo0]        </instrumented-classes>
[INFO] [cargo0] 
[INFO] [cargo0]    * if there is already an <instrumented-classes> element 
present, simply add
[INFO] [cargo0]      the new includes inside it
[INFO] [cargo0] 
[INFO] [cargo0] It is possible that some or all of the classes above are truly 
non-portable, the solution
[INFO] [cargo0] is then to mark the referring field as transient.
[INFO] [cargo0] 
[INFO] [cargo0] 
[INFO] [cargo0] 
*******************************************************************************
[INFO] [cargo0] 
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.throwNonPortableException(ClientObjectManagerImpl.java:826)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.checkPortabilityOfTraversedReference(ClientObjectManagerImpl.java:718)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.access$900(ClientObjectManagerImpl.java:82)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl$NewObjectTraverseTest.checkPortability(ClientObjectManagerImpl.java:1059)
[INFO] [cargo0]         at 
com.tc.object.Traverser.addReferencedObjects(Traverser.java:48)
[INFO] [cargo0]         at com.tc.object.Traverser.traverse(Traverser.java:89)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.addToManagedFromRoot(ClientObjectManagerImpl.java:982)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.create(ClientObjectManagerImpl.java:338)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.lookupOrCreateIfNecesary(ClientObjectManagerImpl.java:402)
[INFO] [cargo0]         at 
com.tc.object.ClientObjectManagerImpl.lookupOrCreate(ClientObjectManagerImpl.java:375)
[INFO] [cargo0]         at 
com.tc.object.tx.ClientTransactionManagerImpl.logicalInvoke(ClientTransactionManagerImpl.java:756)
[INFO] [cargo0]         at 
com.tc.object.TCObjectLogical.logicalInvoke(TCObjectLogical.java:20)
[INFO] [cargo0]         at 
com.tc.object.bytecode.ManagerImpl.logicalInvoke(ManagerImpl.java:235)
[INFO] [cargo0]         at 
com.tc.object.bytecode.ManagerUtil.logicalInvoke(ManagerUtil.java:287)
[INFO] [cargo0]         at java.util.HashMap.put(HashMap.java)
[INFO] [cargo0]         at 
com.terracotta.session.SessionData.bindAttribute(SessionData.java:345)
[INFO] [cargo0]         at 
com.terracotta.session.SessionData.setAttributeReturnOld(SessionData.java:241)
[INFO] [cargo0]         at 
com.terracotta.session.SessionData.setAttribute(SessionData.java:233)
[INFO] [cargo0]         at 
org.springframework.security.context.HttpSessionContextIntegrationFilter.storeSecurityContextInSession(HttpSessionContextIntegrationFilter.java:392)
[INFO] [cargo0]         at 
org.springframework.security.context.HttpSessionContextIntegrationFilter.access$000(HttpSessionContextIntegrationFilter.java:100)
[INFO] [cargo0]         at 
org.springframework.security.context.HttpSessionContextIntegrationFilter$OnRedirectUpdateSessionResponseWrapper.doSessionUpdate(HttpSessionContextIntegrationFilter.java:518)
[INFO] [cargo0]         at 
org.springframework.security.context.HttpSessionContextIntegrationFilter$OnRedirectUpdateSessionResponseWrapper.sendRedirect(HttpSessionContextIntegrationFilter.java:506)
[INFO] [cargo0]         at 
org.springframework.security.util.RedirectUtils.sendRedirect(RedirectUtils.java:60)
[INFO] [cargo0]         at 
org.springframework.security.ui.AbstractProcessingFilter.sendRedirect(AbstractProcessingFilter.java:345)
[INFO] [cargo0]         at 
org.springframework.security.ui.AbstractProcessingFilter.successfulAuthentication(AbstractProcessingFilter.java:379)
[INFO] [cargo0]         at 
org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:266)
[INFO] [cargo0]         at 
org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
[INFO] [cargo0]         at 
org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:371)
[INFO] [cargo0]         at 
org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
[INFO] [cargo0]         at 
org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
[INFO] [cargo0]         at 
org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:371)
[INFO] [cargo0]         at 
org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
[INFO] [cargo0]         at 
org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
[INFO] [cargo0]         at 
org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:371)
[INFO] [cargo0]         at 
org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:174)
[INFO] [cargo0]         at 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
[INFO] [cargo0]         at 
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
[INFO] [cargo0]         at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
[INFO] [cargo0]         at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
[INFO] [cargo0]         at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
[INFO] [cargo0]         at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
[INFO] [cargo0]         at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
[INFO] [cargo0]         at 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
[INFO] [cargo0]         at 
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
[INFO] [cargo0]         at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
[INFO] [cargo0]         at 
com.tc.tomcat55.session.SessionValve55.tcInvoke(SessionValve55.java:63)
[INFO] [cargo0]         at 
com.tc.tomcat55.session.SessionValve55.invoke(SessionValve55.java:50)
[INFO] [cargo0]         at 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
[INFO] [cargo0]         at 
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
[INFO] [cargo0]         at 
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
[INFO] [cargo0]         at 
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
[INFO] [cargo0]         at java.lang.Thread.run(Thread.java:613)


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://jira.terracotta.org/jira//secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        
_______________________________________________
tc-dev mailing list
tc-dev@lists.terracotta.org
http://lists.terracotta.org/mailman/listinfo/tc-dev

Reply via email to