I'm using jndi to perform a database lookup :
<jee:jndi-lookup id="myDataSource" jndi-name="jdbc/mydb"
resource-ref="true" expected-type="javax.sql.DataSource" />
In a spring context file I invoke the constructor using :
<bean id="myController " class="com.MyController">
<constructor-arg index="0" ref="myDataSource" />
</bean>
I no longer want to expose "myDataSource" via a jndi lookup, so a I create a mock object which is of same type as "javax.sql.DataSource" and use it instead as a constructor parameter :
<bean id="myMockDataSource" class="com.mock.MyMockDataSourceConnection">
</bean>
<bean id="myController" class="com.MyController">
<constructor-arg index="0" ref="myMockDataSource" />
</bean>
The mock object just returns a dummy connection.
Is this the correct way so as to longer use jndi lookup when want to use a mock object instead ?
You may want to look at Spring's SimpleNamingContextBuilder class, which is useful for building JNDI tree without needing a Java EE container.
class JndiMock
{
public void init()
{
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind( "jdbc/mydb" , new YourDummyConnectionClass() );
builder.activate();
}
...
}
(This is from memory, but should give you the idea). You can instantiate it as a singleton right in your application context XML descriptor using the init-method attribute:
<bean id="jndimock" class="your.package.JndiMock" init-method="init" />
and make it is created before the jee:jndi-lookup.
Cheers,
Related
Java
public class MyObject{}
public class MyFactory{
private Optional<MyObject> myproperty;
public Optional<MyObject> getMyproperty{...}
public void setMyproperty{...}
}
Spring config xml (doesn't work)
<bean id="myproperty" class="java.util.Optional">
<constructor-arg>
<value>com.MyObject</value>
</constructor-arg>
</bean>
<bean id="myfactory" class="com.Myfactory">
<property name="myproperty" ref="myproperty" />
</bean>
Does spring support generics beans?
The reason for using Optional is it provide some useful features such as checking value if null. You can complete checking and further action in one line of code.
getMyproperty().ifPresent(id -> call.setId(id));
Seems the problem have nothing to do with generics.
You simply need to properly tell Spring to create the bean using a factory method, as Optional can only be created though factory methods. Something like:
<bean id="myproperty" class="java.util.Optional" factory-method="of">
<constructor-arg type="java.lang.Object" value="com.MyObject" />
</bean>
for which it is supposed to mean creating the myproperty bean by Optional.of(com.MyObject.class) (Change the factory-method to ofNullable if that's the one you want to use)
Another option is to use SpEL (Spring Expression Language):
<bean id="mybean" ...>
<property name="optProp" value="#{ T(java.util.Optional).of( #wrapme) }"/>
</bean>
Where "wrapme" is the name of a bean defined elsewhere that you want to wrap in java.util.Optional.
I need my Spring application context to include a bean that is a (Java 7) Path object, with a fixed (known) path-name. What XML bean definition should I use?
This kind of bean has some complications:
Path is an interface, and Path objects should be created using the Paths.get(String...) static factory method.
The static factory method also has an overloaded variant, Paths.get(URI).
As the object is-a Path, the class of the bean should be Path:
<bean name="myPath" class="java.nio.file.Path"/>
I need to indicate the static factory method to use, which would seem to require a factory-method attribute. But the factory method belongs to the java.nio.file.Paths class rather than the java.nio.file.Path class, so I assume the following would not work:
<bean name="myPath" class="java.nio.file.Path"
factory-method="java.nio.file.Paths.get"/>
Lastly, I need to give the arguments for the factory method. How do I do that? Using nested constructor-arg (sic) elements? So, something like this?
<bean name="myPath" class="java.nio.file.Path"
factory-method="java.nio.file.Paths.get">
<constructor-arg value="/my/path/name"/>
</bean>
But that does not work: Springs throws a BeanCreationException, complaining of "No matching factory method found: factory method 'java.nio.file.Paths.get()'."
After some experimenting with pingw33n's answer, I found this worked:
<bean id="myPath" class="java.nio.file.Paths" factory-method="get">
<constructor-arg value="/my/path" />
<constructor-arg><array /></constructor-arg>
</bean>
Note:
Give the name of the factory class, rather than the object class, as the value of the class attribute.
Give an extra empty array constructor argument, to force selection of the correct overload of the factory method. This avoids having to go the round-about route of instead constructing a file URI.
Well , i had the same problem as you , and my solution was ...
<bean id="ThreadRunnerConfigFile" class="java.nio.file.Paths" factory-method="get" c:_0="ThreadRunnerConfigFileStr" />
Dont forget to include the c namespace on your .xml configuration file
Something like below should help.
<bean id="myPath" class="java.nio.file.Paths" factory-method="get">
<constructor-arg type="java.lang.String" value="/my/path/name" />
</bean>
Try this:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod"><value>java.nio.file.Paths.get</value></property>
<property name="arguments">
<array>
<value>/my/path/name</value>
<array/>
</array>
</property>
</bean>
I am new to the Spring framework and can't find a way to achieve the following:
I am using a class whose attributes are all private and there are no setters (the intended way to use objects of that class is to set attributes once with a constructor) - I will refer to it as Preferences. I also have a few classes that each has the same instance of Preferences as an attribute. Preferences is intended to contain certain properties, among which some can only be resolved at runtime (e.g. provided by the user).
In my .xml file I would write something along the lines of:
<bean id="preferenes" class="Preferences" scope="singleton">
<constructor-arg index="0" value="defaultAttrOne" />
<constructor-arg index="1" value="defaultAttrTwo" />
<constructor-arg index="2" value="defaultAttrThree" />
</bean>
<bean id="someOtherBean" class="SomeOtherClass" scope="singleton">
<constructor-arg index="0" ref="preferences" />
</bean>
That is, I could provide default values and replace some of them with custom ones at runtime. As I cannot modify attributes of an existing instance of Preferences, I would have to construct a new object and somehow make the instance of SomeOtherClass point to that new object (is this possible through the bean mechanism?).
Rather, I'd pass the desired runtime constructor arguments to the preferences bean before instantiating any of the beans (those arguments will be known before the first call to the ApplicationContext's constructor). I know there is a flavour of the getBean() method that takes varargs as initialization parameters, though it only applies to prototype beans. In this case I want to initialize Preferenes once and have all helper classes refer to that single instance.
Thank you for any hints.
This is pretty much what Spring does for you by default so there is nothing special you'll have to do: if you create that singleton bean reference (called preferences), you'll be able to inject it to any other bean as you would expect.
Regarding your attributes with default values, there's several ways to achieve that:
Regular XML config
You can keep a purely XML-based configuration if you want and configure a PropertyPlaceholderConfigurer with default values. Something like:
<bean class="org.s.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="prefrences.properties"/>
</bean>
<bean id="preferenes" class="Preferences" scope="singleton">
<constructor-arg index="0" value="$[preferences.one:12]" />
<constructor-arg index="1" value="$[preferences.two:AUTO]" />
<constructor-arg index="2" value="$[preferences.three:false]" />
</bean>
And have a prefrences.properties at the root of the classpath hold the specific values if you don't want the default
prefrences.three=true
FactoryBean
As you're already using XML, you can go with a FactoryBean that would create the Preferences instance, something like
<bean id="preferences" class="org.myproject.PreferencesFactoryBean"/>
in the code of the factory you could use whatever mechanism you want to retrieve the non default values for your configuration, including injecting custom properties.
Java config
You can also go the java config way but as you're a beginner this may be a bit of a change. However, java config is really powerful and flexible so you may want to give it a try.
#Configuration
#PropertySource("classpath:preferences.properties")
public class AppConfig {
#Value("${preferences.one}")
private int preferenceOne = 12;
#Value("${preferences.two}")
private MyEnum preferenceTwo = MyEnum.AUTO;
#Value("${preferences.three}")
private boolean preferenceThree;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public Preferences preferences() {
return new Preferences(preferenceOne, preferenceTwo, preferenceThree);
}
}
I have a problem with Spring: I need to reuse the same instance of bean twice, but not making it singleton.
Here is a brief ApplicationContext:
<bean class="a.b.c.Provider" id="defaultProvider" scope="prototype">
<constructor-arg ref="lifecycle" />
<constructor-arg ref="propertySetter" />
</bean>
<bean name="lifecycle" class="a.b.c.Lifecycle" scope="prototype">
<constructor-arg ref="someParam" />
... and more args
</bean>
<bean id="propertySetter" class="a.b.c.PropertySetter" scope="prototype">
<constructor-arg ref="lifecycle" />
</bean>
So, I need to have fully initialized Provider with Lifecycle and PropertySetter inside,
and this PropertySetter must contain reference to same Lifecycle, as the Provider have.
When I define lifecycle and propertySetter as singletons, it causes big problems, because
if I create more than one Provider, all instances of Provider class shares same lifecycle
and property setter, and it's breaking application logic.
When I try to define all beans as prototypes, Lifecycles in Provider and in PropertySetter are not the same => exceptions again.
I have one solution: to pass to Provider only Lifecycle and create PropertySetter inside Provider java constructor (by extending Provider).
It is working well, but only in my local environment. In production code I can't extend 3pty Provider class, so I can't use this solution.
Please advise me, what most appropriate to do in this situation?
You don't need to extend Provider. Just create your own ProviderFactory that will take reference to lifecycle and will create PropertySetter and then Provider:
public class ProviderFactory {
public static create(Lifecycle lc) {
return new Provider(lc, new PropertySetter(lc));
}
}
Here is Spring declaration:
<bean id="defaultProvider" scope="prototype"
class="a.b.c.ProviderFactory" factory-method="create">
<constructor-arg ref="lifecycle" />
</bean>
I have three apps in a Spring 2.5 managed project that share some code and differ in details.
Each application has a property (java.lang.String) which is used before the application context is built.
Building the app context takes some time and cannot happen first. As such, it's defined in each individual application. This property is duplicated in the context definition since it is also needed there. Can I get rid of that duplication?
Is it possible to inject that property into my application context?
Have a look at PropertyPlaceholderConfigurer.
The Spring documentation talks about it here.
<bean id="myPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:my-property-file.properties"/>
<property name="placeholderPrefix" value="$myPrefix{"/>
</bean>
<bean id="myClassWhichUsesTheProperties" class="com.class.Name">
<property name="propertyName" value="$myPrefix{my.property.from.the.file}"/>
</bean>
You then have reference to that String to anywhere you'd like in your application context, constructor-arg, property etc.
With spring 3.0 you have the #Value("${property}"). It uses the defined PropertyPlaceholderConfigurer beans.
In spring 2.5 you can again use the PropertyPlaceholderConfigurer and then define a bean of type java.lang.String which you can then autowire:
<bean id="yourProperty" class="java.lang.String">
<constructor-arg value="${property}" />
</bean>
#Autowired
#Qualifier("yourProperty")
private String property;
If you don't want to deal with external properties,you could define some common bean
<bean id="parent" class="my.class.Name"/>
then initialize it somehow, and put into common spring xml file, lets say common.xml. After that, you can make this context as a parent for each or your apps - in your child context xml file:
<import resource="common.xml"/>
and then you can inject properties of your parent into the beans you're interested in:
<bean ...
<property name="myProperty" value="#{parent.commonProperty}"/>
...
</bean>