7

I have a servlet that reads in a .properties file on init(). My code (not the one below) works if I have a context-parameter set in my web.xml but I read that a context-parameter is globally accessible and I don't want that as this servlet is just a piece of a bigger web application. I just want to be able to do this using the init-param tag I tried this:

public void init(ServletConfig config) throws ServletException {

    try {
    String fileName = config.getInitParameter("configFile");
    System.out.println(fileName);
    File file = new File(fileName);
    FileInputStream fis = new FileInputStream(file);

    p = new Properties();

    p.load(fis);
} catch (IOException e) {
        e.printStackTrace();
    }
}

but I keep getting file not found exception. I have searched the internet but most people use servlet contexts. How else can I load my properties file without including the context-param tag in my web.xml?

Thanks!

EDIT:

java.io.FileNotFoundException: C:\WEB-INF\classes\myapp.properties (The system cannot find the path specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.io.FileInputStream.<init>(FileInputStream.java:79)
at ipadService.ProxyServlet.init(ProxyServlet.java:53)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1206)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:827)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:129)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
user1192724
  • 529
  • 2
  • 7
  • 14
  • Since you're printing the name of the fileName parameter (`configFile`), does that happen? Do you see the parameter that you specified in web.xml? If so, the parameter seems to work and the problem is within the way you're trying to load the file. Can you add the exception that you're getting? – nwinkler Mar 27 '12 at 15:43
  • Related: [getResourceAsStream() vs FileInputStream](http://stackoverflow.com/questions/2308188/getresourceasstream-vs-fileinputstream) and [Where to place configuration files?](http://stackoverflow.com/questions/2161054/where-to-place-configuration-properties-files-in-a-jsp-servlet-web-application) – BalusC Mar 27 '12 at 15:52
  • yes it prints out the filename properly. The error is '' – user1192724 Mar 27 '12 at 15:58
  • yes I did thank you. I now understand why that didn't work. I tried 'p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));' but I still get the same error – user1192724 Mar 27 '12 at 16:13

4 Answers4

12

Given that fileName is /WEB-INF/classes/myapp.properties, you need to get it as a webapp resource, not as a local disk file system file.

So, replace

String fileName = config.getInitParameter("configFile");
System.out.println(fileName);
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
p = new Properties();
p.load(fis);

by

String fileName = config.getInitParameter("configFile");
InputStream input = config.getServletContext().getResourceAsStream(fileName);
p = new Properties();
p.load(input);

A simpler way is to set the fileName to myapp.properties and get it as a classpath resource.

String fileName = config.getInitParameter("configFile");
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
p = new Properties();
p.load(input);

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • I could have sworn I tried this at some point! I probably missed out something. Thank you! Thank you everyone for sharing your knowledge, I have learnt so much from stack overflow! – user1192724 Mar 27 '12 at 16:17
  • considering the file is loaded as above - can we now write to it as well? -- what i am looking for is a way to initialize an outputstream with the path of a file inside web-inf/classes. is this possible? – sttaq Jun 01 '12 at 16:45
  • 1
    @sttaq: no. See also http://stackoverflow.com/questions/2161054/where-to-place-configuration-properties-files-in-a-jsp-servlet-web-application/2161583#2161583 – BalusC Jun 01 '12 at 16:48
  • hmm thats what I ended up with - had to place my file somewhere else. thanks – sttaq Jun 01 '12 at 16:52
  • @sttaq: you're welcome. Note that you can theoretically use `ServletContext#getRealPath()` to convert a web resource path to an absolute disk file system path, but all those changes would get lost whenever you redeploy the webapp simply because those changes are not contained in the original WAR. As a completely different alternative, take a look at `java.util.prefs.Preferences`. It stores the prefs in the OS-specific registry. It's however rarely used in Java EE webapps as sysadmins prefer self-documenting configuration files which they can just edit in vi/notepad. – BalusC Jun 01 '12 at 16:56
0

Problem is not with init param setting. Problem is how you are accessing the file. Make sure you have a config file in your class path, e.g. under Web-Inf directory; then change your code to access file like

InputStream is = getClass().getResourceAsStream(fileName);        
p = new Properties();                                       
p.load(is);
Sandip Dhummad
  • 933
  • 7
  • 9
0

I don't know how you set your web.xml, it should be ok as this:

<servlet>
    <servlet-name>MyServletName</servlet-name>
    <servlet-class>com.mycompany.MyServlet</servlet-class>

    <init-param>
        <param-name> param1 </param-name>
        <param-value> value1 </param-value>
    </init-param>
    <init-param>
        <param-name> param2 </param-name>
        <param-value> value2 </param-value>
    </init-param>
    ...
</servlet>

and as in your code, you didn't use absolute path, so this file will be found in classes directory, you should make sure this file exist in WEB-INF/classes dir.

Mavlarn
  • 3,451
  • 2
  • 29
  • 54
  • OP's concrete problem is that he used `FileInputStream` which should **not** be used at all in a webapp which is supposed to be portable. The params and so on are right, as confirmed by OP's comments and the exception message. – BalusC Mar 27 '12 at 16:17
-1
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
@WebServlet("/Propertyloader")
public class Propertyloader extends HttpServlet 
{
    private static final long serialVersionUID = 1L;


    public static Logger logger;
    public static Properties props=new Properties();
    public Propertyloader() 
    {
        super();
    }

    public void init(ServletConfig sconfig)
    {   
        try
        {   
            logger = Logger.getLogger(Propertyloader.class.getName());
            props.load(Propertyloader.class.getClassLoader().getResourceAsStream("books.properties"));
}
  • 1
    Welcome to SO :) It's always better to add an explanation to the code you're posting as an answer, so that it will helps visitors understand why this is a good answer. – abarisone Jul 05 '16 at 06:16