Default value for spring #Value annotation - spring

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;

Related

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

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.

Spring Framework 4.1 ignores custom Object Mapper in ContentNegotiation

I'm trying to upgrade to Spring 4.1.5.
I have a custom Object mapper defined like so
<bean id="apiObjectMapper" class="my.company.ApiObjectMapper" />
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="apiObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
The object mapper itself looks like this:
public class ApiObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
public ApiObjectMapper() {
JaxbAnnotationModule module = new JaxbAnnotationModule();
module.setPriority(Priority.SECONDARY);
registerModule(module);
setSerializationInclusion(JsonInclude.Include.NON_NULL);
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
}
The issue happens during content negotiation it seems
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorParameter" value="true" />
<property name="defaultContentType" value="text/xml" />
<property name="mediaTypes" >
<value>
json=application/json
xml=text/xml
</value>
</property>
</bean>
After upgrading, the object mapper is simply ignored. No Jaxb annotations are taken into account, NULLs appear.
Spring 4.0.9 works fine.
I tried Java Configuration with the same result.
Also tried configuring the new Jackson2ObjectMapperFactoryBean directly, but couldn't get the original behavior to happen either.
E.g.: Original output for an endpoint like "list.xml"
<result>
<typeB>
<itemA>...</itemA>
<itemB>...</itemB>
</typeB>
</result>
Now outputs (typeA is empty/null):
<result>
<typeA />
<typeB>
<itemA>...</itemA>
<itemB>...</itemB>
</typeB>
</result>
Any ideas?
I believe I found the culprit and fix for this issue.
When the content negotiation determines that the response should be serialized in JSON then org.springframework.http.converter.json.MappingJackson2HttpMessageConverter is used. However, if the response should be serialized in XML then org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter is used instead. Different message converter that will use a default object mapper if none is provided.
What I had to change was
public class ApiObjectMapper extends XmlMapper { // XmlMapper extends ObjectMapper
// same logic
}
and
<bean id="apiObjectMapper" class="my.company.ApiObjectMapper" />
<mvc:annotation-driven content-negotiation- manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="apiObjectMapper"/>
</bean>
<!-- Added this bean configuration for XML serialization -->
<bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
<property name="objectMapper" ref="apiObjectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
I have yet to find what changed in Spring Framework or Jackson to make this happen although my money is n the separation of Jackson XML handling into a different library (I'll update this answer once I do).
Hope it helps.
Leaving some more information for future reference.
Based on this Spring blog post, starting with Spring 4.1, Jackson XML is used to generate XML instead of Jaxb if the former is found on the classpath. That's the main reason for the output to change, because the library generating it changed.
Now after some trial and error, getting Jackson XML to generate the same output as Jaxb is quite the endeavour. Instead you could just remove all references to Jackson XML (not Jackson itself) and everything should work the same way it worked before.

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.

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