I am a new user of spring. I am trying to achieve dependency injection by annotation. My
beans.xml is :-
<!-- Add your classes base package here -->
<context:component-scan base-package="com.springaction.chapter01"/>
<bean id="greeting" class="com.springaction.chapter01.GreetingImpl">
<property name="greeting">
<value>Naveen Jakad</value>
</property>
</bean>
bean which I want to inject is:-
package com.springaction.chapter01;
import org.springframework.stereotype.Service;
#Service
public class InjectBean {
private int id;
private String name;
public InjectBean() {
super();
}
//setter getter of above instance variables..
}
and the bean in which I want to inject above bean is :-
package com.springaction.chapter01;
import org.springframework.beans.factory.annotation.Autowired;
public class GreetingImpl implements Greeting {
private String greeting;
#Autowired
private InjectBean myBean;
public GreetingImpl() {
super();
}
public GreetingImpl(String greeting) {
super();
this.greeting = greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
#Override
public void sayGreeting() {
System.out.println(greeting + " " + myBean);
}
}
so when I test the above code by :-
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("config.xml"));
Greeting greeting = (Greeting)beanFactory.getBean("greeting");
greeting.sayGreeting();
I get the output "Naveen Jakad null", means in nutshell I am not able to achieve my target. So please help me out and let me know where I making mistake
if you want to inject by #Autowired you don't need to config it in xml :)
You need to set
<mvc:annotation-driven />
<context:component-scan base-package="com.your.base.package" />
That way spring will know to check for annotations
With Fixus solution you do not need the xml file where you define the "greeting" bean:
Just add:
#Component // or #Service if it's also a service
public class GreetingImpl implements Greeting {
This way you do not need to define your beans in the xml file.
If you use Junit test, you just inject the class to test (e.g "Greeting") in your MyJunitClass and have your context set to the one with the annotation-driven and component -scan definition.
You can see that doc to configure your JUnit tests:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/testing.html#integration-testing-annotations
Related
Does anyone know if I should be able to use property placeholder as an expression in a Qualifier? I can't seem to get this working.
I am using spring 3.0.4.
#Controller
public class MyController {
#Autowired
#Qualifier("${service.class}")
Service service;
}
#Service
#Qualifier("ServiceA")
ServiceA implements Service {
public void print() {
System.out.println("printing ServiceA.print()");
}
}
#Service
#Qualifier("ServiceB")
ServiceB implements Service {
public void print() {
System.out.println("printing ServiceB.print()");
}
}
XML:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:/etc/config.properties"/>
</bean>
config.properties:
config.properties
service.class=serviceB
This works. You can leave off the service names if you just use the default spring bean name. serviceA vs ServiceA, etc.
#Controller
class MyController {
#Autowired(required=false)
#Qualifier("Service")
Service service;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("app-ctx.xml", MyController.class);
for(String s:context.getBeanDefinitionNames()){
System.out.println(s);
for(String t:context.getAliases(s)){
System.out.println("\t" + t);
}
}
context.getBean(MyController.class).service.print();
}
}
public interface Service {
void print();
}
#Service(value="ServiceA")
public class ServiceA implements example.Service {
public void print() {
System.out.println("printing ServiceA.print()");
}
}
#Service(value="ServiceB")
public class ServiceB implements example.Service {
public void print() {
System.out.println("printing ServiceB.print()");
}
}
XML:
<beans>
<alias name="${service.class}" alias="Service"/>
<context:property-placeholder location="example/app.properties"/>
<context:component-scan base-package="example"/>
<beans>
Props:
service.class=ServiceB
This solution works without XML and with properties file.
Yours classes improved:
MyController.java:
#Controller
public class MyController {
#Autowired
public MyController(#Qualifier("MyServiceAlias") MyService myService) {
myService.print();
}
}
ServiceA.java:
#Service("serviceA")
public class ServiceA implements MyService {
#Override
public void print() {
System.out.println("printing ServiceA.print()");
}
}
ServiceB.java:
#Service("serviceB")
public class ServiceB implements MyService {
#Override
public void print() {
System.out.println("printing ServiceB.print()");
}
}
application.properties (here you can change which class will be loaded):
service.class=serviceA
And important configuration file AppConfig.java:
#Configuration
public class AppConfig {
#Autowired
private ApplicationContext context;
#Bean
public MyService MyServiceAlias(#Value("${service.class}") String qualifier) {
return (MyService) context.getBean(qualifier);
}
}
Additional explanations:
Use #Qualifier only for field which will be autowired. For services, to specify bean name, use #Service.
If you want standard bean name you don't need to use #Service with specyify name. For example, standard bean name for ServiceA is serviceA (not ServiceA - see big first letter), so #Service("serviceA") redundant (#Service is enough).
I based AppConfig on this answer: Spring Bean Alias in JavaConfig.
This solution is better than this Spring Qualifier and property placeholder, because you don't need XML.
Tested on Spring Boot 1.5.7.
I would venture to guess the answer is no, just based on the write ups in a few javadoc pages. For example, see the docs for #Value:
http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Value.html
Notice they make special mention of using expressions in the annotation. For comparison, the docs for #Qualifier:
http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/beans/factory/annotation/Qualifier.html
Which make no mention of expressions. Obviously not a definitive answer (but spring is generally very good on documentation). Also, if expressions were supported in the #Qualifier annotation I would expect they work the same way as the #Value annotation (just based on spring being a very consistent framework).
Spring 3.1 has the new profile bean feature, which seems like it can accomplish something like what you're trying to do. Here's a write up for that:
http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/
As a workarround, you can set the desired Spring service implementation based on its name in your config.properties.
#Controller
public class MyController {
//add a String which will hold the name of the service to implement
#Value("${service.class}")
private String serviceToImplement;
Service service;
// now autowire spring service bean based on int name using setter
#Autowired
public void setService(ApplicationContext context) {
service = (Service) context.getBean(serviceToImplement);
}
}
#Service
#Qualifier("ServiceA")
ServiceA implements Service {
public void print() {
System.out.println("printing ServiceA.print()");
}
}
#Service
#Qualifier("ServiceB")
ServiceB implements Service {
public void print() {
System.out.println("printing ServiceB.print()");
}
}
config.properties
service.class=serviceB
Maybe give this a whirl:
#Controller
public class MyController {
private String serviceId;
#Value("${serviceId}")
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
#Autowired
#Qualifier(serviceId)
Service service;
}
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.
I am very new to SO,I have working on the task where Load environment configurations and properties according to the environment like (dev,prod,test),I have been successfully achieved database configuration on DAO level by using <beans profile="profile.name">. In front end side I have to get properties file according to the environment so I have the different files. to call that i have tried the below code:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class PropertiesUtility {
#Value("${mount.images.webpath}")
private String imagePath;
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
#Override
public String toString() {
return "PropertiesUtility{" +
"imagePath='" + imagePath + '\'' +
'}';
}
}
My context.xml configuration:
<context:annotation-config/>
<beans profile="dev">
<context:property-placeholder location="classpath:properties/pharmisa_web_conf.properties"
ignore-unresolvable="true" />
</beans>
<beans profile="test">
<context:property-placeholder location="classpath:properties/pharmisa_web_test_conf.properties"
ignore-unresolvable="true" />
</beans>
Calling PropertiesUtility:
public class URLUtility {
#SpringBean //even #Autowired also not working
static PropertiesUtility propertiesUtility;
public static String getCompanyLogoUrl(int id) {
StringBuffer sb = new StringBuffer(getImagePath());
boolean isEndWithSlash=PharmisaStringUtils.endsWith(getImagePath(),"/");
if (!isEndWithSlash){
sb.append("/");
}
sb.append(id);
sb.append("/");
return sb.toString();
}
private static final String getImagePath() {
return propertiesUtility.getImagePath().trim();
}
}
SpringJunitTest
Test working perfectly
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:spring/pharmisa_web-context.xml"})
#ActiveProfiles(profiles = "test")
public class CompanyServiceImplTest {
#Autowired
PropertiesUtility propertiUtility;
#Test
public void testAppProperties() {
System.out.println(propertiUtility.getImagePath());
}
}
When i tried to inject PropertiesUtility class in wicket page .I am not getting the value of the properties. because it is not injected. I have aware of #SpringBean in wicket but even though it is not working.
Is there anyway to get the value any alternative welcomes.
For your further i have followed the link
http://examples.javacodegeeks.com/enterprise-java/spring/load-environment-configurations-and-properties-with-spring-example/
URLUtility should be a Spring bean if you want #Component or #Autowire to work.
#SrpingBean works automatically only in Wicket components. In anything else you need to "ask for injection" explicitly with Injector.get().inject(this).
I have a method on my service, where I included a packaged (that is in a jar) from other libraries (that I cannot modify).
So, the included packages are in other contexts (I can reach them because they were included on my pom).
At the end, the problem is this.
On the class myService I have
private SomeService someService;
private boolean doSommething() {
try {
success = someService.somemethod();
} catch (InterruptedException exc) {
...
}
}
return success;
}
#Required
public void setMyService(SomeService someService) {
this.someService = someService;
}
From my app, I always get someService as null. Is there anyway to configure this to make it work? Like a bean configuration or something?
In your bean definitions, add this:
<bean id="someService" class="SomeService"/>
<bean id="myService" class="MyService">
<property name="someService" ref="someService"/>
</bean>
Make sure the method name in MyService is:
setSomeService(SomeService someService)
With annotation you can inject the dependency like below
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
#Component
public class CallingService {
#Autowired
protected SomeService someService ;
}
I have a requestScope bean, regular Java bean, and Spring configuration just like the code shown below. May I know how can I access the bean's property from regular Java code that is configured with Spring?
Managed Bean
#ManagedBean(name="requestBean")
public class RequestBean {
private String theID;
/** getter and setter of theID **/
}
Spring Bean
public class SpringBean {
private RequestBean theBean = null;
// how could I access the RequestBean.theID from this class ??
}
Spring configuration
<bean id="springBean" class="org.huahsin.SpringBean"/>
Maybe I do not understand the question, but I think it is simply by calling the getter:
public class SpringBean {
private RequestBean theBean = null;
...
public void aCallingMethod() {
if (theBean != null) {
theBean.getTheId(); // <-- here it is !!
}
}
}
EDIT
To inject the request bean into the Spring bean, either you use an #Autowired annotation:
public class SpringBean {
#Autowired
private RequestBean theBean = null;
...
}
Either you inject it in your XML file:
<bean id="springBean" class="org.huahsin.SpringBean">
<property name="theBean" ref="requestBean"/>
</bean>