Injecting property into bean - java

i am trying to decalre a spring bean on a xml (Mule config file), and i've created a bean like that:
<bean id="IsActiveFilter" class="com.TimeLineListener.IsActiveFilter">
<property name="isChatActive" value="${chatListener.isActive}"/>
</bean>
Now, my question is - how can i get tothe value of isChatActive from within the actual bean class? i mean, can i just create a variable (private int isChatActive) with the name isChatActive and it will get whatever value the placeholder gives it? i mean something like:
public class IsActiveFilter{
{
private int isChatActive;
}
Will that work? if not, how do i use it?
thanks in advance

Create a getter and setter and you are fine:
public class IsActiveFilter{
private int isChatActive;
public int getIsChatActive() {
return this.isChatActive;
}
public void setIsChatActive(int isChatActive) {
this.isChatActive = isChatActive;
}
}

public class IsActiveFilter {
private int chatActive;
public boolean isChatActive() {
return chatActive;
}
public void setChatActive(boolean chatActive) {
this.chatActive = chatActive;
}
}

Related

Spring autowire byName not working as expected

Spring autowire byName not working as expected.
public class SpellChecker {
public SpellChecker() {
System.out.println("Inside SpellChecker constructor." );
}
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
public class TextEditor {
private SpellChecker spellChecker1;
private String name;
public void setSpellChecker( SpellChecker spellChecker1 ){
this.spellChecker1 = spellChecker1;
}
public SpellChecker getSpellChecker() {
return spellChecker1;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void spellCheck() {
System.out.println(" TextEditor name is " +name);
spellChecker1.checkSpelling();
}
}
public class TextEditorMain {
public static void main(String args[]) throws InterruptedException{
ApplicationContext context = new
ClassPathXmlApplicationContext("Beans.xml");
TextEditor tEditor = (TextEditor) context.getBean("textEditor");
tEditor.spellCheck();
}
}
Spring beans configuration:
<bean id = "spellChecker1" class = "com.spring.beans.SpellChecker">
</bean>
<bean id = "textEditor" class = "com.spring.beans.TextEditor" autowire="byName">
<property name = "name" value = "text1"/>
</bean>
When I give spellChecker1 as bean id it is not working. Below are the console o/p,
Inside SpellChecker constructor.
TextEditor name is text1
Exception in thread "main" java.lang.NullPointerException
at com.spring.beans.TextEditor.spellCheck(TextEditor.java:26)
at com.spring.main.TextEditorMain.main(TextEditorMain.java:15)
Bean id and reference name both are same spellChecker1 but still not working. But the strange thing is if I change the bean id in xml from spellChecker1 to spellChecker the code is working and giving below o/p,
Inside SpellChecker constructor.
TextEditor name is text1
Inside checkSpelling.
So why dependency is not added when I am using spellChecker1 ?
It actually works as designed. Your property is named spellChecker not spellChecker1. You have a field named spellChecker1.
The name of the field is not the same as the name of a property. A name of the property is defined by the get and set methods available on a class. As you have a setSpellChecker (and the corresponding getter) there is a property named spellChecker.
All of this is written down in the JavaBeans Specification (which was written somewhere in 1998!)
Basically properties are named attributes associated with a bean that can be read or written by calling appropriate methods on the bean. Thus for example, a bean might have a foreground property that represents its foreground color. This property might be read by calling a Color getForeground() method and updated by calling a void setForeground(Color c) method.
Source the JavaBeans Specification.

Read application.properties from non-component class like pojo or singleton

I'm using spring boot & for properties I've placed application.properties inside src/main/resources
From #Controllers & #Services, I'm able to read properties, but from my model pojo & a singleton class, I'm not able to read the values.
My #SpringBootApplication is in com.vehicle & I've not overriden #ComponentScan, so I belive it should read all the underlying packages.
Below is code:
application.properties
vehicle.lift.maxWeight=10
vehicle.lift.error.overWeight=Overweight
vehicle.battery.default=5.0
vehicle.battery.critical.limit=15
vehicle.walk.distance.error=Not able to move
WalkServiceImpl.java (able to read from here)
package com.vehicle.prototype.service.impl;
#Service
public class WalkServiceImpl implements CapabilityService {
#Value("${vehicle.walk.distance.error}")
private String mDistanceError;
#Override
public void performTask(VehicleData vehicleData) {
double distance = vehicleData.getWalkingDistance();
double remainingBattery = vehicleData.getRemainingBattery();
if (remainingBattery < distance) {
vehicleData.setErrorMessage(mDistanceError);
System.out.println(mDistanceError);
} else {
vehicleData.setRemainingBattery(remainingBattery - distance);
}
VehicleUtil.checkBatteryStatus(vehicleData);
}
}
VehicleData.java (Pojo - not able read from here)
package com.vehicle.prototype.model;
public class VehicleData {
private double walkingDistance;
private double liftWeight;
#Value("${vehicle.battery.default}")
private double remainingBattery;
// setters & getters ....
}
VehicleUtil.java (Singleton - not able to read from here)
package com.vehicle.prototype.utils;
public class VehicleUtil {
private static VehicleUtil mInstance = null;
private static Object mLock = new Object();
#Value("${vehicle.battery.critical.limit}")
private static double mCriticalLimit;
#Value("${vehicle.battery.default}")
private static double mTotalPower;
#Value("${vehicle.battery.critical.warning}")
private static String powerWarning;
private VehicleUtil() {
// empty private constructor.
}
public static VehicleUtil getInstance() {
if (mInstance == null) {
synchronized (mLock) {
if (mInstance == null)
mInstance = new VehicleUtil();
}
}
return mInstance;
}
public static void checkBatteryStatus(VehicleData vehicleData) {
double criticalMark = (mCriticalLimit * 100.0f) / mTotalPower;
if (vehicleData.getRemainingBattery() < criticalMark) {
vehicleData.setBatteryCritical(Boolean.TRUE);
System.out.println(powerWarning);
} else {
vehicleData.setBatteryCritical(Boolean.FALSE);
}
}
}
Please let me know how to fix this.
Thank You
You need to inject the properties into a spring-managed bean.
What you can do, is to bundle the properties in a bean like this (see documentation)
#ConfigurationProperties(prefix="vehicle")
public class VehicleProperties {
#Value("${battery.critical.limit}")
private double mCriticalLimit;
#Value("${battery.default}")
private double mTotalPower;
#Value("${battery.critical.warning}")
private String powerWarning;
}
Then, inject the Vehicle Properties into your service and passe them to VehicleUtil:
public class WalkServiceImpl {
#Autowired
private VehicleProperties vehicleProperties;
#Override
public void performTask(VehicleData vehicleData) {
...
VehicleUtil.checkBatteryStatus(vehicleProperties, vehicleData);
}
}
Better yet, I would convert VehicleUtil into a managed-bean
#Component
public class VehicleUtil {
#Autowired
private VehicleProperties vehicleProperties;
}
VehicleData
I'm assuming VehicleData is some business object, passed from the client or that you create yourself, for which they are many instances (not just one singleton). In this case, it wouldn't make sense to convert VehicleData into a managed-bean, and its external dependencies could just be provided to it through its setters:
public class VehicleData {
private double walkingDistance;
private double liftWeight;
private double remainingBattery;
// setters & getters ....
}
Only Instances controlled by Spring are able to get property values injected.
As you have a Spring application you should not write own singleton logic instead of simply annotation VehicleUtil by #Component. This would also make any usages more testable as you can mock it in a test when the util instance is injected.
You cannot inject a value directly to the VehicleData pojo. The property value is mostly a constant during runtime so it can be a default only. You should set the value before exposing in a repo or service or leave it null and use the value instead of the non set property wherever it is used.

DeltaSpike custom ConfigSource with CDI

I am trying to define a custom DeltaSpike ConfigSource. The custom config source will have the highest priority and check the database for the config parameter.
I have a ConfigParameter entity, that simply has a key and a value.
#Entity
#Cacheable
public class ConfigParameter ... {
private String key;
private String value;
}
I have a #Dependent DAO that finds all config parameters.
What I am trying to do now, is define a custom ConfigSource, that is able to get the config parameter from the database. Therefore, I want to inject my DAO in the ConfigSource. So basically something like
#ApplicationScoped
public class DatabaseConfigSource implements ConfigSource {
#Inject
private ConfigParameterDao configParameterDao;
....
}
However, when registering the ConfigSource via META-INF/services/org.apache.deltaspike.core.spi.config.ConfigSource, the class will be instantiated and CDI will not work.
Is there any way to get CDI working in this case?
Thanks in advance, if you need any further information, please let me know.
The main problem is, that the ConfigSource gets instantiated very early on when the BeanManager is not available yet. Even the JNDI lookup does not work at that point in time. Thus, I need to delay the injection/lookup.
What I did now, is add a static boolean to my config source, that I set manually. We have a InitializerService that makes sure that the system is setup properly. At the end of the initialization process, I call allowInitialization() in order to tell the config source, that the bean is injectable now. Next time the ConfigSource is asked, it will be able to inject the bean using BeanProvider.injectFields.
public class DatabaseConfigSource implements ConfigSource {
private static boolean allowInit;
#Inject
private ConfigParameterProvider configParameterProvider;
#Override
public int getOrdinal() {
return 500;
}
#Override
public String getPropertyValue(String key) {
initIfNecessary();
if (configParameterProvider == null) {
return null;
}
return configParameterProvider.getProperty(key);
}
public static void allowInitialization() {
allowInit = true;
}
private void initIfNecessary() {
if (allowInit) {
BeanProvider.injectFields(this);
}
}
}
I have a request-scoped bean that holds all my config variables for type-safe access.
#RequestScoped
public class Configuration {
#Inject
#ConfigProperty(name = "myProperty")
private String myProperty;
#Inject
#ConfigProperty(name = "myProperty2")
private String myProperty2;
....
}
When injecting the Configuration class in a different bean, each ConfigProperty will be resolved. Since my custom DatabaseConfigSource has the highest ordinal (500), it will be used for property resolution first. If the property is not found, it will delegate the resolution to the next ConfigSource.
For each ConfigProperty the getPropertyValue function from the DatabaseConfigSource is called. Since I do not want to retreive the parameters from the database for each config property, I moved the config property resolution to a request-scoped bean.
#RequestScoped
public class ConfigParameterProvider {
#Inject
private ConfigParameterDao configParameterDao;
private Map<String, String> configParameters = new HashMap<>();
#PostConstruct
public void init() {
List<ConfigParameter> configParams = configParameterDao.findAll();
configParameters = configParams.stream()
.collect(toMap(ConfigParameter::getId, ConfigParameter::getValue));
}
public String getProperty(String key) {
return configParameters.get(key);
}
}
I could sure change the request-scoped ConfigParameterProvider to ApplicationScoped. However, we have a multi-tenant setup and the parameters need to be resolved per request.
As you can see, this is a bit hacky, because we need to explicitly tell the ConfigSource, when it is allowed to be instantiated properly (inject the bean).
I would prefer a standarized solution from DeltaSpike for using CDI in a ConfigSource. If you have any idea on how to properly realise this, please let me know.
Even though this post has been answered already I'd like to suggest another possible solution for this problem.
I managed to load properties from my db service by creating an #Signleton #Startup EJB which extends the org.apache.deltaspike.core.impl.config.BaseConfigSource and injects my DAO as delegate which I then registered into the org.apache.deltaspike.core.api.config.ConfigResolver.
#Startup
#Singleton
public class DatabaseConfigSourceBean extends BaseConfigSource {
private static final Logger logger = LoggerFactory.getLogger(DatabaseConfigSourceBean.class);
private #Inject PropertyService delegateService;
#PostConstruct
public void onStartup() {
ConfigResolver.addConfigSources(Collections.singletonList(this));
logger.info("Registered the DatabaseConfigSourceBean in the ConfigSourceProvider ...");
}
#Override
public Map<String, String> getProperties() {
return delegateService.getProperties();
}
#Override
public String getPropertyValue(String key) {
return delegateService.getPropertyValue(key);
}
#Override
public String getConfigName() {
return DatabaseConfigSourceBean.class.getSimpleName();
}
#Override
public boolean isScannable() {
return true;
}
}
I know that creating an EJB for this purpose basically produces a way too big overhead, but I think it's a bit of a cleaner solution instead of handling this problem by some marker booleans with static accessors ...
DS is using the java se spi mechanism for this which is not CD'Injectable'. One solution would be to use the BeanProvider to get hold of your DatabaseConfigSource and delegate operations to it.

Converting configuration properties to enum values

I have a configuration file which contains this line:
login.mode=PASSWORD
and an enum
public enum LoginMode {
PASSWORD, NOT_PASSWORD, OTHER }
and a spring bean
<bean id="environment" class="a.b.c.Environment" init-method="init">
<property name="loginMode" value="${login.mode}"/>
</bean>
and of course a bean class
public class Environment {
private LoginMode loginMode;
public LoginMode getLoginMode() {
return loginMode;
}
public void setLoginMode(LoginMode loginMode) {
this.loginMode = loginMode;
}
}
How can i convert the property of the configuration file (which is a String) into the corresponding enum value of LoginMode?
EDIT: i know how to get the enum value of a string input, but the issue is another one:
If i try this:
public class Environment {
private LoginMode loginMode;
public LoginMode getLoginMode() {
return loginMode;
}
public void setLoginMode(String loginMode) {
this.loginMode = LoginMode.valueOf(loginMode);
}
}
spring is complaining about getter and setter not having the same input and output type.
Bean property 'loginMode' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
Spring automatically converts input Strings to the corresponding valueOf of the desired enum.
You can do that by
LoginMode.valueOf("someString");
LoginMode.valueOf(valueOfProperty);
EDIT:
Try using converter
http://docs.spring.io/spring/docs/3.0.0.RC2/reference/html/ch05s05.html
http://forum.spring.io/forum/spring-projects/web/83191-custom-enum-string-converters
EDIT2:
also check this:
How assign bean's property an Enum value in Spring config file?

Invalid property exception in spring

I am using spring in my application , When i am loading the springApplicationContext to get the beans i am getting the errors
Caused by:
org.springframework.beans.InvalidPropertyException:
Invalid property "abc"
Even though there is a property abc and the setter for that property in the bean.
This is a weird error i know , but i can't figure out where is the problem.
Any pointers will be helpful.
Thanks!
Pratik
Ensure that the property has both a public setter and getter. In case of an AnyObject property it should look like:
private AnyObject abc;
public AnyObject getAbc() { return abc; }
public void setAbc(AnyObject abc) { this.abc = abc; }
There is however one special case: in case of a boolean property it should look like:
private boolean abc;
public boolean isAbc() { return abc; }
public void setAbc(boolean abc) { this.abc = abc; }
Note the is prefix instead of get.
I remeber the similar question at Spring forums. It was found out that there was a setter signature like
public class MyClass {
private Aggregated field;
public MyClass setField(Aggregated field) {
this.field = field;
}
}
I.e. the setter's return type was not void.
Anyway, Spring uses standard Instrospector for processing class properties. Try it with your class and check if target property is found.

Categories