Autowiring in spring (property name and bean name must be same) - java

public class B {
public B(){
System.out.println("B is created");
}
public void print(){
System.out.println("hello b");
}
}
class B.java
public class A {
B c;
public A(){
System.out.println("a is created");
}
public B getB(){
return c;
}
public void setB(B c){
this.c =c;
}
void print(){
System.out.println("hello a");
}
void display(){
print();
c.print();
}
}
class A.java
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="b" class="B"></bean>
<bean id="a" class="A" autowire="byName"></bean>
</beans>
applicationcontext.xml
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
A a1 = context.getBean("a",A.class);
a1.display();
}
}
Test .java
i was going through the tutorials on autowiring in spring by using "byName" mode. and it says- The byName mode injects the object dependency according to name of the bean. In such case, property name and bean name must be same. It internally calls setter method.
but in this application the property name and the bean name both are different but it still works fine,so how this autowiring is working even though the both names are different?

It says property name, not field name.
Property name in this case is inferred from the setter method name as defined by the JavaBeans naming convention (setB -> b), thus property name and bean name are the same.

Related

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'car' is defined

Can anyone tell me what is the error in this program and how to correct the error? I have given proper annotation and still getting errors.
I need help fixing this error I get when trying to deploy . Why isn't the Car bean being defined? Am I missing something in my web.xml or do I have to map the customerService somehow? I am using annotations for mapping. any help would be much appreciated. Here is the error log entry from the localhost log:
App.java
package om.venkatesh.omshakthi;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
public static void main( String[] args )
{
ApplicationContext context=new ClassPathXmlApplicationContext("Spring.xml");
Car obj=(Car)context.getBean("car");
obj.drive();
}
}
Car.java
package om.venkatesh.omshakthi;
import org.springframework.stereotype.Component;
#Component
public class Car implements Vehicle{
public void drive()
{
System.out.println("Car");
}
}
Vehicle.java
package om.venkatesh.omshakthi;
public interface Vehicle {
void drive();
}
Spring.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:context = "http://www.springframework.org/schema/context"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="tyre" class="om.venkatesh.omshakthi.Tyre">
</bean>
</beans>
Without xml you can do it like this:
Create config class:
#Configuration
public class AppConfig {
#Bean
public Car car() {
return new Car();
}
}
Main class:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);
ctx.refresh();
Car car = (Car) ctx.getBean("car");
car.drive();
}
}
Spring.xml has no bean with id "car" (although there is one for "tyre")
You need to define your bean in XML
<bean id="car" class="om.venkatesh.omshakthi.Car">
You don`t need #Component annotation when you use ClassPathXmlApplicationContext.
Just define a Car bean in your xml:
<bean id="car" class="om.venkatesh.omshakthi.Car">

Spring Boot trying to resolve bean not in my xml

I want to test a class that simple shutdown the application:
#Component
public class ShutdownManager {
#Autowired
private ApplicationContext applicationcontext;
public int shutdown(int returnCode) {
return SpringApplication.exit(applicationcontext, () -> returnCode);
}
}
The test case I created is this:
public class ShutdownManagerTest {
#Test
public void should_shutdown_gracefully() {
SpringApplication app = new SpringApplication(TestClass.class);
ConfigurableApplicationContext context = app.run();
ShutdownManager shutdownManager = (ShutdownManager)context.getBean("shutdownManager");
int result = shutdownManager.shutdown(10);
assertThat(result).isEqualTo(10);
}
#SpringBootApplication
#ImportResource("classpath:/core/shutdownmanagertest.xml")
private static class TestClass {
public TestClass() {
}
public static void main(String[] args) {
}
}
}
My shutdownmanagertest.xml contains only one bean:
<?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.xsd">
<bean id="shutdownManager" class="com.mycodebase.ShutdownManager" />
</beans>
However, when I run this, it complains that:
Field myOtherService in com.mycodebase.MyTask required a bean of type 'com.mycodebase.MyOtherService ' that could not be found.
The class MyTask is in the same package of the ShutdownManager which contains a field myOtherService which has an #Autowire annocation. But it is not defined in my test xml which contains just one bean.
Can someone help me understand why it tries to resolve a bean that is not in the context?
It's doing that because that's how #SpringBootApplication works.
#SpringBootApplication:
This is a convenience annotation that is equivalent to declaring #Configuration, #EnableAutoConfiguration and #ComponentScan.
#ComponentScan
If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.
So everything in the same or a subpackage of ShutdownManagerTest is being picked up.

how to make a bean prototype using only #scope("prototype) annotation in spring?

i have this main class
public class Draw {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Triangle t = (Triangle) context.getBean("triangle");
Triangle t1 = (Triangle) context.getBean("triangle");
t.show();
System.out.println(t == t1);
}
}
TRIANGLE CLASS
#Service
#Scope("prototype")
public class Triangle {
private Point pointa;
public Point getPointa() {
return pointa;
}
public Triangle(Point pointa) {
this.pointa = pointa;
}
public void show() {
System.out.println("POINT A (" + pointa.getX() + "," + pointa.getY() + ")");
}
#Override
public String toString() {
return "Triangle [pointa=" + pointa + "]";
}
}
AND SPRING.XML
<context:component-scan base-package="com.spring.demo" />
<mvc:annotation-driven />
<context:component-scan base-package="com.spring.demo" />
<bean id="triangle" class="com.spring.demo.Triangle" autowire="constructor">
</bean>
<bean id="pointabc" class="com.spring.demo.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<context:annotation-config />
i know that to make a bean prototype we use scope="prototype" in spring.xml.
but i want to make bean prototype by using #scope("prototype") only.
i don't know why the above code is not working correctly.
I've researched a lot but couldn't find any answer
System.out.println(t == t1); this gives me true while ideally it should be false.
Declaring Triangle as prototype has no effect as it is instantiated in your spring.xml as singleton.
The key is to ask for a new prototype bean everytime you need one.
This can be achieved by using a configuration class (and removing <bean id="triangle" ... from spring.xml:
package com.spring.demo;
#Configuration
public class MyProvider {
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Triangle create() {
return new Triangle();
}
}
Usage is as follows:
package com.spring.demo;
#Component
public class MySingleton {
#Autowired
private MyProvider myProvider;
#PostConstruct // will execute this method once app context loaded
public void doStuffThatNeedsAPrototypeBeanInstance() {
Triangle t1 = myProvider.create();
Triangle t2 = myProvider.create();
...
}
}
Adding a #PostConstruct has the effect that the method is called once the application context has been initialized, as alternative to running things in the main method. This way, execution is inside a spring bean with the benefit of easily accessing other spring beans through annotations.
As ApplicationContext has several implementations, ClassPathXmlApplicationContext one is used for XML bean configuration.
In XML ways you simply set the scope attribute in bean element.
AnnotationConfigApplicationContext is implementation of ApplicationContext used for Java Based Configuration means for annotation based configuration like #Bean etc.
If you want to use annotation way, then you need to define Java Based Configuration and need to use AnnotationConfigApplicationContext object.
#Configuration
public class AppConfiguration{
#Bean
#Scope("prototype")
public Triangle triangle(){
return new Triangle();
}
}
Then obtained the bean as below.
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfiguration.class);
Triangle triangle= ctx.getBean(Triangle.class);
for annotation configuration we use AnnotationConfigApplicationContext an implementation of Abstract Application Context
public class Scope{
public static void main(String[] args) {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(TeacherConfig.class);
Teacher tea=(Teacher) context.getBean("teacher");
Teacher tea1=(Teacher) context.getBean("teacher");
System.out.println(tea==tea1);
}
}
TEACHER CLASS
public class Teacher {
public void print(String msg){
System.out.println("TEACHER -->"+msg);
}
TeacherConfig
#Configuration
public class TeacherConfig {
#Bean(name = "teacher")
#Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON)
public Teacher Teacher() {
return new Teacher();
}
}
#Configuration to tell Spring that this is the core Spring configuration file equivalent to spring.xml, and define bean via #Bean.
OUTPUT OF System.out.println(tea==tea1); is TRUE
By extending the answer given by #AshishUpadhyay, I made couple of changes in code. The above answer is for singleton scope. For prototype need to make few changes.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class Scope{
public static void main(String[] args) {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(TeacherConfig.class);
Teacher tea=(Teacher) context.getBean(Teacher.class);
Teacher tea1=(Teacher) context.getBean(Teacher.class);
System.out.println(tea);
System.out.println(tea1);
System.out.println(tea==tea1);
}
}
Teacher class:
public class Teacher {
public void print(String msg) {
System.out.println("TEACHER -->" + msg);
}
}
TeacherConfig class:
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
#Configuration
public class TeacherConfig {
#Bean()
#Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Teacher Teacher() {
return new Teacher();
}
}
After running the Scope class the output is false which is expected in case of prototype.
Hope this will help someone.

How do I inject property from one bean into another in Spring 3.0?

In Spring 3.0.2, I am trying to inject the property of Bean A into another Bean B, but the Spring EL isn't working.
Bean A is being created manually in Java. Bean B is created through XML.
In this case Bean A is Potato and Bean B is Baby (both in package springinit).
Bean A (Potato):
public class Potato {
String potatoType;
public String getPotatoType() { return potatoType; }
public void setPotatoType(String potatoType) { this.potatoType = potatoType; }
#Override
public String toString() {
return "Potato{" + "potatoType=" + potatoType + '}';
}
}
Bean B (Baby):
public class Baby {
private String name;
private Potato potatoThing;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Potato getPotatoThing() { return potatoThing; }
public void setPotatoThing(Potato p) { this.potatoThing = p; }
#Override
public String toString() {
return "Baby{" + "name=" + name +
", potatoThing=" + potatoThing + '}';
}
}
In my Main class, I create a Potato and use it in the XML when trying to make a Baby
package springinit;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
GenericApplicationContext ctx= new GenericApplicationContext();
// define java-based spring bean
ctx.registerBeanDefinition("myPotato",
genericBeanDefinition(Potato.class)
.addPropertyValue("potatoType", "spudzz")
.getBeanDefinition());
// read in XML-bean
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(
new ClassPathResource("/resources/spring_init.xml"));
// print out results
System.out.format(
"Baby: %s%n%n" +
"Potato: %s%n",
ctx.getBean(Baby.class),
ctx.getBean(Potato.class)
);
}
}
Here's my spring_init.xml:
<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-3.0.xsd">
<bean id="myBaby" class="springinit.Baby" depends-on="myPotato">
<property name="name" value="#{myPotato.potatoType}" />
<property name="potatoThing">
<ref bean="myPotato" />
</property>
</bean>
</beans>
When I run main, I get this output:
Baby: Baby{name=#{myPotato.potatoType}, potatoThing=Potato{potatoType=spudzz}}
Potato: Potato{potatoType=spudzz}
I want the baby's name to be "spudzz", which is a property of myPotato. Why won't spring inject this value into the baby?
Thank you for reading. I hope it was clear enough.
Perhaps you need to call ctx.refresh() before getting beans.
From javadoc:
Typical usage is to register a variety of bean definitions via the BeanDefinitionRegistry interface and then call AbstractApplicationContext.refresh() to initialize those beans with application context semantics (handling ApplicationContextAware, auto-detecting BeanFactoryPostProcessors, etc).

Spring: Nested application contexts

I have a hierarchy of application contexts. The bean that is defined in the parent context depends on a bean that is defined in the child. Here's how it looks like:
public class X {
public static class A {
public B b;
public void setB(B b) { this.b = b; }
}
public static class B { }
public static void main(String[] args) {
ClassPathXmlApplicationContext parent = new ClassPathXmlApplicationContext(
"/a.xml");
go1(parent);
}
public static void go1(ClassPathXmlApplicationContext parent) {
GenericApplicationContext child = new GenericApplicationContext(parent);
child.getBeanFactory().registerSingleton("b", new B());
A a = (A) child.getBean("a");
Assert.assertNotNull(a.b);
}
}
The xml file defining the "a" bean looks like this:
<?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-2.5.xsd">
<bean id="a" class="X$A" autowire="byName" lazy-init="true"/>
</beans>
The problem is that B is not injected into A. Injection will occur only if I register the "b" singleton with the parent - which is not an option in my program.
Any ideas?
You can't do that. Parent contexts cannot refer to bean definitions in the child contexts. It only works the other way around.

Categories