I'm wondering whether it is possible to evaluate properties in Spring's xml configuration files. I'm currently already injecting properties using a PropertyPlaceholderConfigurer. But what I want to achieve is to inject a value, if a certain property is true, and inject another value, if it is false.
For example I want to set the hibernate property hibernate.hbm2ddl.auto in my persistence.context.xml to validate only, if my custom property com.github.dpeger.jpa.validate is true. I know I can specify defaults like this:
<property name="jpaProperties">
<map>
<entry key="hibernate.hbm2ddl.auto" value="${com.github.dpeger.jpa.validate:none}" />
...
</map>
</property>
But is there a possibility to somehow evaluate a properties' value maybe like this:
<property name="jpaProperties">
<map>
<entry key="hibernate.hbm2ddl.auto" value="${com.github.dpeger.jpa.validate?validate:none}" />
...
</map>
</property>
First option:
You can use #{} EL expression and insert ${} placeholder right into this expression:
<property name="jpaProperties">
<map>
<entry key="hibernate.hbm2ddl.auto"
value="#{${com.github.dpeger.jpa.validate}?'validate':'none'}" />
...
</map>
</property>
Second option:
You can create separate property bean (note, that you have to define xmlns:util namespace and spring-util.xsd location):
<beans ...
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="...
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<util:properties id="props" location="classpath:appliction.properties"/>
...
</beans>
Now you can use this property bean in the EL expression by id:
<property name="jpaProperties">
<map>
<entry key="hibernate.hbm2ddl.auto"
value="#{props['com.github.dpeger.jpa.validate']?'validate':'none'}" />
...
</map>
</property>
Related
I'm trying to implement this Java data structure in Spring (which I am new to):
Map<String, List<String>>
I tried the below (and variants of it), but am getting the following exception:
Caused by: org.xml.sax.SAXParseException; lineNumber: XX; columnNumber: YY; cvc-complex-type.2.4.d: Invalid content was found starting with element 'util:list'. No child element is expected at this point.
Can someone tell me the mistake I am making? I need to be able to build out the above mentioned "Map" data structure with literal Keys (String) and List of values. I included twp complete sample "entries" (which are not working) just to show the fill-in pattern that I'm seeking to create.
<bean .... >
...
<property name="monitoredObjects">
<util:map map-class="java.util.HashMap">
<entry key="java.lang:type=GarbageCollector,name=ConcurrentMarkSweep">
<value>
<util:list>
<value>HeapMemoryUsage</value>
<value>NonHeapMemoryUsage</value>
</util:list>
</value>
</entry>
<entry key="java.lang:type=FOO,name=BAR">
<value>
<util:list>
<value>YADA-YADA</value>
<value>BLAH-BLAH</value>
</util:list>
</value>
</entry>
</util:map>
</property>
...
</bean>
Thank you! =:)
I tinkered some more and got it to work by removing "value" elements that enclosed the util:list elements. In other words, like this:
<bean .... >
...
<property name="monitoredObjects">
<util:map map-class="java.util.HashMap">
<entry key="java.lang:type=GarbageCollector,name=ConcurrentMarkSweep">
<util:list>
<value>HeapMemoryUsage</value>
<value>NonHeapMemoryUsage</value>
</util:list>
</entry>
<entry key="java.lang:type=FOO,name=BAR">
<util:list>
<value>YADA-YADA</value>
<value>BLAH-BLAH</value>
</util:list>
</entry>
</util:map>
</property>
...
</bean>
Thanks as always for looking!
Define a Map like this first inside your applicationContext.xml:
<util:list id="list1">
<value>foo#bar.com</value>
<value>foo1#bar.com</value>
</util:list>
<util:list id="list2">
<value>foo2#bar.com</value>
<value>foo3#bar.com</value>
</util:list>
<util:map id="emailMap" value-type="java.util.List">
<!-- Map between String key and List -->
<entry key="entry1" value-ref="list1" />
<entry key="entry2" value-ref="list2" />
...
</util:map>
Then use this Map in any bean of yours like this:
<bean id="myBean" class="com.sample.beans">
<property name="emailMap" ref="emailMap" />
</bean>
How to give value as xpath expression in spring map .
I am trying like below but is not working.
<bean id="test" class="com.test.testmap">
<property name="testmap">
<map>
<entry key="1" value="/emp/empid"/>
<entry key="2" value="/emp/empname"/>
</map>
</property>
</bean>
Regards,
Chaitu
Use Spring's MapFactoryBean to define the testmap property, including the Map implementation you wish to use (below is with a TreeMap).
<bean id="test" class="com.test.testmap">
<property name="testmap">
<bean class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="1">
<value>/emp/empid</value>
</entry>
<entry key="2">
<value>/emp/empname</value>
</entry>
</map>
</property>
<property name="targetMapClass" value="java.util.TreeMap"/>
</bean>
</property>
</bean>
In your java code, you can use it like this, assuming you have a getter for your testmap field, which you should:
com.test.testmap test = (com.test.testmap)applicationContext.getBean("test");
String xpath = (String)test.getTestmap().get("1");
You should also stick to Java conventions and rename your class com.test.TestMap for readability's sake.
I'm using Spring's ContentNegotiatingViewResolver along with VelocityViewResolver in a REST Spring MVC application which will support many different response types.
I would like Velocity to be able to handle multiple content types, but it seems like it only supports 1 (default text/html or supplied via the contentType property). In the config example below, I would like Velocity to support the html, csv, and custom content types.
Is this possible with 1 VelocityViewResolver? or do I need to configure one for each content type?
<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/> <!-- MarshallingView -->
<entry key="json" value="application/json"/> <!-- MappingJacksonJsonView -->
<!-- Would like the 3 content types below handled by Velocity -->
<entry key="html" value="text/html"/>
<entry key="csv" value="application/csv"/>
<entry key="custom" value="application/custom"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="false"/>
<property name="prefix" value=""/>
<property name="suffix" value=".vm"/>
</bean>
</list>
</property>
</bean>
Spring has ability to initialisate values of core java collection types.
I have a complex collection type Map<String, Set<String>> map and it inital value defined in spring config:
<bean id="dao" class="ru.mypkg.dao.DaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="map">
<map>
<entry key="TABLE">
<set>
<value>COMMENT</value>
<value>INDEX</value>
</set>
</entry>
<entry key="VIEW">
<set>
<value>COMMENT</value>
</set>
</entry>
</map>
</property>
</bean>
I want rewrite my config in next manner: Split it on 2 beans for more readability
<bean id="dao" class="ru.mypkg.dao.DaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="map" ref-id="myMap"/>
</bean>
<bean id="myMap" ..????..>
<entry key="TABLE">
<set>
<value>COMMENT</value>
<value>INDEX</value>
</set>
</entry>
<entry key="VIEW">
<set>
<value>COMMENT</value>
</set>
</entry>
</bean>
Can I achieve that with no creating additional classes?
Certainly, using the <util:map> namespace. See the Spring documentation C.2.2.5.
Another way to create complex configuration is using the #Configuration approach, or alternatively the FactoryBean interface.
How to inject a Map in java spring framework?
If possible please provide some sample code.
Is the following legal?
<property name="testMap">
<map>
<entry>
<key>
<value>test</value>
</key>
<value>
<list>
<value>String</value>
<value>String</value>
</list>
</value>
</entry>
</map>
</property>
Define a Map like this first inside your applicationContext.xml:
<util:list id="list1">
<value>foo#bar.com</value>
<value>foo1#bar.com</value>
</util:list>
<util:list id="list2">
<value>foo2#bar.com</value>
<value>foo3#bar.com</value>
</util:list>
<util:map id="emailMap" value-type="java.util.List">
<!-- Map between String key and List -->
<entry key="entry1" value-ref="list1" />
<entry key="entry2" value-ref="list2" />
...
</util:map>
Then use this Map in any bean of yours like this:
<bean id="myBean" class="com.sample.beans">
<property name="emailMap" ref="emailMap" />
</bean>
I think your syntax is not legal as spring throws org.xml.sax.SAXParseException when processing the bean configuration xml .
It should work after removing the <value> tag around the <list>.
<property name="testMap">
<map>
<entry>
<key>
<value>test</value>
</key>
<list>
<value>String</value>
<value>String</value>
</list>
</entry>
</map>
</property>
This is my example:
<bean class="com.common.handlermgmnt.HandlerMapAdder">
<constructor-arg index="0" type="java.util.Map">
<map key-type="java.lang.String" value-type="com.common.ViewWidget">
<entry key="DefaultView">
<bean class="com.common.DefaultViewWidget"/>
</entry>
<entry key="AnotherView">
<bean class="com.common.AnotherViewWidget"/>
</entry>
</map>
</constructor-arg>
<constructor-arg index="1" type="com.common.handlermgmnt.HandlerManager" ref="widget_handlerManager"/>
</bean>
Inject it using SpEL. #{id}. this works for me.
in the .xml:
<util:map id="roleLocationMap">
<entry key="ROLE_ADMIN" value-ref="listA" />
<entry key="ROLE_USER" value-ref="listB" />
</util:map>
in the .java
#Autowired
public MainController(
#Value("#{roleLocationMap}") final Map<String, List<String>> roleLocationMap) {
this.roleLocationMap = roleLocationMap;
}
Just ran into this case myself. If no need to reuse the list values as independent beans elsewhere, you could use this shorter version, without using 'value-ref':
<util:map id="mymap">
<entry key="key1">
<util:list>
<value>val1</value>
<value>val2</value>
</util:list>
</entry>
<entry key="key2">
<util:list>
<value>val2</value>
<value>val3</value>
<value>val4</value>
</util:list>
</entry>
</util:map>
And, wire it up in your Java code like this:
#Resource(name="mymap")
Map<String, List<String>> mapKey_List;