I am learning spring and I was just playing around with ApplicationContextAware and bean scopes.
I will be attaching the code and then describe what I want to do.
So far, I have created a
Point class:
public class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "x: "+this.x+",y: "+this.y;
}
}
I have created a Triangle class which has 3 instances of this Point class:
public class Triangle implements ApplicationContextAware, BeanNameAware{
private Point pointA;
private Point pointB;
private Point pointC;
private String beanName;
private ApplicationContext context=null;
public Point getPointA() {
return pointA;
}
public void setPointA(Point pointA) {
this.pointA = (Point)this.context.getBean("point1");
}
public Point getPointB() {
return pointB;
}
public void setPointB(Point pointB) {
this.pointB = (Point)this.context.getBean("point2");
}
public Point getPointC() {
return pointC;
}
public void setPointC(Point pointC) {
this.pointC = (Point)this.context.getBean("point3");
}
public void draw() {
System.out.println("BeanName is: "+this.beanName);
System.out.println(pointA);
System.out.println(pointB);
System.out.println(pointC);
}
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
this.context = arg0;
}
@Override
public void setBeanName(String arg0) {
this.beanName = arg0;
}
}
Below is spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 5.1.1//EN" "http://www.springframework.org/dtd/spring-beans-5.1.1.dtd">
<beans>
<bean id="triangle" class="org.java.learning.Triangle" >
<property name="pointA" ref="point1" />
<property name="pointB" ref="point2" />
<property name="pointC" ref="point3" />
</bean>
<bean id="point1" class="org.java.learning.Point" scope="prototype">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="org.java.learning.Point" scope="prototype">
<property name="x" value="20" />
<property name="y" value="20" />
</bean>
<bean id="point3" class="org.java.learning.Point" scope="prototype">
<property name="x" value="-20" />
<property name="y" value="20" />
</bean>
And this is the Main class:
public class DrawingApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Triangle t = (Triangle) context.getBean("triangle");
t.draw();
}
}
So, you would have seen that bean scope of three beans, point1, point2 and point3 is prototype, but they are members of bean triangle, whose scope by default is singleton in spring.xml
So, my assumption is, this should not work, unless I can somehow get ApplicationContext in my Triangle class and set pointA, pointB, pointC respectively like I have done in their setter methods using ApplicationContext.
Not sure if this is correct way or not, or how useful is this thing in live applications.
So, if it all above code works, I should get three lines output like:
x: 0,y: 0
x: 20,y: 20
x: -20,y: 20
But when I run the main method I get following error:
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'triangle' defined in class path resource [spring.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (3) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'pointA' threw exception; nested exception is java.lang.NullPointerException PropertyAccessException 2: org.springframework.beans.MethodInvocationException: Property 'pointB' threw exception; nested exception is java.lang.NullPointerException PropertyAccessException 3: org.springframework.beans.MethodInvocationException: Property 'pointC' threw exception; nested exception is java.lang.NullPointerException Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'triangle' defined in class path resource [spring.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (3) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'pointA' threw exception; nested exception is java.lang.NullPointerException PropertyAccessException 2: org.springframework.beans.MethodInvocationException: Property 'pointB' threw exception; nested exception is java.lang.NullPointerException PropertyAccessException 3: org.springframework.beans.MethodInvocationException: Property 'pointC' threw exception; nested exception is java.lang.NullPointerException at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1685) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1400) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85) at org.java.learning.DrawingApp.main(DrawingApp.java:9) Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (3) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'pointA' threw exception; nested exception is java.lang.NullPointerException PropertyAccessException 2: org.springframework.beans.MethodInvocationException: Property 'pointB' threw exception; nested exception is java.lang.NullPointerException PropertyAccessException 3: org.springframework.beans.MethodInvocationException: Property 'pointC' threw exception; nested exception is java.lang.NullPointerException at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:122) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:77) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.app lyPropertyValues(AbstractAutowireCapableBeanFactory.java:1681) ... 13 more
I believe I have done something wrong while setting the values of pointA, pointB and pointC member variables
Please let me know if any details required from my side, to get rid of this error and achieve what I am trying to do.
getBean:getBean(Triangle.class). - chrylis -cautiouslyoptimistic-public void setPointB(Point pointB) { this.pointB = (Point)this.context.getBean("point2"); }. If you are injecting via setter you should have to have "bean-standard" setter - smsnheck