• Post Reply Bookmark Topic Watch Topic
  • New Topic

(No such file or directory) getClass().getResource("/networks/file.zip").getFile();  RSS feed

 
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I have a web project in Maven.
When I start Tomcat in Eclipse and go to the browser, the system works normally. When I generate .war and do the deployment without server, I can not load this file, error "no file or directory".
Already even check any server if the file was without correct path after deploy, and it was yes.

(No such file or directory)
getClass().getResource("/networks/file.zip").getFile();
 
Bartender
Posts: 19353
86
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the JavaRanch, Wellington!

you should not try to get a "file" in a webapp. Officially, a webapp is part of a WAR, which is a ZIP-format (JAR) file, and thus the "files" inside the WAR are not true files that can be opened via ordinary OS filesystem calls.

Also, it's not good practice to reference anything relative to a WAR's filesystem, for various reasons, most of which boil down to it's unreliable.

If you want to get a "file" (resource) within a webapp, use the getResource() or getResourceAsStream() method calls against the webapp's ServletContext. The getResourceAsStream method is especially useful, since it presents the resource already open for reading. The resource path is always rooted at the base of the WAR, so for example:


Close the resource when you're done with it.

You might notice that there's a getRealPath() servletContext method. Avoid it. It returns the absolute filesystem path of a resource, but if the webapp is in an unexploded WAR, that will return NULL.

As a general rule, if a file is not directly bundled within a WAR, you should reference it by an absolute filesystem path (J2EE does not define a "working directory" for webapps). I recommend putting that path in an injected resource (server JNDI) so you can change it without recompiling the WAR.

And never, absolutely NEVER attempt to write anything into a WAR. Even when it works, it's a ticking bomb.
 
Wellington Oliveira
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Hi,

But i am not using Servlets. In the front-end i have angularjs and Java in the back-end.
They are simple Java Classes... Actually i do not right anything about servlets.

I thought i was supposed to locate my files into /src/main/resources. The files are neural networks and i dont want them to be accessible on web. That's why i located the file into the resource folder.

When i start the server in Eclipse, it loads and works 100%. The problem is when i deploy the .war file at the real server.

I already tried the codes below and i still have the problem. What else should I do..

and




Tim Holloway wrote:Welcome to the JavaRanch, Wellington!

You should not try to get a "file" in a webapp. Officially, a webapp is part of a WAR, which is a ZIP-format (JAR) file, and thus the "files" inside the WAR are not true files that can be opened via ordinary OS filesystem calls.

Also, it's not good practice to reference anything relative to a WAR's filesystem, for various reasons, most of which boil down to it's unreliable.

If you want to get a "file" (resource) within a webapp, use the getResource() or getResourceAsStream() method calls against the webapp's ServletContext. The getResourceAsStream method is especially useful, since it presents the resource already open for reading. The resource path is always rooted at the base of the WAR, so for example:


Close the resource when you're done with it.

You might notice that there's a getRealPath() servletContext method. Avoid it. It returns the absolute filesystem path of a resource, but if the webapp is in an unexploded WAR, that will return NULL.

As a general rule, if a file is not directly bundled within a WAR, you should reference it by an absolute filesystem path (J2EE does not define a "working directory" for webapps). I recommend putting that path in an injected resource (server JNDI) so you can change it without recompiling the WAR.

And never, absolutely NEVER attempt to write anything into a WAR. Even when it works, it's a ticking bomb.


 
Tim Holloway
Bartender
Posts: 19353
86
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm afraid that you are operating with insufficient knowledge.

Servlets are the way webapps work. Even if you don't write your own servlet and use a framework such as JavaServer Faces or Struts, there's at least one servlet that handles the incoming HTTP URL requests (although in such cases the servlet is part of the framework). Even JSPs compile down into servlets. The servlets may call out to simple classes, but the core processing for every web request goes through a servlet.

"/src/main/resources" is not a Tomcat or Enterprise Java directory. It's how you store files in a Maven project where Maven can copy them into the webapp. And if you're doing a Maven WAR build, the proper directory isn't src/main/resources, it's src/main/webapp. There will not be a "/src/main/resources" directory in the WAR.
 
Wellington Oliveira
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok,

The directory maven created for me is /WEB-INF/classes/redes/file.zip (the file is there).

What i am doing is:



and the error i am getting is:




How can i find a servlet for calling and trying this method getResourceAsStream()??



Tim Holloway wrote:I'm afraid that you are operating with insufficient knowledge.

Servlets are the way webapps work. Even if you don't write your own servlet and use a framework such as JavaServer Faces or Struts, there's at least one servlet that handles the incoming HTTP URL requests (although in such cases the servlet is part of the framework). Even JSPs compile down into servlets. The servlets may call out to simple classes, but the core processing for every web request goes through a servlet.

"/src/main/resources" is not a Tomcat or Enterprise Java directory. It's how you store files in a Maven project where Maven can copy them into the webapp. And if you're doing a Maven WAR build, the proper directory isn't src/main/resources, it's src/main/webapp. There will not be a "/src/main/resources" directory in the WAR.

 
Wellington Oliveira
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Just correcting a typing mistake.... but the problem is the same...


Wellington Oliveira wrote:Ok,

The directory maven created for me is /WEB-INF/classes/redes/file.zip (the file is there).

What i am doing is:



and the error i am getting is:




How can i find a servlet for calling and trying this method getResourceAsStream()??



Tim Holloway wrote:I'm afraid that you are operating with insufficient knowledge.

Servlets are the way webapps work. Even if you don't write your own servlet and use a framework such as JavaServer Faces or Struts, there's at least one servlet that handles the incoming HTTP URL requests (although in such cases the servlet is part of the framework). Even JSPs compile down into servlets. The servlets may call out to simple classes, but the core processing for every web request goes through a servlet.

"/src/main/resources" is not a Tomcat or Enterprise Java directory. It's how you store files in a Maven project where Maven can copy them into the webapp. And if you're doing a Maven WAR build, the proper directory isn't src/main/resources, it's src/main/webapp. There will not be a "/src/main/resources" directory in the WAR.

 
Tim Holloway
Bartender
Posts: 19353
86
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, you don't need the servlet. What you need is the ServletContext. You can get the ServletContext from the HttpServlet that is currently processing your request or from its HttpServletRequest parameter.

In a JSP, you can use the scriptlet "request.getServletContext();" method call to get the servletContext. Although if you're putting logic in JSPs, the Bear will growl at you.

In pure Java if you are running under some sort of framework, then the framework usually has a way to pass the HttpServletRequest object to your user-defined class if you code your class right. The actual mechanism that's available depends on the framework, so without knowing what's calling your Java classes I cannot say anything specific.
 
Sheriff
Posts: 23485
46
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Wellington Oliveira wrote:The directory maven created for me is /WEB-INF/classes/redes/file.zip (the file is there).



When you say the file is "there", what exactly do you mean by "there"?

/var/lib/tomcat8/webapps/produto/WEB-INF/classes/redes/file.zip



This is what "there" means in the context of your Web application when it is running. When Maven created your WAR file it should have put the file there, if its input was correct. So I'd suggest you review your setup and make sure that file is put into the "classes" folder the right way.
 
Tim Holloway
Bartender
Posts: 19353
86
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, Paul.

Maven isn't going to do that unless you are very careful in how you set things up. Its normal course of action when building a WAR is to construct/copy/compile into MAVEN_PROJECT_DIRECTORY/target/goalname and then (assuming you're running the war:war goal), to zip that into a MAVEN_PROJECT_DIRECTORY/target/goalname.war file. Only if you've added a deployment option is it going to then propagate the target war to a server such as Tomcat.

But to repeat myself, using brute-force filesystem and classpath operations to get a webapp resource is not something I recommend. It's too complicated and too breakable. For example, anything that assumes that the current working directory is the WAR root is in for a big disappointment. Or even that the current working directory will always be the same when Tomcat runs. This is why I promote using the J2EE resource access methods.

The hard part about that is that you do need some sort of way to obtain the ServletContext, but then if you're going to get WAR resources, you really should have managed the app so that that's not impossible. Ideally, I suppose, you should be able to go the JSF route and have a static means of getting ServletContext, but such niceties had not been thought of when J2EE was first designed.

I may be mis-reading, but I think that Wellington put the resources in the right place and has done the right call to get at them ("right" meaning functional, though not recommended). But this logic can fail regardless if the WAR was not exploded. Because, as I said initially, a "file" in a WAR isn't necessarily a "real" file.
 
Tim Holloway
Bartender
Posts: 19353
86
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:

/var/lib/tomcat8/webapps/produto/WEB-INF/classes/redes/file.zip



This is what "there" means in the context of your Web application when it is running.



Not your day Paul. "Context" as used in Enterprise Java isn't a filesystem context, it's a webapp resource context. A lot of people get confused because a context path in a URL looks a lot like a Unix filesystem path. But it isn't. Not even when the web server maps it to a filesystem path. The syntax is similar, but the mechanisms are very, very different. The context here is "/produto" and the canonical URL path would be "http://host:port/produto/WEB-INF/classes/redes/file.zip". Although again, a web server is not a file server, so Tomcat will refuse to resolve WEB-INF or its contents to external URL requesters. You'd get a 404 Resource Not Found response.

Internally is another story, which is why a servletContext.getResource("/produto/WEB-INF/classes/redes/file.zip") will work even on an unexploded WAR as long as the resource is in the expected place.

J2EE very deliberately does not know about what the directory organization of the webapp server is. It makes things more portable and it makes them much more secure. You cannot walk uphill into sensitive OS resources if the uphill path literally does not exist.

Or to put it another way, by specifying a suitable Tomcat Context definition, you can - and I often do - have my webapps deployed such that that resource would be located in a place such as /opt/com/mousetech/produto.zip. And if J2EE resource resolution methods are used, it will be just as easy to obtain the /produto/WEB-INF/classes/redes/file.zip resources from there as it would be if I deployed my webapp to TOMCAT_HOME/webapps. In both cases, TOMCAT_HOME would actually be something like /usr/local/apache-tomcat on my system, regardless of the filesystem locations of my webapps.
 
Wellington Oliveira
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Thanks everybody.

I made a change on my code and now it works fine:

i changed this:

to this:

         



Tim Holloway wrote:

Paul Clapham wrote:

/var/lib/tomcat8/webapps/produto/WEB-INF/classes/redes/file.zip



This is what "there" means in the context of your Web application when it is running.



Not your day Paul. "Context" as used in Enterprise Java isn't a filesystem context, it's a webapp resource context. A lot of people get confused because a context path in a URL looks a lot like a Unix filesystem path. But it isn't. Not even when the web server maps it to a filesystem path. The syntax is similar, but the mechanisms are very, very different. The context here is "/produto" and the canonical URL path would be "http://host:port/produto/WEB-INF/classes/redes/file.zip". Although again, a web server is not a file server, so Tomcat will refuse to resolve WEB-INF or its contents to external URL requesters. You'd get a 404 Resource Not Found response.

Internally is another story, which is why a servletContext.getResource("/produto/WEB-INF/classes/redes/file.zip") will work even on an unexploded WAR as long as the resource is in the expected place.

J2EE very deliberately does not know about what the directory organization of the webapp server is. It makes things more portable and it makes them much more secure. You cannot walk uphill into sensitive OS resources if the uphill path literally does not exist.

Or to put it another way, by specifying a suitable Tomcat Context definition, you can - and I often do - have my webapps deployed such that that resource would be located in a place such as /opt/com/mousetech/produto.zip. And if J2EE resource resolution methods are used, it will be just as easy to obtain the /produto/WEB-INF/classes/redes/file.zip resources from there as it would be if I deployed my webapp to TOMCAT_HOME/webapps. In both cases, TOMCAT_HOME would actually be something like /usr/local/apache-tomcat on my system, regardless of the filesystem locations of my webapps.

 
Paul Clapham
Sheriff
Posts: 23485
46
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Wellington Oliveira wrote:
Thanks everybody.

I made a change on my code and now it works fine...



So, it's like Tim said: you can get an InputStream from the resource but not a File, which sounds to me like the WAR is an unexploded WAR.
 
Wellington Oliveira
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes,

Thanks Tim!!!


Paul Clapham wrote:

Wellington Oliveira wrote:
Thanks everybody.

I made a change on my code and now it works fine...



So, it's like Tim said: you can get an InputStream from the resource but not a File, which sounds to me like the WAR is an unexploded WAR.

 
Tim Holloway
Bartender
Posts: 19353
86
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're welcome! 

One thing to note: The difference between using getResource on a class versus getResource on the ServletContext is that the class getResource is searching the webapp's classpath. That means not only the WEB-INF/classes and the JARs in WEB-INF/lib, but also classes that come from the webapp server (for example, classes in the Tomcat servlet-api.jar file).

The getResource on ServletContext will not return stuff external to the WAR (like Tomcat's servlet-api.jar), but on the other hand, it will return stuff in the WAR that's not in the servlet's classpath. For example  "/README.md".
 
Wellington Oliveira
Greenhorn
Posts: 7
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Nice to know...
Thanks Tim!


Tim Holloway wrote:You're welcome! 

One thing to note: The difference between using getResource on a class versus getResource on the ServletContext is that the class getResource is searching the webapp's classpath. That means not only the WEB-INF/classes and the JARs in WEB-INF/lib, but also classes that come from the webapp server (for example, classes in the Tomcat servlet-api.jar file).

The getResource on ServletContext will not return stuff external to the WAR (like Tomcat's servlet-api.jar), but on the other hand, it will return stuff in the WAR that's not in the servlet's classpath. For example  "/README.md".

  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!