javaspringtomcatjndi

Using JNDI environment variables with Spring/Tomcat


I have been given responsibility of a web services project for a Kiosk.

I am simply trying to inject a couple of Strings from the JNDI in the tomtact contaxt into a Spring bean. I have found scant documentation for this (although found extensive documentation for JNDI datasources) and I've down my best to piece together what's going on.

Inside the tomcat context file, I have:

<Context path="/kiosk" debug="0" reloadable="true"
         crossContext="true">
     <Resource name="jdbc/kiosk" auth="Container" type="javax.sql.DataSource"
                maxTotal="20" 
                maxIdle="-1" maxWaitMillis="20000" 
                username="xxxx"  password="xxxx" 
                driverClassName="com.informix.jdbc.IfxDriver"     
                url="jdbc:some:url"/>
     <Environment name="configFilePath"
         value="c:\\dev\\KioskServicesConfiguration\\"
         type="java.lang.String" override="false"/>
     <Environment name="configFileName"
         value="KioskServicesConfiguration"
         type="java.lang.String" override="false"/>

</Context>

Inside my applicationContext.xml I have:

    <!-- Location of the configuration file stored ih the context -->
    <bean id="configFileName" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/configFileName"/>
    </bean>
    <bean id="configFilePath" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/configFilePath"/>
    </bean>

And my class definition:

@Service
public class XMLConfigurationLoader implements ConfigurationLoader {

    private static Logger logger = LogManager.getLogger();
    private static final String CONFIG_FILE_NAME = "configFileName";
    private static final String CONFIG_FILE_PATH = "configFilePath";

    //injected
    @Resource(name = CONFIG_FILE_NAME)
    private String envName;
    @Resource(name = CONFIG_FILE_PATH)
    private String envPath;

    ...

    private List<GlobalConfiguration> loadConfigurationFromXML() {
        System.err.println("envName:" + envName);
        System.err.println("envPath:" + envPath);
    }

And then the output:

envName:null
envPath:null

Since I'm not getting an error, it's hard to figure out what's wrong. Can anyone point the way for me? Spring 4, java 8.

UPDATE: I tried changing the name of the Environment entry to env/configFilePath to see what would happen and Spring threw an exception for not being able to locate the resource, so it appears that Spring is pulling the resource from the context successfully.

UPDATE: Changing the resource name

@Resource(name = "Slartibartfast")
private String envName;

Also results in an error, so Spring is loading the bean.


Solution

  • Still not sure what the problem was, but I worked around it. I created a new class:

    public class EnvironmentVariables implements InitializingBean {
        private String configFileName;
        private String configFilePath;
    
        @Override
        public void afterPropertiesSet() throws Exception {
            if (configFileName == null || configFileName.isEmpty()) throw new NullPointerException("configFileName is not defined");
            if (configFilePath == null || configFilePath.isEmpty()) throw new NullPointerException("configFilePath is not defined");
        }
    
        public String getConfigFileName() {
            return configFileName;
        }
    
        public void setConfigFileName(String configFileName) {
            this.configFileName = configFileName;
        }
    
        public String getConfigFilePath() {
            return configFilePath;
        }
    
        public void setConfigFilePath(String configFilePath) {
            this.configFilePath = configFilePath;
        }
    }
    

    Then added a new bean definition:

        <!-- Location of the configuration file stored ih the context -->
        <bean id="configFileName" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:comp/env/configFileName"/>
        </bean>
        <bean id="configFilePath" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="java:comp/env/configFilePath"/>
        </bean>
    
        <bean id="environmentVariables" class="com.gs.juror.kiosk.services.configuration.EnvironmentVariables">
            <property name="configFileName" ref="configFileName"/>
            <property name="configFilePath" ref="configFilePath"/>
        </bean>
    

    Finally, I autowired it into a setter on XMLConfigurationLoader:

    @Autowired
    public void setEnvironmentVariables(EnvironmentVariables environmentVariables) {
        this.environmentVariables = environmentVariables;
    }
    

    And then, using the getter methods on this works fine.

    Not sure where the breakdown was, but this is working, so I'm happy. Wonder if this is a bug in Spring?