0

I have a TranslateServlet that takes some text, creates an instance of a Cracker class and calls a getCrackedResult method which returns a HashMap of keys and values:

public class TranslateServlet extends HttpServlet {
    public static void main(String[] args) {
        Cracker cracker = new Cracker("German", "English");
        HashMap<String, ArrayList<Cracker.EntrySet<String, ArrayList<String>>>> crackedResults =
                cracker.getCrackedResult("Ich bin");

        for (String category: crackedResults.keySet())  {
            System.out.print(category);  //works fine
        }

    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        Cracker cracker = new Cracker("German", "English");

        HashMap<String, ArrayList<Cracker.EntrySet<String, ArrayList<String>>>> crackedResults =
                cracker.getCrackedResult("Ich bin");

        for (String category: crackedResults.keySet())  {
                response.getWriter().print(category);  //doesn't work
        }

        response.getWriter().print("DONE");  //works fine
    }
}

However, while iterating over a HashMap inside the main method works fine, when trying to get the key values through doPost() method, I only get DONE as an output, and no other values. Why??

EDIT: "Doesn't work" means doesn't output categories. If the main method outputs "Dog", "Cat", the jsp page only outputs "Done", instead of "Dog", "Cat", "Done".

What is wrong with my question to suffice closing it? Thank you anonymous downvoter too.

EDIT: I checked the tomcat's log and there is a java.io.FileNotFoundException: some_folder/some_file.bin error every time the servlet is called.

I realised that the function getCrackedResult makes use of a local file like this:

InputStream inputPOS = new FileInputStream("some_folder/some_file.bin");

I tried moving the file to WEB-INF and changing the file path:

InputStream inputPOS = new FileInputStream("WEB-INF/some_folder/some_file.bin");

But I still get the exception: java.io.FileNotFoundException: WEB-INF/some_folder/some_file.bin.

How should I deal with the file so that Cracker class, specifically its getCrackedResults function could get it after deployment. My file structure looks like this:

Project Root
------------src
---------------com
------------------util
----------------------Cracker.java
------------------web
---------------------TranslateServlet.java
------------target
------------------classes
-------------------------com
----------------------------util
--------------------------------Cracker.class
----------------------------web
-------------------------------TranslateServlet.class
------------imgs
------------some_folder
-----------------------some_file.bin
------------WEB-INF
-------------------classes
-------------------lib
-------------------some_folder
------------------------------some_file.bin (tried putting it here)
xerx593
  • 12,237
  • 5
  • 33
  • 64
parsecer
  • 4,758
  • 13
  • 71
  • 140
  • What is wrong with your question is that it isn't complete. No `Cracker` class. – user207421 Feb 08 '19 at 04:58
  • The title doesn’t fit what your code is doing. The normal approach would be to have the servlet set request attributes and let the JSP get them from the request. – Nathan Hughes Feb 08 '19 at 05:16
  • @Nathan Hughes That's what I initially did. But in trying to get to the root of the problem I tried the servlet output the `HashMap` directly which didn't work, meaning the problem is somewhere in the servlet inself. – parsecer Feb 08 '19 at 05:20
  • The `src` directory isn't there at runtime. You need to place it and access it as a resource, not as a file. – user207421 Feb 10 '19 at 00:25
  • 1
    to make it work, (try) put it under `WEB-INF/classes/some_folder/some_file.bin` ...and then refer to `new FileInputStream("some_folder/some_file.bin");` ...if that doesn't load `...ClassLoader.getResourceAsStream("/some_folder/some_file.bin");` could. – xerx593 Feb 10 '19 at 00:30
  • @xerx593 The first one won't work, the second one will. – user207421 Feb 10 '19 at 00:32
  • 1
    *best* would be `request.getServletContext().getResourceAsStream(path)`, where path starts with "/" and is relatively to your servlet context root (the root of your .war ..the folder "deployed" above "WEB-INF") ..answer!?;) ...then you *could* put it *above* WEB-INF, which i would still **not** recommend. – xerx593 Feb 10 '19 at 00:48
  • @xerx593 I tried the `InputStream inputPOS = Cracker.class.getClassLoader().getResourceAsStream("some_folder/some_file.bin")`, but it seems the `InputStream` is null, because I get a `NullPointerException`. Tried it with both `"some_folder/some_file.bin"` and `"WEB-INF/some_folder/some_file.bin"` as arguments. Tried putting the `/` in front of both paths as well, same result. – parsecer Feb 10 '19 at 01:01
  • @xerx593 You would still not recommend why? – user207421 Feb 10 '19 at 01:02
  • @parsecer You didn't copy his code correctly. Note 'where `path` starts with "/"'. – user207421 Feb 10 '19 at 01:02
  • @user207421 "Tried putting the / in front of both paths as well, same result". – parsecer Feb 10 '19 at 01:03
  • @user207421 The resource is under `Project Root/some_folder/some_file.bin` (and now that I've copied it, it's in `Project Root/WEB-INF/some_folder/some_file.bin` as well). – parsecer Feb 10 '19 at 01:06
  • Why? That's not where you were told to put it. Why post the question if you're going to just ignore what you're being told here? – user207421 Feb 10 '19 at 01:08
  • I followed @xerx593 comment. As far as I can see, they didn't mention moving the file anywhere else. – parsecer Feb 10 '19 at 01:09
  • No you didn't. @xerx593 has said to use `ClassLoader.getResourceAsStream()` or `ServletContext.getResourceAsStream`. You have used neither. You have also not followed his suggested resource placement in either case. He certainly did mention moving it elsewhere. Twice. – user207421 Feb 10 '19 at 01:18
  • ..not recommend: because the file (some.bin) is exposed to "the web", WEB-INF folder is protected (no1 can "download" your web.xml;). `Cracker.class.getClassLoader()`...is not (always) good in servlet environment, alternative: `Thread.currentThread().getContextClassLoader().getResourceAsStream("path/relatively/to/WEB-INF/classes")` ..and best: (there are several ways to obtain the servletcontext) `... ServletContext.getResourceAsStream("/WEB-INF/where-ever-you-put-it/some.bin")` – xerx593 Feb 10 '19 at 01:19
  • @xerx593 You appear to suggest that you are not recommending `ServletConext.getResourceAsStream()`, in the comment where you introduced it. – user207421 Feb 10 '19 at 01:20
  • Nono, I *recommend* `ServletConext.getResourceAsStream("/WEB-INF/some_folder/some.bin")` :) , and the file must be there. (in .war) – xerx593 Feb 10 '19 at 01:25
  • "This method is different from java.lang.Class.getResourceAsStream, which uses a class loader. This method **allows servlet containers to make a resource available to a servlet from any location, without using a class loader**." from [servletContext-javadoc](https://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html#getResourceAsStream-java.lang.String-) – xerx593 Feb 10 '19 at 01:28
  • aah, **not recommend**: placing sensible files outside WEB-INF! xD – xerx593 Feb 10 '19 at 01:33
  • possible dup: https://stackoverflow.com/q/12883861/592355 – xerx593 Feb 13 '19 at 15:01

2 Answers2

1

Solution:

Please deploy(!) /WEB-INF/some_file/some.bin at the correct location, then you can access its FileInputStream from a servlet environment like:

java.io.InputStream inS = /*httpRequest.get*/servletContext
    .getResourceAsStream("/WEB-INF/some_file/some.bin");

See: ServletContext Javadoc (Java8)

Community
  • 1
  • 1
xerx593
  • 12,237
  • 5
  • 33
  • 64
0

For now, I managed to fix it with

InputStream inputPOS = Cracker.class.getClassLoader().getResourceAsStream("some_folder/some_file.bin");

solution and placing some_folder/some_file.bin both inside

  1. Project Root/target/classes (so that code would work inside IDE)

and

  1. Project Root/WEB-INF/classes (so that code would work when deployed on tomcat).
parsecer
  • 4,758
  • 13
  • 71
  • 140