weavejester / lein-ring

Ring plugin for Leiningen
Eclipse Public License 1.0
501 stars 100 forks source link

resource-path #5

Closed himangshuj closed 13 years ago

himangshuj commented 13 years ago

normally, the way we interpret resource-path of leiningen to denote files in classpath, but this plugin does not treat them as such and the while creating war, the resource files do not go inside WEB-INF/classes folder. this breaks the code, I had to change the code for our use case. do you see a way to distinguish between web resource and classpath resource

weavejester commented 13 years ago

It's rather unfortunate that Java has two different and incompatible ways of accessing resources.

On the one hand, putting the resources in WEB-INF/classes would allow resources to be accessed in the same way in both the Jetty adapter, and in a deployed war file. But on the other hand, putting resources in the classes directory seems rather bad practice.

I'm not quite sure what the best solution is, so what I'll do is I'll add a new configuration option, :resources-war-path, which will allow you to control where the resources are placed in the war. e.g.

:ring {:handler hello-world.core/app
       :resources-war-path "WEB-INF/classes/"}

In the future, I may make this the default, but for now you'll have to set the value manually. I'll release a new version with this change either tonight or tomorrow.

himangshuj commented 13 years ago

i was thinking on other lines -> distinguish between class-path resources and static resources which needs to be put in the root directory of war . something in these lines (dir-entry project "WEB-INF/classes/" (:compile-path project)) (dir-entry project "WEB-INF/classes/" (:source-path project)) (dir-entry project "WEB-INF/classes/" (:resources-path project)) (dir-entry project "" (:static-resources project))

weavejester commented 13 years ago

If it was going to have a separate key, I'd prefer something like :servlet-resources-path or something like that. I'm also not convinced that the :resources-path directory should be put into WEB-INF/classes.

himangshuj commented 13 years ago

hi in normal clojure projects the files under resources are accessible as classpath resource , there should be some consistency in the behavior in war file according to me. For instance when u do lein ring server my code was working fine but starting bombing after making the war. Atleast the behavior of lein ring server and the created war should be same

himangshuj commented 13 years ago

off hand topic, can you reopen the issue, since it is not yet closed. hit by the github bug

weavejester commented 13 years ago

I know of two ways of dealing with this problem:

  1. Shoehorn the resources into WEB-INF/classes.
  2. Use a function capable of finding resources from both the classpath and servlet context.

Currently I've gone for option 2 in Compojure, as I didn't like the idea of putting resources in a directory meant for classes.

However, now that I Google around, it's starting to look like placing resources in WEB-INF/classes is not uncommon. I'll need to check around a little more, see if there isn't an alternative, but I'm warming to the idea of using WEB-INF/classes. It's a hack, but maybe a standard one.

himangshuj commented 13 years ago

hi, but if my memory serves right, you can access stuff inside WEB-INF/classes only if the contents are referred to in web.xml, otherwise static content might not be served. I might be wrong on this

weavejester commented 13 years ago

If you're using the standard getResourceAsStream method, you don't need to reference the resources in web.xml. Otherwise I don't think Clojure would work at all, as it references source files as resources on the classpath.

himangshuj commented 13 years ago

i was not refering to getResourceAsStream, I was talking abt pure html codes like <img src="">.

weavejester commented 13 years ago

Ah, I see. This has come up as a topic on the clojure-web-dev Google group:

http://groups.google.com/group/clojure-web-dev/browse_thread/thread/760fe555f8b5cbec

I think the solution I'm going to go with is to have the :resources-path dump files in WEB-INF/classes, and have a custom :servlet-resources-path dump files in the root of the war file.

So it's basically a very similar solution to the one you outlined :)

I don't like the idea of putting resources in WEB-INF/classes, but I think it's the least worst option.

himangshuj commented 13 years ago

Great !!! man soon i ll be able to get rid of custom dependency :D.

butlermh commented 11 years ago

Hi, I am very new to Clojure - so please forgive a newbie :-)

I am working with Snowplow's clojure collector. In order to build the collector it is necessary to add three resources to the war manually. I wondered if there was a better way to do so I did some investigating. The collector is using lein-ring to build and it seems to be related to the issue above. Specifically if I add

  :resource-paths   ["war-resources/.ebextensions"]

to project.clj then if I call the lein jar target everything is fine but if I call the lein ring uberwar target the resources are in WEB-INF/classes hence the need to put the resources manually in the war.

I noticed in the README you refer to resources-path not resource-paths although both are concatenated in the code. However if I try using resources-path in project.clj I get an error

$ lein ring war
java.lang.IllegalArgumentException: No implementation of method: :as-file of protocol: #'clojure.java.io/Coercions found for class: clojure.lang.PersistentVector

I tried war-resources-path (again referred to in the README) but that generates the same error. `war-resource-pathsdoes not generate an error but does not seem to include the resources either at the root or inWEB-INF/classes``.

I also tried the servlet-resources-path referred to above (and it's variant servlet-resource-paths just in case). The former throws an error but the latter seems to do nothing.

Is there any way to automatically include the resources in the war root?

I suspect the documentation is broken because it refers to resources-path and war-resources-path neither of which work and this issue - that sometimes you want resources in WEB-INF/classes and sometimes at the root - has only been fixed the former case, not the latter. May I suggest adding the property servlet-resource-paths as outlined above to fix this use case?

BTW Thanks very much for making this plugin available

butlermh commented 11 years ago

Okay, a bit more digging ... sorry I said I was a clojure newbie ...

: war-resources-path "war-resources/.ebextensions"

works - unlike `war-resource-paths`` it does not need to be a vector. Problem solved.