Reputation: 633
I have a central class (RuntimeConfiguration
) that holds around 100
parameters for my application. These parameters are taken from an XML file which I stored in the WEB-INF
folder. On my development box, I hard-coded the path, but for very obvious reasons, this is not a productive solution.
For portability reasons (my application might be executed on a Tomcat or a Jetty and under Windows OR Unix), I want to have a generic access way to this file from within my RuntimeConfiguration
class.
I know, I can use getRealPath
in case I have a servlet, BUT RuntimeConfiguration
is NOT started within a servlet context. It is invoked from a job (a crawler) which in turn is started from quartz job control via applicationContext.xml
. Now this seems to be the core of my problem.
Can anyone tell me, how to get the absolute path to my XML in this environment?
I tried this ClassLoader
approach, but it gives me a NullPointerException
:
ClassLoader loader = this.getClass().getClassLoader();
loader.getResource("WEB-INF");
result = loader.getSystemResource(RTCF).toString();
I also tried
URL url = this.getClass().getClassLoader().getResource("WEB-INF");
which also throws a null pointer exception
Can anyone give me a portable solution, one that works on my dev-machine and on a production system where my application is deployed as a WAR-file?
By the way, the method should at best be able to handle Windows AND Mac OS X / Unix based systems.
Upvotes: 6
Views: 15919
Reputation: 148870
You can always use the holder pattern : you create a class, with a static field (with its static getter) that will contain the real path of the WEB-INF
directory. This class should implement ApplicationContextAware
You create in root spring application context an instance of this holder class, Spring give it a pointer to the ApplicationContext that will be a WebApplicationContext
as you are in a web application.
In the init method, you use the WebApplicationContext
to get the path and store it in the static field. Thanks to Spring, you are sure that the method is called once and only once before the application really starts.
Now anywhere in the application where you want to get the path, you can use it by calling the static getter.
public class ResourcePathHolder implements ApplicationContextAware, InitializingBean{
private WebApplicationContext wac;
private static String resourcePath;
private static ServletContext sc;
private String path = "WEB-INF";
public static String getResourcePath() {
return resourcePath;
}
public static ServletContext getServletContext() {
return sc;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
wac = (WebApplicationContext) applicationContext;
}
public void setPath(String path) {
this.path = path;
}
@Override
public void afterPropertiesSet() throws Exception {
ResourcePathHolder.sc = wac.getServletContext();
ResourcePathHolder.resourcePath = sc.getRealPath(path);
}
}
This implementation also gives you access to the ServletContext
to allow you to use ServletContext.getResource()
EDIT :
Using the full path may not work on production servers that would not explode the war. From the javadoc for ServletContext.getRealPath()
: This method returns null if the servlet container is unable to translate the given virtual path to a real path. But in that case, you can always access to the files as resources with ServletContext.getResource()
or ServletContext.getResourceAsStream()
Upvotes: 1
Reputation: 12453
Just put it in your classpath and load it with "getResourcesAsStream()", or better make it a ".properties"-file and load it the usual way:
ResourceBundle config = ResourceBundle.getBundle("filename");
Upvotes: 0
Reputation: 2807
In spring web application, you cannot get context path until you declare some class as bean in your web application context. Add below code in your RuntimeConfiguration
class
@Autowired
private ServletContext servletContext;
public {desired returnType} getDirectoryPath(){
File webInfPath = new File(this.getClass().getClassLoader().getResource("WEB-INF"));
// OR use getResourceAsStream() method
InputStream is = RuntimeConfiguration.class.getClassLoader().getResourceAsStream("WEB-INF");
}
OR
If you don't want to do autowiring, then you can implement RuntimeConfiguration with ServletContextAware interface. Just like below, to get servlet context object in this class :-
public class RuntimeConfiguration implements ServletContextAware {
private ServletContext context;
private ServletConfig config;
@Override
public void setServletContext(final ServletContext servletContext) {
this.context = servletContext;
}
public ServletContext getServletContext()[
return context;
}
//do other tasks
}
OR
Have a look at ServletContextResource ServletContextResource - Spring Docs
Upvotes: 0