Tomcat: Servlet Context Parameters

I have been working with Tomcat and Srping and was trying to get settings from the META-INF/context.xml to be accessible in Spring or the JSPs. I found a few ways. The first one is by creating a JNDI resource using a custom bean and @Autowire it. The second involves context parameters.

Custom JNDI Resource

In the META-INF/context.xml I would write this:

<Context>
<Resource 
	name="test"
	type="bean.Test"
	factory="org.apache.naming.factory.BeanFactory"
 
	test1="value1" 
	test2="value2"
/>
</Context>

The bean.Test class is simple bean with getters and setters (for value test1 and test2) and a default constructor.

In the Spring context file would include this:

<jee:jndi-lookup 
	id="test" 
	jndi-name="java:comp/env/test"
	expected-type="bean.Test" 
/>

Which needs those schema entries:

xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"

The one can simpy use the @Autowire annotation as in

@Autowired
private Test test;

Context Paramters

It is also possible to access context parameters using the @Value annotation.

The META-INF/context.xml would specify a parameter:

<Context>
	<Parameter name="test" value="testvalue" override="false"/>
</Context>

The value is then accessible using the @Value annotation:

@Value("#{contextParameters.test}")
private String test;

Considerations

The interesting thing is how to nicely export those parameters to the Model (to be accessed in a JSP).
The first solution makes it easy when adding the bean.Test object to the Model using the @ModelAttribute annotation. It is also possible to have several configuration objects. But when adding new parameters, the bean.Test class would need to be updated.
The second does not need adjustment of any class, but exposing parameters to the Model needs adding every single parameter to the Model using the @Value annotation because it does no allow to get a map but only single properties. This will need coding again.
Maybe there is a solution to create a properties like JNDI resource. Probably by creating custom factory class for creating the JNDI resource as shown blow.

PropertiesFactory

To the pom.xml, add the folowing dependency:

<dependency>
	<groupId>org.apache.tomcat</groupId>
	<artifactId>catalina</artifactId>
	<version>6.0.16</version>
	<scope>provided</scope>
</dependency>

Then one can implement the class factory.PropertiesFactory:

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
 
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
 
import org.apache.naming.ResourceRef;
 
 
public class PropertiesFactory implements ObjectFactory {
 
	public Object getObjectInstance(
			Object obj, 
			Name name, 
			Context nameCtx,
			Hashtable<?, ?> environment) throws Exception {
 
		if (obj instanceof ResourceRef) {
 
			Properties properties = new Properties();
 
			Reference ref = (Reference) obj;
			Enumeration<RefAddr> e = ref.getAll();
 
			while (e.hasMoreElements()) {
				RefAddr ra = (RefAddr) e.nextElement();
				properties.setProperty(
						ra.getType(), 
						ra.getContent().toString());
			}
 
			return properties;
 
		}
		return null;
 
	}
 
}

and use it as follows:

META-INF/context.xml

<Context>
<Resource 
	name="test"
	type="java.util.Properties"
	factory="factory.PropertiesFactory"
 
	test1="value1" 
	test2="value2"
/>
</Context>

applicationContext.xml

<jee:jndi-lookup 
	id="test" 
	jndi-name="java:comp/env/test"
	expected-type="java.util.Properties" 
/>

Java

@Autowired
@Qualifier(value = "test")
private Properties test;
VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Leave a Reply