Spring My-batis MapperScannerConfigurer not resolving dat source place holder values - spring

After adding MapperScannerConfigurer bean configuration to the configuration xml to autowire my-batis mappers, getting below datasource bean creation error for placeholder issue. looks like spring unable to resolve the dynamic data source properties from property file. Configuration has PropertySourcesPlaceholderConfigurer defination as well to retrieve the datasource properties(min pool size and max pool size ) from class path file. even though having PropertySourcesPlaceholderConfigurer bean configuration, Integration test failing with below error. Basically it is unable to resolve dynamic properties. Any help is much appreciated..
This is just spring and my-batis based project and I there is no spring boot.
Spring version 5.3
my-batis-spring 2.0.6
java.lang.NumberFormatException: For input string: "${datasource.minpoolsize}"
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<bean id="appProperties"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>
classpath:configs/application.yaml
</value>
</list>
</property>
</bean>

Instead of configuring MapperScannerConfigurer in the xml, I used #MapperScan on
Spring configuration bean which resolved the issue.

Related

Default value for spring #Value annotation

I have a property annotated with #Value, normally populated from context.xml (jndi/tomcat)
#Value("${some.property}")
private String property
This works fine, but we have installations of our software, where that property shouldn't be configured.
However, if the property is missing, I get a javax.naming.NameNotFoundException: Name [some.property] is not bound in this Context. Unable to find [some.property]., which is logical.
I tried fixing this, by adding a default value this way:
#Value("${some.property:some_property_not_configured}")
private String property
However, I still get the same error.
Any ideas how to prevent/fix this?
I would like to use this in a Spring 3.2.x and a Spring 4+ environment.
The annotation #Value is available from Spring 3+
UPDATE:
The problem was not with the #Value annotation, but in app-config.xml
<entry key="some.property">
<jee:jndi-lookup jndi-name="java:comp/env/some.property" />
</entry>
This caused the error at startup time!
However, if I add default-value="something" here, it still fails with the same error
I solved this by defining a default value in the property-placeholder AND in the #value annotation:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<bean class="java.util.Properties">
<constructor-arg>
<map>
<entry key="some.property">
<jee:jndi-lookup jndi-name="java:comp/env/some.property" default-value="not_configured" />
</entry>
</map>
</constructor-arg>
</bean>
</property>
</bean>
and:
#Value(value = "${some.property:not_configured}")
private String property;

How to configure flushMode property of OpenSessionInViewInterceptor of spring 3.1.4

As I am planning to update from "hibernate3" to "hibernate4" & "spring 3.0.5" to "spring 3.1.4".
I have configured OpenSessionInViewInterceptor in spring 3.0.5 so want to configure same in 3.1.4.
But I am not able to configure flushMode in OpenSessionInViewInterceptor of Spring 3.1.4;
My Previous setting for spring 3.0.5 was:
<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="flushMode">
<bean
id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_NEVER"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
Now tried to configure same for spring 3.1.4 as below:
<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="flushMode">
<bean
id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_NEVER"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
</property>
</bean>
then it throws below exception:
org.springframework.beans.NotWritablePropertyException: Invalid property 'flushMode' of bean class [org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor]: Bean property 'flushMode' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
And there is no similar class found in alternate to org.springframework.orm.hibernate3.HibernateAccessor in spring 3.1.4
So my question is how to set flushMode property of OpenSessionInViewInterceptor of spring 3.1.4 ?
It looks like a mess, with unbound links to property accessors. I'd guess that a copy-paste job was done without much thinking about cleaning things up given the different inheritance hierarchies. I hate it when that happens…
Can you use the Hibernate 3 version instead? Yes, it really does appear to be there; here's the link: org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
Longer term, look more carefully whether the Hibernate 4 code does what you want without specifying the flag at all. Unfortunately, you'll have to ignore the documentation (at least for now) and study the source itself.

Loading properties from a file AND system properties using Spring

Searched through some other posts but could not find exactly what I needed, but I would guess this is an easy question..
So I have a property file called myprops.properties
myprops.localProp1=localProp1
myprops.localProp2=localProp2
myprops.systemProp=${systemPropertyName}
Basically, in this property file I want to use the values as is for localProp1 and locapProp2 but for systemProp, I would like to load the system property. Let's assume that the system property is always set.
My spring config xml looks like this...
<bean id="myprops" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<qualifer value="myprops" />
<property name="singleton" value="true"/>
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list><value>classpath:myprops.properties</value></list>
</property>
</bean>
I use the qualifier have this bean autowired and use the qualifier string "myprops" to access it in another class. All the expected values are there except the myprops.systemProp, it still = ${systemPropertyName}.
How would I get this property to be resolved with the actual system property?
I tried the following in my spring config:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="myprops" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
This didn't seem to help..
Any ideas? I'm hoping this is an easy one and I am just misunderstanding a common concept in property configuration.
Note: I had to manually type all the code couldn't copy/paste so please excuse typos.
Thanks.

Spring PropertiesFactoryBean that automatically exposes a PropertyPlaceholderConfigurer's property

Ideally I'd like to do this from code:
#Value("#{aPropertiesFactoryBean.aProperty}")
private String aProperty;
Based on a spring configuration where I set up a PropertyPlaceholderConfigurer and a PropertiesFactoryBean, and just pass the configurer bean as a ref to the bean, and everything that the configurer generates is exposed as a property of the factory bean.
There is a hack to just redefine every property from the Configurer like:
<bean id="aPropertiesFactoryBean"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="properties">
<props>
<prop key="aProperty">${aProperty}</prop>
</props>
</property>
</bean>
And then every time you add a property to the Configurer, you have to re-expose it with the FactoryBean. And the punchline is, I want all the management features of the configurer, and also be able to reference the same batch of properties from both the spring xml files, and #Value annotations.
So the two questions:
Is there something like this out of the box?
It looks like it would be simple to override PropertiesFactoryBean and give it a property for the PlaceholderConfigurer, but the code to actually access the properties would have to involve unwelding the hood through reflection and digging into Spring's internal PropertiesLoaderSupport class. Is there a less hacky way to do this?
Note, I'm not looking for something that can just quickly get me on my way, the above hack with PropertiesFactoryBean suffices for now. I'm looking to either find or make a reusable component that I can use to easily manage injectable properties for projects down the road.
I was just thinking about this backwards. This config does exactly what I want, being able to have properties defined in the xml config, overridable from a properties file, and available as both placeholder properties and injectable values.
<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-3.0.xsd">
<!--
One-stop shopping for properties here.
Available as injected values and elsewhere in the spring config.
-->
<bean id="injectableProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="properties">
<props>
<prop key="prop1">value1</prop>
<prop key="prop2">value2</prop>
</props>
</property>
<!-- Allow foo.conf to override default properties -->
<property name="location" value="file:/etc/foo/foo.conf" />
</bean>
<!-- Expose the properties so other parts of the spring config can use them -->
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="properties" ref="injectableProperties"/>
</bean>
</beans>
Maybe I'm misunderstanding the situation, but you can inject properties without having to define a PropertiesFactoryBean by using the syntax:
#Value("${my.property}") String myProperty;

Configuring Datasource in Spring 3.0

Hello guys I have configured a connection pool and JNDI resource in glassfish 2.1. I can get the Datasource via lookup method in my projects and everything works good. However I decided to try Spring framework and to use my existing connection pool.
In the Spring context file I have the following:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/name" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="dao" class="com.mycompany.mavenproject3.Dao">
<property name="simpleJdbcTemplate" ref="jdbcTemplate"/>
</bean>
When I deploy the project I get:
java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required]
Is there anything else I have to configure in that file or in any other file in order to get the Datasource?
Presumably, com.mycompany.mavenproject3.Dao extends JdbcDaoSupport, but you're setting a property named simpleJdbcTemplate on it, leading me to believe that you've defined your own property to hold the template since that doesn't exist on Spring's implementation. It's therefore complaining at you because you're required to set either the dataSource property or the jdbcTemplate property of the JdbcDaoSupport object before using it, exactly like it's telling you. Change <property name="simpleJdbcTemplate"... to <property name="jdbcTemplate"....
If your DAO doesn't extend JdbcDaoSupport, then find what does and remove it or set its properties appropriately.
You can also call your datasource directly in your dao bean, don't need to do an another bean for jdbcTemplate. So your context file become something like this:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/name" />
<bean id="dao" class="com.mycompany.mavenproject3.Dao">
<property name="dataSource" ref="dataSource"/>
</bean>
After you just have to extends JdbcDaoSupport spring class (in which contain the getter and setter of datasource) on your Dao class.

Resources