I want to override keysForReload method in spring xml to return empty Iterator
<!-- MetricsMethodData Cache Store -->
<bean id="bean1"
class="com.ext.Myclass"
scope="singleton" lazy-init="true">
<lookup-method name="keysForReload" bean="metrics.keysForReload"/>
<!-- Not working as expecting Iterator while it returns ArrayList -->
<!-- can I use expression language somehow value="#{metrics.keysForReload.iterator()}" -->
</bean>
<bean id="metrics.keysForReload" class="java.util.ArrayList">
<constructor-arg>
<list value-type="java.lang.String">
</list>
</constructor-arg>
</bean>
this method I want to override in XML
MyClass has keysForReload method
public Iterator<String> keysForReload(){
return keys();
}
can I use Expression language to get Iterator from ArrayList? because I can not change the method.
Example: value="#{metrics.keysForReload.iterator()}"
You can invoke method in Spring expression language and assign to the value but in this case you have to define your bean metrics. Look at this example. SpEL example
Should something like this work for you?
#Bean("keysForReload")
public List<String> keysForReload() {
return Lists.newArrayList("val");
}
#Component
public class Myclass{
//your iterator here
#Value("#{keysForReload.iterator()}")
private Iterator<String> itr;
}
Related
I'm working with a special CacheConfig object that holds a field (with standard getter/setter methods), accessExpirationValue, which is of type java.time.Duration. (EDIT: actually, the field is of type Long (the number of seconds), but the getter and setter are of type Duration.)
I'm trying to wire this in Spring by setting this value as a number of seconds and using a ConversionServiceFactoryBean, like so:
Relevant beans in ApplicationContext.xml:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean" >
<property name="converters">
<set>
<bean
class="com.tjamesboone.example.config.SecondsToDurationConverter"/>
</set>
</property>
</bean>
<bean id="cacheConfig" class="com.tjamesboone.example.cache.CacheConfig" >
<property name="accessExpirationValue" value="0" />
</bean>
SecondsToDurationConverter:
package com.tjamesboone.example.cache;
import java.time.Duration;
import org.springframework.core.convert.converter.Converter;
public class SecondsToDurationConverter implements Converter<String, Duration> {
#Override
public Duration convert(String seconds) {
return Duration.ofSeconds(Long.parseLong(seconds));
}
}
Now, as I understand it, this is supposed to just work. When I pass in "0" for the value of accessExpirationValue, the fact that I've declared a conversionService bean that handles converting Strings to Durations means that is should set the value as a Duration of zero length.
But this would be to easy. And it is. Because when I test my application (using SpringJUnit4ClassRunner), I get this error, as if I'd never registered a Converter:
Bean property 'accessExpirationValue' is not writable or has an
invalid setter method. Does the parameter type of the setter match
the return type of the getter?
So my question is, What am I doing wrong? How do I get this to work they way I want?
For reference, this is the primary documentation I've been using:
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert-Spring-config
It specifically says,
In a Spring application, you typically configure a ConversionService instance per Spring container (or ApplicationContext). That ConversionService will be picked up by Spring and then used whenever a type conversion needs to be performed by the framework.
EDIT:
I should probably also post the relevant part of CacheConfig!
package com.tjamesboone.example.config;
import java.time.Duration;
public class CacheConfig {
private Long accessExpirationValue;
public Duration getAccessExpiration() {
return Duration.ofSeconds(accessExpirationValue.intValue);
}
public void setAccessExpiration() {
this.accessExpirationValue = expirationDuration.getSeconds();
}
}
Spring is going to try to match the properties in your bean with the getters and setters specified in your class.
Your getters/setters are currently getAccessExpiration() but should be getAccessExpirationValue() to match your bean property name="accessExpirationValue". Change one or the other and you should have it.
I am trying to reproduce an assignment in Java code with an equivalent bean definition in Spring. As far as I can tell, though, Spring only lets you assign values to the fields within an object (provided that the class defines the appropriate setter methods). Is there a way to simply capture a reference to an object using Spring beans?
Here's an example of how I would expect this to work:
<!-- Non-working example. -->
<bean id="string" class="java.lang.String">
<value>"I am a string."</value>
</bean>
I realize that in this particular case I could just use a <constructor-arg>, but I'm looking for more general solution, one that also works for classes that don't provide parameterized constructors.
String class is immutable. No property setter method is available in java.lang.String class. If you want to inject the property value you can use below:
<bean id="emp" class="com.org.emp">
<property name="name" value="Alex" />
</bean>
in above for the obj emp, its name property will be set as Alex.
The thing to use here is a factory-method, possibly in conjunction with a factory-bean. (Non-static functions must be instantiated by a bean of the appropriate type.) In my example problem, I wanted to capture the output of a function that returns a String. Let's say the function looks like this:
class StringReturner {
public String gimmeUhString(String inStr) {
return "Your string is: " + instr;
}
}
First I need to create a bean of type StringReturner.
<bean name="stringReturner" class="how.do.i.java.StringReturner" />
Then I instantiate my String bean by calling the desired function as a factory-method. You can even provide parameters to the factory method using <constructor-arg> elements:
<bean id="string" factory-bean="stringReturner" factory-method="gimmeUhString">
<constructor-arg>
<value>I am a string.</value>
</constructor-arg>
</bean>
This is (for my purposes) equivalent to saying:
StringReturner stringReturner = new StringReturner();
String string = stringReturner.gimmeUhString("I am a string.");
String is not a Bean, Bean is a Objet that his Class that have a Constructor with empty arguments and the properties are accessible by Getters Methods and are modifiable by Setters Methods
While working with Spring i am facing a strange issue.i have a class which takes a set as an input since the class is of underlying framework so i can not change it.
Here is its declaration
private Set evaluate;
public Set getEvaluate()
{
return evaluate;
}
public void setEvaluate(Set evaluate)
{
this.evaluate = evaluate;
}
i am spring file i have following entry
<bean id="customService"
class="com.platform.impl.DefaultFrameworkService"
scope="tenant" parent="abstractService">
<property name="evaluate">
<set>
<ref bean="bean1" />
<ref bean="bean2" />
<ref bean="bean3" />
<!-- inject new bean here. -->
<ref bean="bean4" />
</set>
</property>
here DefaultFrameworkService takes set as input. so all i am trying is to inject a new bean to the underlying service.
My problem is when spring read this file it convert this <set> entry of sprong.xml to LinkedHashSet and than try to set these values to private Set evaluate which ultimately throwing exception.
Though i can always override the DefaultFrameworkService and than can convert that LinkedHashSet to set but want to look for better way.
Exception i m getting is
Failed to convert property value of type 'java.util.LinkedHashSet' to required type 'java.util.Set' for property 'evaluate'
How can i make spring to pass value only as a set and not LinkedHashSet
Update
I was unable to set all these even so i played around a bit created a new customclass namely CustomDefaultFrameworkService with following implimentation
public class CustomDefaultFrameworkService extends DefaultFrameworkService
{
Logger log = Logger.getLogger(CustomDefaultFrameworkService.class);
#SuppressWarnings("unused")
private Set evaluate;
/**
* #param evaluateStrategies
* the evaluateStrategies to set
*/
#Override
public void setEvaluate(final Set evaluate)
{
log.info("Setting values to super class. Total values being injected are " + evaluateStrategies.size());
super.setEvaluate(evaluate);
}
}
and i am able to set map to super class.This thing has made me more confused.
Use the util namespace, it element set has a parameter set-class where you can specify the implementation you want to use.
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<util:set id="emails" set-class="my.custom.set.implmentation">
<value>pechorin#hero.org</value>
<value>raskolnikov#slums.org</value>
<value>stavrogin#gov.org</value>
<value>porfiry#gov.org</value>
</util:set>
</beans>
#See Spring Reference Chapter C.2.2.6
When calling Spring's "Validate" from Eclipse, I get a lot of errors when I want to get back an enum using Enum's implicit "valueOf" method.
For example:
<bean id="docFamily" class="...DocFamily" factory-method="valueOf">
<constructor-arg>
<value>LOGY</value>
</constructor-arg>
</bean>
has Eclipse telling me:
Non-static factory method 'valueOf'
with 1 arguments not found in factory
bean class ...
However as I understand it from the documentation:
BeanWrapperImpl supports JDK 1.5 enums
and old-style enum classes: String
values will be treated as enum value
names
So the above should work right? (btw is 'constructor-arg' the correct tag in that case, shouldn't it be some 'method-arg'?).
Why is Eclipse/Spring's "Validate" giving me that error message?
Enum.valueOf() has two arguments:
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
Therefore the desired definition may look like this:
<bean id="docFamily" class="java.lang.Enum" factory-method="valueOf">
<constructor-arg index = "0"><value>...DocFamily</value></constructor-arg>
<constructor-arg index = "1"><value>LOGY</value></constructor-arg>
</bean>
However, something like this can be a more elegant solution:
<util:constant id = "docFamily" static-field = "...DocFamily.LOGY" />
I just tried using it like this:
<bean id="docFamily" class="...DocFamily" factory-method="valueOf">
<constructor-arg type="java.lang.String" value="LOGY"/>
</bean>
and it worked like charm. Does it works for you?
I am New to Spring.I have this question which has been bothering me for a while now. Any help would be appreciated.
There is an Interface which calls a getter method.
interface MessageHandler{
public List GetMessageCheckerList();
}
There is another Interface called MessageChecker which has multiple Implementations.
Say MessageChecker1, TestChecker, etc. (lets assume 2 for now )
Now how do i define this in the configuration xml file.
I actually have the bean created ,
here is the rest of the code
<bean id="checkerList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="HL7Checker"/>
</list>
</constructor-arg>
</bean>
<bean id="HL7Checker" class="com.kahootz.messagereceiver.HL7CheckerImpl">
<property name="messageExecutor" ref="Executor"/>
</bean>
Please Advice
When I actually run the program using a main method, I get the handle of one of the beans, The HL7Checker should be passed in a list to the Bean with ID=messageHandler. But when i print out the list. It is empty.
Without using spring and only using getter and setter methods , i am able "set" a list and retrieve it using Get.
Almost all of your names do not conform to the Java Naming Conventions. That makes it hard for others to understand your code.
The <ref> tag expects the name of an object, not the name of a class. So you need to define a <bean id="testChecker" class="com.test.TestChecker" /> before you can reference it.
Don't use the package name com.Test. First, it should contain only lowercase letters. Second, you should be the owner of that name.