Thom
Thom

Reputation: 15092

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.

Upvotes: 0

Views: 61

Answers (2)

M. Deinum
M. Deinum

Reputation: 125202

Add the following to your applicationContext.xml.

<context:property-placeholder />

Now use ${configFileName} as the value for the properties you want to set. The configured property-placeholder will resolve those expressions for you.

<bean id="environmentVariables" class="com.gs.juror.kiosk.services.configuration.EnvironmentVariables">
    <property name="configFileName" value="${configFileName}"/>
    <property name="configFilePath" value="${configFilePath}"/>
</bean>

Now Spring will resolve them using the Environment abstraction build into Spring using PropertySource instances. One of them is for looking up properties from JNDI.

In short you are making things overly complex.

Upvotes: 0

Thom
Thom

Reputation: 15092

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?

Upvotes: 0

Related Questions