Import resource based on JNDI in Spring 4.x - spring

I want to import a resource based on a JNDI entry.
My application-context.xml looks like:
<jee:jndi-lookup id="td.naccms.cods2.config.path"
jndi-name="td.naccms.cods2.config.path" expected-type="java.lang.String"
default-value="classpath:application-context-persistence.xml" />
<context:property-placeholder />
<import resource="${td.naccms.cods2.config.path}" />
And tomcat returns the following error:
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [application-context-cods2-web.xml]; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'td.naccms.cods2.config.path' in string value "${td.naccms.cods2.config.path}"
Note, I do not want to load the resources from a property files because the resourse to be imported is going to change based on the JNDI.

When using placeholders ${...} you can use a : to specify another value in case the expression doesn't resolve (this could even be another placeholder!).
So instead of hacking around with lookups yourself just pass the value using a :.
<import resource="${td.naccms.cods2.config.path:classpath:application-context-persistence.xml}" />
The Environment abstraction (used to do resolving of placeholders in newer Spring versions) also checks JNDI for the property next to the System Environment, Property files (loaded through #PropertySource) and in a web application the ServletContext.

Related

how to handle name not found exception in application-context.xml?

I am creating a spring project using Oracle and jboss server.
I have one bean in my application-context.xml.
<!-- Datasource for TaskManager -->
<jee:jndi-lookup id="tmTestDataSource"
jndi-name="test_datasource" expectedtype="javax.sql.DataSource"/>
<bean id="tmTestJdbcTemplate" name="TmTestJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="tmTestDataSource" />
</bean>
If the 'test_datasource' JNDI (one datasource.xml file in jboss deployment folder, which contains db credentials like url, uid, password) inside the file found deployment is successfull, but if the file is not there then the deployment is failing.
I want to handle this exception so that deployment should not fail.
how I can do this. Can anybody provide me any solution.
Thanks.
Instead of using dataSource args constructor, you can set it using setter method.
This way your bean will be created but its datasource will be null. So you will get NPE if you try to use it, but at least bean creation tree will not be stalled.

How to configure address in JAX-WS CXF Client using JNDI lookup

I am looking up my JNDI value of endpoint (properties file is not an option) on server like this
<jee:jndi-lookup id="MyEndpoint" jndi-name="endpoint.url" />
I would like to use the above looked up value in the place of address.
<jaxws:client id="helloClient"
serviceClass="demo.spring.HelloWorld"
address="http://localhost:9002/HelloWorld" />
I tried address="${MyEndpoint}". Did n't work. Looks like I have to use another bean, which uses jndi value and use its method to return as string i.e. address="#{MyBean.geyMyEndpoint()}". Doesn't look clean that way. Any suggestions?
You should be able to use Spring Expression Language to get the behavior you want, without using another bean. The following works for me in Tomcat 7:
<jee:jndi-lookup id="MyEndpoint" jndi-name="java:comp/env/MyEndpoint" />
<jaxws:client id="helloClient"
serviceClass="demo.spring.HelloWorld"
address="#{MyEndpoint}" />
Also on another note from Spring 3.1 - Spring has unified property management. so instead of the above solution you can do this
<jaxws:client id="helloClient" serviceClass="demo.spring.HelloWorld" address="${endpoint.url}" />
endpoint.url could be any property(system, environment etc) and it will automatically resolve the property. so no need to do separate JNDI lookup and your code looks clean.

OSGi bundle read config properties

I have config.properties in my OSGi bundle. but the OSGi bundle can not read it.
Application context refresh failed (OsgiBundleXmlApplicationContext(bundle=dao, config=osgibundle:/META-INF/spring/*.xml))
org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException
I am using Spring to read the config.properties
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="config.properties" />
</bean>
It seems like the OSGi only reads the .xml file.
Does someone has any idea?
You have to specify the correct resource for your value property.
There are some built in implementations, like:
ClassPathResource: value="classpath:/META-INF/config.properties"
FileSystemResource: value="file:C:/foobar/config.properties"
If you want to place the file outside the library you can use a system property (e.g. -DpropertyFile=C:/loremIpsum/config.properties) to specify the path, like
value="file:${propertyFile}"
since Spring 3.0.? even with default value
value="file:${propertyFile:C:/foobar/config.properties}"
(Have a look at your OSGi framework on how to set a system property. I am also not sure if the ClassPathResource works well / is recommended in OSGi environments.)

how to inject webapp resource using relative path in spring

I have a bean which im trying to pass a relative path at web application startup. It works for an absolute path (running tomcat within eclipse) such as (C:/dev/workspace/project/src/main/webapp/WEB-INF/resource/)
However when I try to pass it a relative path such as WEB-INF/my_resource/ it says cannot find the location C:/dev/eclipse/WEB-INF/my_resource/ probably because tomcat is running within eclipse. How can I make this path relative so that it will be always picked up from whatever webcontainer is running it no matter the location of the webapp?
Ive read in place to use the servletconfig.getRelativePath(/) but neither know how to obtain the servlet config from within my bean or even if this is the right thing to do in Spring... Please help
The source code for my bean class and bean configuration xml can be found below
public class SuggestionIndexSearcher extends IndexSearcher {
private String indexSearcherType;
public SuggestionIndexSearcher(String type, String path){
super(path);
this.indexSearcherType = type;
}
...
}
The bean is defined in teh beans xml as...
<bean id="KMSearcherBean" class="com.hp.it.km.search.web.suggestion.SuggestionIndexSearcher">
<constructor-arg index="0" value="KMSearcher" />
<constructor-arg index="1" value="WEB-INF/resource/keyword" />
</bean>
If your change your bean to take org.springframework.core.io.Resource (javadoc) instead of String, then Spring will automagically coerce your path into the appropriate type of Resource. When running inside a servlet container, Spring will generally pick ServletContextResource, in which the path becomes relative to the webapp root (so WEB-INF/my_resource/ should work as you expect).
How your code chooses to handle Resource depends what you want to do with it, obviously.
No change is required in your XML config, just keep passing the path string as before. See the Spring manual for a wider description of resources.
Change the argument type from String to Resource - spring will then do the conversion and give you the resource object which you can process. You should be using an XMLWebApplicationContext (which is the default if the context is being created by the ContextLoaderListener or DispatcherServlet).
Take a look at this page for more details.

Loading Liferay Properties from Spring IoC container (to get jdbc connection parameters)

I'm developing some portlets for Liferay Portal 5.2.3 with bundled tomcat 6.0.18 using Spring IoC container.
I need to map the User_ table used in Liferay database to an entity with Hibernate, so I need to use two different dataSources to separate the liferay db from the db used by portlets.
My jdbc.properties has to hold all connection parameters for both databases: no problem for the one used by portlets, but I am having issues determining which database uses liferay to hold its data.
My conclusion is that i should have something like this:
liferayConnection.url=jdbc:hsqldb:${liferay.home}/data/hsql/lportal
in order to get the database url dynamically loaded, according to Liferay properties found in portal-ext.properties. (Or, better, load the whole portal-ext.properties and read database properties from there).
The problem is that the placeholder is not resolved:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'liferayDataSource' defined in class path resource [WEB-INF/applicationContext.xml]: Could not resolve placeholder 'liferay.home'
To dodge this problem I tried to load explicitly portal-ext.properties with a Spring bean:
<bean id="liferayPropertiesConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="../../portal-ext.properties"/>
but no luck: liferay.home is not resolved but there aren't other errors.
How can I resolve the placeholder defined by Liferay? Thanks
You can use PropsUtil class (from Liferay) to get values of portal-ext.properties.
String value = PropsUtil.get("key");
For loading properties files from an applicationContext.xml file I usually use the PropertiesFactoryBean specifying the location property with a the name of the file located in the classpath, like this:
<bean name="myHibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>classpath:hibernate.properties</value>
</property>
</bean>
Make sure the properties files are in a folder/package that is in the classpath.
You can call PropsUtil using SpringEL. for example:
#{T(com.liferay.portal.kernel.util.PropsUtil).get('liferay.home')}
I haven't tried exactly this. but you could load the liferay properties that you need with the following:
<util:properties id="liferayProps">
<prop key="liferay.home">#{T(com.liferay.portal.kernel.util.PropsUtil).get('liferay.home')}</prop>
</util:properties>

Resources