Announcement Announcement Module
Collapse
No announcement yet.
cglib proxy Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • cglib proxy

    Hello,

    I have gone through several threads and all of them mention that i need to use Cglib and this error

    Code:
    java.lang.ClassCastException: $Proxy20 cannot be cast
    will go away.

    I think I have done that but still i seem to keep getting the error.

    I would appreciate if some one could help me out

    service layer
    Code:
    <!-- Activates annotation-based bean configuration -->
    	<context:annotation-config/>
    	
    	<!-- Scans for application @Components to deploy -->
    	<context:component-scan base-package="com.netmemex.netmx"  />
    	
    	<!--  Activate annotated task threads -->
    	<task:annotation-driven executor="executorWithPoolSizeRange"/>
    	
    	<task:executor id="executorWithPoolSizeRange" pool-size="5-25"  queue-capacity="5"/>
    	
        <bean id="serviceFactory"
                class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
         	<property name="serviceLocatorInterface" value="com.netmemex.netmx.service.transactions.ComplexDuesProcessingServiceFactory"/>
        </bean>
    ....
     <aop:aspectj-autoproxy proxy-target-class="true"/>
      
      	<aop:config>
            <aop:pointcut id="serviceOperation"
                        expression="execution(* com.netmemex.netmx.service.impl.*Service*.*(..))"/>
            <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/>
    	</aop:config>
    ...
    
    <aop:config  proxy-target-class="true">
    		<aop:aspect ref="encryptAspect">
                <aop:pointcut id="encryptTransaction" 
                expression="execution(* com.netmemex.netmx.service.transactions.impl.TransactionServiceImpl.save(..)) and args(t)"/>
                <aop:before pointcut-ref="encryptTransaction" method="encryptTrxAccountNumber" />
            </aop:aspect>
         </aop:config>
    ...

    Factory interface
    Code:
    public interface ComplexDuesProcessingServiceFactory
    {
        public ComplexDuesProcessingThreadImpl getService();
        
        public ComplexDuesProcessingThread getService(String name);
    }
    Service that is looked up by the by factory
    Code:
    public interface ComplexDuesProcessingThread
    {
        public Map<Long, Long> getChargeIdMap();
        
        public ComplexDuesForm getDuesForm();
        
        public Master getLoggedUser();
        
        public void run();
    ...
    }
    implementation of service
    Code:
    @Service("complexDuesProcessing")
    @Scope("prototype")
    public class ComplexDuesProcessingThreadImpl implements
    	ComplexDuesProcessingThread, Runnable
    {
      // instance of AccountItemService
        @Autowired
        @Qualifier("accountItemService")
        private AccountItemService accountItemService;
    
    
        @Async
        public void run()
        {
    	log.debug("gets here");
    	AccountItem a = this.getAccountItemService().getCheckPaymentItem();
    	log.debug(a.getId());
        }
    test case which keep giving me the class cast exception

    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:com/netmemex/netmx/deploy/service-layer.xml" })
    @Transactional
    public class DuesProcessServiceTest
    {
    
        @Autowired
        @Qualifier("executorWithPoolSizeRange")
        private TaskExecutor taskExecutor;
    
        @Autowired
        @Qualifier("serviceFactory")
        private ComplexDuesProcessingServiceFactory complexDuesProcessingServiceFactory;
    
      @Test
        public void getProcess() throws NetmemexServiceException
        {
    	
    	ComplexDuesProcessingThread thread = this
    		.getComplexDuesProcessingServiceFactory().getService(
    			"complexDuesProcessing");
    	log.debug(this.getComplexDuesProcessingServiceFactory().getService(
    		"complexDuesProcessing").getClass().getName());
    	// thread.run();
    	this.getTaskExecutor()
    		.execute((ComplexDuesProcessingThreadImpl) thread);
    	log.debug("done");
        }
    }
    of course the actual run implementation is a lot more complex than I am using in the example.

    as in the reference doc
    To be clear: using 'proxy-target-class="true"' on <tx:annotation-driven/>, <aop:aspectj-autoproxy/> or <aop:config/> elements will force the use of CGLIB proxies for all three of them.
    i assumed, in the service layer, by having defined "aop config" elements with "proxy class" attribute and having an explicit <aop:aspectj-autoproxy proxy-target-class="true"/> should take care of the cglib issue.

    Can any one help.

    thanks for reading.

    ~s.
    Last edited by some one; Jul 13th, 2011, 03:59 PM.

  • #2
    You have mutiple proxies. You are basically proxying proxies...

    Why do you have 2 aop:config blocks? Merge them into one, you also have aop:aspectj-autoproxy which is creating proxies also... You are mixing proxy strategies which in general isn't a good idea.

    Comment


    • #3
      aggregating aop configs did not help

      Thank you for advice. I aggregated all the aspects into one aop config block, but still I get the same class cast exception.

      Code:
      java.lang.ClassCastException: $Proxy21  cannot be cast to ...
      I did not intend to mix strategies but it was like the last thing that i tried to fix this.

      the new aop-config block

      Code:
       <bean id="encryptAspect" class="com.netmemex.netmx.aop.EncryptBeforeAspect" />    
      
       <aop:config proxy-target-class="true">
      		<aop:aspect ref="encryptAspect">
                  <aop:pointcut id="encryptAcct" 
                  expression="execution(* com.netmemex.netmx.service.transactions.impl.PayInstrumentServiceImpl.save(..)) and args(pi)"/>
                  <aop:before pointcut-ref="encryptAcct" method="encryptAccountNumber" />
              </aop:aspect>
              <aop:aspect ref="encryptAspect">
                  <aop:pointcut id="encryptTransaction" 
                  expression="execution(* com.netmemex.netmx.service.transactions.impl.TransactionServiceImpl.save(..)) and args(t)"/>
                  <aop:before pointcut-ref="encryptTransaction" method="encryptTrxAccountNumber" />
              </aop:aspect>
      ...
      </aop-config>
      just to be clear as regards to the above block EncryptBeforeAspect is a pojo with no decorations.

      what am i missing here ?

      thanks for reading

      Comment


      • #4
        I commented off anything to do with aop. and I still get the exception.

        I, then added just one dummy

        Code:
        <aop:config proxy-target-class="true"/>
        and that did not work either.

        Now I am out of ideas of how to force the application to use cglib.
        Checklist of possible solutions
        a. Program to interfaces. : All Dao, service classes and threads implement interfaces. Hibernate mapping pojos, Controllers, webflow formactions, and other utility functions for encryption etc do not. And that is acceptable.
        b. Use Runnable instead of Thread: This is the first runnable interface I am implementing in this application and there are no classes extending java.lang.Thread
        c. Make sure the proxies are not jdk proxies but cglib I am trying to do that but I am unable to force this.

        Maybe I am trying to solve the wrong problem or may be i am missing a solution.

        Comment


        • #5
          issue fixed.

          It really had nothing to do with aop config after all.

          The issue was the ClassCastException was occurring when because I wanted to give the TaskExecutor an object that implements Runnable. My interface was not "Runnable" but my implementation was.

          What I did was make my thread interface extend Runnable.

          Code:
          public interface ComplexDuesProcessingThread extends Runnable
          {
              public Map<Long, Long> getChargeIdMap();
              
              public ComplexDuesForm getDuesForm();
              
              public Master getLoggedUser();
              
              public void run();
          ..
          }
          I removed the 'implements Runnable' from the implementation
          Code:
          @Service("complexDuesProcessing")
          @Scope("prototype")
          public class ComplexDuesProcessingThreadImpl implements
          	ComplexDuesProcessingThread
          {
          ..
          }
          in the test case i no longer needed to cast it to the implementation class so i got rid of the class cast exception.
          Code:
          @RunWith(SpringJUnit4ClassRunner.class)
          @ContextConfiguration(locations = { "classpath:com/netmemex/netmx/deploy/service-layer.xml" })
          @Transactional
          public class DuesProcessServiceTest
          {
              private static final Logger log = Logger
          	    .getLogger(DuesProcessServiceTest.class); // logger
          // instance of AccountingDefaultService
              @Autowired
              @Qualifier("serviceFactory")
              private ComplexDuesProcessingServiceFactory complexDuesProcessingServiceFactory;
          
          // instance of AccountItemService
              @Autowired
              @Qualifier("executorWithPoolSizeRange")
              private TaskExecutor taskExecutor;
          
           
              @Test
              public void getProcess() throws NetmemexServiceException
              {
          
          	ComplexDuesProcessingThread thread = this
          		.getComplexDuesProcessingServiceFactory().getService(
          			"complexDuesProcessing");
          	log.debug(this.getComplexDuesProcessingServiceFactory().getService(
          		"complexDuesProcessing").getClass().getName());
          	
          	this.getTaskExecutor().execute(thread);
          	log.debug("done");
              }
          i put up the code just in case. Also re reading the reference doc a few times helped.

          @marten according to the doc
          Multiple <aop:config/> sections are collapsed into a single unified auto-proxy creator at runtime, which applies the strongest proxy settings that any of the <aop:config/> sections (typically from different XML bean definition files) specified. This also applies to the <tx:annotation-driven/> and <aop:aspectj-autoproxy/> elements.
          so i assume even having a single aop config with proxy-target-class="true" make cglib applicable to all proxies. But your idea of making a single aop-config makes the application context file cleaner and more readable.

          However I will investigate "You are basically proxying proxies." I am however unsure how to begin.
          Last edited by some one; Jul 13th, 2011, 03:57 PM.

          Comment


          • #6
            The issue was the ClassCastException was occurring when because I wanted to give the TaskExecutor an object that implements Runnable. My interface was not "Runnable" but my implementation was.
            which would be strange if you use cglib because it shouldn't matter, it would create a class proxy... For some reason I suspect this was still using a Jdk Proxy (or maybe a proxied proxy).

            Comment


            • #7
              epilogue

              apparently this is not entirely accurate.

              Multiple <aop:config/> sections are collapsed into a single unified auto-proxy creator at runtime, which applies the strongest proxy settings that any of the <aop:config/> sections (typically from different XML bean definition files) specified. This also applies to the <tx:annotation-driven/> and <aop:aspectj-autoproxy/> elements.
              i think it was using jdk proxies inspite of
              Code:
               <aop:aspectj-autoproxy proxy-target-class="true"/>
              and
              Code:
              <aop:config proxy-target-class="true">
              ...
              I went through all the context files for web, web service and webflow and found a couple of aop:config blocks with out proxy-target-class.

              thanks for your help.

              ~s.

              Comment

              Working...
              X