spring #value returns null - java

I'm using spring 3.2.2 and what to inject some string in my .properties file into a class. But always get null.
In my applicationContext.xml:
....
<context:component-scan base-package="com.mypackage">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/
</context:component-scan>
<context:property-placeholder location="classpath:/config/core/abc.properties"/>
....
in abc.properties:
path=testpath
in java code:
package com.mypackage
#Component
public class myclass implements Imyclass {
#Value("${path}")
private String path; //this always is null
...
public String getMyPath() {
return path+"myclass";
}
}
what I'm missing here?
[Edit]
the reason is in my code someone is calling new Imyclass().
Now there is another class impelement Imyclass:
package com.mypackage
#Component
public class myclass2 implements Imyclass {
#Value("${path}")
private String path; //this always is null
...
public String getMyPath() {
return path+"myclass2";
}
}
The function calling the Imyclass:
public class myClassContext {
public static String getPath(...){
return getImyclass(...).getMyPath();
}
private static Imyclass getImyclass(....){
Imyclass mc=null;
if (.....) {
mc=new myclass();
}
else{
mc=new myclass2();
}
return state;
}
}
What's the better way to manage the instance by Spring so the #value will inject correctly?
Do I have to inject both class into myClassContext as a property or use the #Configurable for both myclass and myclass2?

Related

How to call super constructor with params from abstract class if current class is spring bean?

I have two classes from custom library, that i can't change. Bass class have only constructor with custom param, that's not a bean. I want to pass param via child constructor, but i have no idea how to do that, so please help)
I tried this, but doesn't work. Idea underline param in Child constructor.
#Bean
public ChildClass childClass() {
return new ChildClass(new CustomParam(5));
}
Base class- can't use #Component, that class from library
public abstract class BaseClass {
private CustomParam customParam;
protected BaseClass(CustomParam customParam) {
this.customParam = customParam;
}
public Integer getCustomParam() {
return customParam.getParamValue();
}
}
Child class. My own extension
#Component
public class ChildClass extends BaseClass {
//idea underline customParam "could not autowire"
public ChildClass(CustomParam customParam) {
super(customParam);
}
}
Param class- can't use #Component, that class from library
public class CustomParam {
private Integer paramValue;
public CustomParam(Integer paramValue) {
this.paramValue = paramValue;
}
public Integer getParamValue() {
return paramValue;
}
public void setParamValue(Integer paramValue) {
this.paramValue = paramValue;
}
}
CustomParam need not to be annotated with #Component annotation, still you can declare it as bean using#Bean annotation
Config class
#Bean
public ChildClass childClass() {
return new ChildClass(customParam());
}
#Bean
public CustomParam customParam() {
return new CustomParam(5);
}
This should work. If you instantiate your bean like this you don't need the #Component annotation on your ChildClass. Make sure your bean definition is in a configurationclass (#Configuration) and your config is part of the component scan.
#Configuration
public class Config {
#Bean
public BaseClass childClass() {
return new ChildClass(new CustomParam(5));
}
}

How to enable #ConditionalOnProperty in spring-boot on runtime changeable property

I have two class which depends on config variable:
#Component
#ConditionalOnProperty("config.db")
public class DatabaseTokenStore implements TokenStore {
}
#Component
#ConditionalOnMissingBean(DatabaseTokenStore.class)
public class SimpleTokenStore implements TokenStore {
}
so when db is true then DatabaseTokenStore class is autowired when false then SimpleTokenStore is autowired. Problem is that I can change this property in runtime with CRaSH. Then this mechanic will not work. Is there some way how to change implement of interface in runtime ?
Initialize both TokenStores on startup. And create a resolver to inject into classes where you need to work with them. Like so:
#Component
public class HelloStoreResolver {
#Autowired
private HelloStore oneHelloStore;
#Autowired
private HelloStore twoHelloStore;
public HelloStore get() {
if (condition) {
return oneHelloStore;
} else {
return twoHelloStore;
}
}
}
#Component
public class HelloController {
#Autowired
private HelloStoreResolver helloResolver;
//annotations omitted
public String sayHello() {
return helloResolver.get().hello();
}
}

Changing a class annotated #Component to #Bean annotated method

I have a class that is annotated #Component that was then #Autowired into another class. However, I need to remove this #Component annotation and instead, create it with an #Bean annotated method in the class where its was previously autowired.
Where previously the classes looked like:
#Component
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Autowired
private IMyClass myClass;
private void methodUsingMyClass()
{
myClass.doStuff();
}
}
So now I have removed the #Component annotation and written a #Bean annotated method like this:
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Bean
public IMyClass getMyClass()
{
return new MyClass();
}
....
}
My question is around replacing the previous call of myClass.doStuff() to use the new bean. Do I now pass in a parameter of type MyClass to the private method:
private void methodUsingMyClass(final MyClass myClass)
{
myClass.doStuff();
}
... or do I call this method directly (doesn't seem the correct way to me):
private void methodUsingMyClass()
{
getMyClass().doStuff();
}
... or are neither of these correct?
I think you misunderstand the #Bean annotation. It can be used to create a Bean. So basically spring will scan all classes, will find your #Bean and create a Bean, not more. You can now use this bean, like if you would use one created with <bean></bean>. To actually use the bean you need to either get it from ApplicationContext or #Autowire it. Of course you can still use that function like any other function in your code, to create a new instance of that object, but that would contradict to what you want to achieve with beans
Using Annotations that solutions
public class MyClass implements IMyClass{
private OtherClassInjection otherClassInjection;
private OtherClassInjection2 otherClassInjection2;
MyClass(OtherClassInjection otherClassInjection, OtherClassInjection2 otherClassInjection2){
this.otherClassInjection=otherClassInjection;
this.otherClassInjection2=otherClassInjection2;
}
public void useObject(){
otherClassInjection.user();
}
}
#Bean(name = "myClass")
#Autowired
#Scope("prototype") //Define scope as needed
public MyClass getMyClass(#Qualifier("otherClassInjection") OtherClassInjection otherClassInjection,
OtherClassInjection2 otherClassInjection2) throws Exception
{
return new MyClass(otherClassInjection, otherClassInjection2);
}
that logical, it's work injection #Autowired when create a Bean if context are know that bean, that you will to want inject.
I'm use that way.

How to Autowire a 1-arg Object Constructor with Previously Autowired Object?

Given the following MyConstructorClass:
#Component
public class MyConstructorClass{
MyObj var;
public MyConstructorClass( MyObj constrArg ){
this.var = var;
}
...
}
How can I autowire a field that requires a constructor argument from a previously #Autowired field? Below is an example.
Note - this question, I believe, is similar to this one, except that my constructor argument is not a String. This code sample is slightly modified from this question.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj; // no arguments to constructor
#Autowired
MyConstructorClass myConstructorClass; // requires `customObj` as an argument
....
}
How can I modify MyBeanService to properly construct myConstructorClass with customObj?
You just need to annotated the constructor of MyConstructorClass with #Autowired:
#Component
public class MyConstructorClass {
final private CustomObject customObj;
#Autowired
public MyConstructorClass(CustomObject customObj) {
this.customObj = customObj;
}
}
Another alternative, (without adding the #Autowired constructor to MyConstructorClass) is to use a #Configuration bean:
#Configuration
public class MyConfiguration {
#Bean
public CustomObject customObj() {
return customObj;
}
#Bean
public MyConstructorClass myConstructorClass() {
return new MyConstructorClass(customObj());
}
#Bean
public MyBeanService myBeanService() {
return new MyBeanService();
}
}
you can use the <constructor-arg> in your servlet
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg>
<bean class="package.CustomObject"/>
</constructor-arg>
</bean>
If this is the only place you need to use that class could use #PostConstruct to instantiate itself. I think there is a better solution, but this is off the top of my head.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj;
MyConstructorClass myConstructorClass;
#PostConstruct
public void construct()
{
myConstructorClass = new MyConstructorClass(customObj);
}
}
In the constructor, you can refer to other beans defined in Spring.
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg index="0" ref="customObj"/>
</bean>

Spring DI with Constructor

I have the following code:
#Component
public class MainBean {
#Autowired
private MyTask myTask
#Autowired
private TaskScheduler taskScheduler
public void start() {
String str = "Print something to console";
//somehow call constructor and pass str argument??
taskScheduler.execute(myTask);
}
}
#Component
public class MyTask implements Runnable {
private String str;
#Autowired
public MyTask(String str) {
this.str = str;
}
#Override
public void run() {
System.out.println(str);
}
}
I want to call MyTask and pass the str argument to the constructor. How can I do this? I cant find any good examples anywhere.
If I understand correctly what you are trying to do, a good solution would be the following:
#Component
public class MainBean {
#Autowired
private MyTaskFactory myTaskFactory
#Autowired
private TaskScheduler taskScheduler
public void start() {
String str = "Print something to console";
taskScheduler.execute(myTaskFactory.getTask(str));
}
}
public class MyTaskFactory {
public MyTask getTask(String str) {
return new MyTask(str);
}
}
#Configuration
public class MyTaskFactoryConfig {
#Bean
public MyTaskFactory myTaskFactory() {
return new MyTaskFactory();
}
}
Note that MyTask will then be changed to:
public class MyTask implements Runnable {
private String str;
public MyTask(String str) {
this.str = str;
}
#Override
public void run() {
System.out.println(str);
}
}
As seen from annotations, you've configured MyTask to be Spring managed. Also, str property is Spring managed, it should be injected by Spring to MyTask.
So, whenever you need MyTask instance, you don't create it yourself.
You #Autowire wherever you need.
public class ClassThatNeedsMyTaskInstances{
#Autowired
MyTask myTask;
}
But beware that by default, MyTask will be a singleton, so you may want to change its scope to prototype.
But this may be a good case where you don't let Spring manage MyTasks lifecycle. Instead you manage it yourself by creating instances using new, or factory
The following examples are for injecting the string from and XML and a Java-based configuration:
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.xsd">
<bean id="MyTaskConstructor" class="java.lang.String">
<constructor-arg type="char[]" value="My value"></constructor-arg>
</bean>
<bean id="myTask" class="com.package.MyTask">
<constructor-arg ref="MyTaskConstructor"/>
</bean>
</beans>
Java-based
#Configuration
public class MyTaskConfig {
#Bean
public String getMyTaskConstructor() {
return "My value";
}
#Bean
public MyTask myTask() {
return new MyTask(getMyTaskConstructor());
}
}

Categories

Resources