subbu royal
subbu royal

Reputation: 65

How to solve BeanNotOfRequiredTypeException

I am writing a small application to check the functionality of "AfterAdvice" concept in spring-AOP but i am getting an exception related to xml file (I think) please help me how to solve the exception

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="pinCheck" class="com.nt.advice.AtmPinVerifierAdvice" />
<bean id="targetBean" class="com.nt.service.AtmPinGenerator" />
<bean id="pfb" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="targetBean" />
    <property name="interceptorNames">
        <list>
            <value>pinCheck</value>
        </list>
    </property>
  </bean>
</beans>

ClientApp.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.nt.service.AtmPinGenerator;
public class ClientApp {
public static void main(String[] args) {
    //activate IOC container
    ApplicationContext ctx = new    FileSystemXmlApplicationContext("src/com/nt/cfgs/applicationContext.xml");
    //get proxy obj
    AtmPinGenerator gen = ctx.getBean("pfb",AtmPinGenerator.class);
    //call b.method
    gen.pinGenerator();
  }

}

AtmPinGenerator.java

import java.util.Random;
public class AtmPinGenerator extends Random {
//generating pin
public int pinGenerator(){
    //creat java.util.Random object 
    Random rad = new Random();
    //use nextInt() to generate random pin of 4 digits
    int pin = rad.nextInt(9999);
return pin;
  }//pinGenerator
}

AtmPinVerifierAdvice.java

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class AtmPinVerifierAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object retValue, Method method, Object[] args,
        Object target) throws Throwable {
    System.out.println(retValue);
    Integer pin = (Integer)retValue;
    //if generated pin is less than four digit throw an exception
    if(pin<=999)
        throw new IllegalArgumentException("invalid pin");
  }//afterReturning
}//AtmPinVerifierAdvice

If I run the above application I am getting this Exception

Output

Aug 17, 2015 2:03:57 PM     org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing     org.springframework.context.support.FileSystemXmlApplicationContext@3ff14318:     startup date [Mon Aug 17 14:03:57 IST 2015]; root of context hierarchy
Aug 17, 2015 2:03:57 PM     org.springframework.beans.factory.xml.XmlBeanDefinitionReader     loadBeanDefinitions
INFO: Loading XML bean definitions from file     [G:\java\Frameworks\SpringAOP\AOPProj6(After advice - pin verifier     decl)\src\com\nt\cfgs\applicationContext.xml]
Exception in thread "main"     org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named     'pfb' must be of type [com.nt.service.AtmPinGenerator], but was actually of type     [com.sun.proxy.$Proxy2]
    at     org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(Abstract    BeanFactory.java:375)
at     org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBe    anFactory.java:199)
at     org.springframework.context.support.AbstractApplicationContext.getBean(AbstractA    pplicationContext.java:962)
at test.ClientApp.main(ClientApp.java:14)

I don't why I am getting Exception. please any one help me why this exception is raising?

Upvotes: 4

Views: 8951

Answers (1)

M. Deinum
M. Deinum

Reputation: 125292

Spring by default uses JDK Dynamic proxies, which are interface based, for applying AOP.

Your AtmPinGenerator extends Random which implements Serializable. Spring sees the interface and uses interface based proxies. You will get a proxy implementing only the Serializable interface.

You have 3 options to solve it

  1. Force class based proxies by configuring the ProxyFactoryBean
  2. Create an interface and implement it
  3. Force class based proxies by not extending Random.

The last option would be the easiest simply don't extend Random, this will force the use of class-based proxies.

public class AtmPinGenerator {

    public int pinGenerator(){
        Random rad = new Random();          
        return rad.nextInt(9999);
    }
}

You could also set the proxyTargetClass property of the ProxyFactoryBean to true and then you don't need to change your class.

<property name="proxyTargetClass" value="true" />

The last option is to introduce an interface and simply expose the pinGenerator() method on it and let your AtmPinGenerator implement that interface.

public interface PinGenerator {

    int pinGenerator();
}

public class AtmPinGenerator implements PinGenerator { ... }

This way you are using interface based proxied. In your main method now use the PinGenerator interface instead of the AtmPinGenerator.

Upvotes: 5

Related Questions