Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 318449

Summary: Class.getResource() breaks when "Serve modules without publishing" is activated
Product: [WebTools] WTP ServerTools Reporter: Peter Walter <guardian>
Component: jst.serverAssignee: Larry Isaacs <larryisaacs>
Status: RESOLVED FIXED QA Contact: Angel Vera <arvera>
Severity: normal    
Priority: P3 CC: ioeth.trocolar
Version: unspecifiedFlags: arvera: pmc_approved? (david_williams)
arvera: pmc_approved? (raghunathan.srinivasan)
arvera: pmc_approved? (naci.dai)
deboer: pmc_approved+
arvera: pmc_approved? (neil.hauge)
arvera: pmc_approved? (kaloyan)
arvera: review+
Target Milestone: 3.2.1   
Hardware: PC   
OS: Windows XP   
See Also: https://git.eclipse.org/r/108974
Whiteboard: PMC_approved
Attachments:
Description Flags
Patch to restore getClass().getResource() functionality. none

Description Peter Walter CLA 2010-06-30 08:24:02 EDT
Build Identifier: 20100618-0524

When the Deployment Option "Serve modules without publishing" is activated than Class.getResource() returns an URL to the assumed location within WEB-INF/classes instead of the real Source Directory.

Example:
I have a File "test.txt" in the root of my source folder.

Calling Class.getResource("test.txt") gives the following:
(I verified this via this.getClass().getResource() within a JSP Page and via TestClass.class.getResource())

- without "Serve modules without publishing":
file:/C:/Workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Test/WEB-INF/classes/test.txt

- with "Serve modules without publishing":
file:/C:/Workspace/Test/WebContent/WEB-INF/classes/test.txt

- Real path in the file system
C:\Workspace\Test\src\test.txt

The Bug was tested with Tomcat 5.5.27

(The functionality got broken within Helios - in the last version of Galileo everything worked as expected).

Reproducible: Always

Steps to Reproduce:
1. Create a new Dynamic Web Project
2. Place a file inside a source folder
3. Create a JSP printing out this.getClass().getResource("/test.txt")
4. View with either "Serve modules without publishing" activated or not
Comment 1 Larry Isaacs CLA 2010-06-30 16:34:57 EDT
I'm able to duplicate this problem, though I believe Galileo would have returned a URL to "C:/Workspace/Test/build/classes/test.txt".  This would appear to be a regression caused by the attempt to support multiple web content folders, something that Tomcat doesn't really support.  The fix is likely to be found in the jar that gets copied to the Tomcat installation.  I'll see if I can create a patched version you can use to test the fix.
Comment 2 Matthew Hall CLA 2010-07-02 09:28:13 EDT
I'm also experiencing this problem.  In my case, when I reproduce the issue, I've noticed that Eclipse is including the extraResourcePaths attribute in the generated webapp context XML, with the value "/WEB-INF/classes|/Users/<username>/Workspaces/<workspace dir>/<project dir>/bin", in the Resources element.  When I remove the attribute and value, everything works just fine, and the file diffs exactly the same as what Galileo would have generated.  Hope this helps!
Comment 3 Larry Isaacs CLA 2010-07-06 15:29:38 EDT
Created attachment 173591 [details]
Patch to restore getClass().getResource() functionality.

Including "/WEB-INF/classes|/<workspace>/<project>/<java output folder>" in the extraResourcePaths attribute was an attempt to allow methods like the following to work with "Serve modules without publishing" enabled:

    ServletContext.getResource("/WEB-INF/classes/<path to some resource>");
    ServletContext.getResourceAsStream("/WEB-INF/classes/<path to some resource>");

Unfortunately, this issue is a side effect of that attempt.  There doesn't appear to be a way to get both Class.getResource() ServletContext.getResource("WEB-INF/classes/...") to work.  Since the methods above methods didn't work in prior versions of WTP and the Class.getResource() did, this would constitute a regression.  The patch eliminates including the "/WEB-INF/classes" mappings in the extraResourcePaths attribute.
Comment 4 Larry Isaacs CLA 2010-07-07 09:35:47 EDT
Angel, I'm requesting this bug be reviewed for inclusion in WTP 3.2.1.  PMC info below.  Thanks.


Explain why you believe this is a stop-ship defect. Or, if it is a "hotbug" (requested by an adopter) please document it as such.

The current WTP 3.2 behavior is a regression.  Class.getResource() in a web project would work correctly with "Serve modules without publishing" enabled in prior versions, but is broken in WTP 3.2.  Though WTP 3.2 now supports ServletContext.getResource("/WEB-INF/classes/<path to resource>"), it's more important that Class.getResource() work. 

 
Is there a work-around?

No work-around other than not using the "Serve modules without publishing" feature with web projects using Class.getResource() or Class.getResourceAsStream().

How has the fix been tested?

I've tested it in my development environment.


Give a brief technical overview. Who has reviewed this fix? 

I'm not sure I can explain this such that it won't sound like Greek.  The Tomcat implementation expects there to be one folder (i.e. docBase) under which all static resources are located.  Hacking around this to support multiple static resource folders made easy by the Deployment Assembly page has led to this issue.  It turns out that Tomcat implements classpath lookups and static resource lookups in such a way that the list of folders to be searched for each must be kept separate.  The current WTP implementation mixes the two lists, which confuses the classpath searching into thinking resources exist on the classpath in locations where they don't.  As a result, Class.getResource() returns a non-functioning URL.  The fix is to not include mappings for Java output folder(s) from the web project in the extraResourcePaths attribute found in the <Resources> element in the server.xml.  Only including Java output folders in the virtualClasspath attribute ensures that Class.getResource() will only find classpath resources where they actually exist.

What is the risk associated with this fix?

The "Serve modules without publishing" feature is isolated, so the impact is limited.  The change is simple and unlikely to introduce other side effects other than to make ServletContext.getResource("/WEB-INF/classes/<path to resource>") stop working, which never worked in prior versions either.  I would rate this a low risk change providing a major improvement in behavior.
Comment 5 Larry Isaacs CLA 2010-07-07 09:37:30 EDT
Moving e-mail to the correct flag field.
Comment 6 Peter Walter CLA 2010-07-07 10:10:30 EDT
I found a possible work-around to this issue by setting my context WEB-INF/classes folder as Java output folder.

In this way the otherwise wrongly assumed location becomes the valid one :)
Comment 7 Angel Vera CLA 2010-07-07 13:38:51 EDT
Putting up for PMC approval. The changes only affect tomcat scenarios
Comment 8 Larry Isaacs CLA 2010-07-07 22:40:02 EDT
Changes released to 3.2 maintenance for WTP 3.2.1 RC2.
Comment 9 Eclipse Genie CLA 2017-10-11 16:34:19 EDT
New Gerrit change created: https://git.eclipse.org/r/108974