alexo / wro4j

New project location is:https://github.com/wro4j/wro4j
441 stars 110 forks source link

Processing fails when a WebJar in wro4j-extensions is overridden with newer version #131

Open mwanji opened 11 years ago

mwanji commented 11 years ago

I've put a tiny project that shows the problem here: https://github.com/mwanji/wro4j-webjar-versions

mvn compile works with default version of handlebars.js.

When I override the WebJar with a newer version, mvn compile throws the following error:

java.lang.IllegalArgumentException: Multiple matches found for handlebars.js. Please provide a more specific path, for example by including a version number. at org.webjars.WebJarAssetLocator.getFullPath(WebJarAssetLocator.java:222) at ro.isdc.wro.extensions.locator.WebjarUriLocator.locate(WebjarUriLocator.java:68)

When I override and specify the version in wro.xml, it works:

webjar:1.0.0-rc.4/handlebars.js
alexo commented 11 years ago

The problem is within webjars-locator itself. Other than a fix to webjars-locator is there anything else you would suggest?

alexo commented 11 years ago

Actually this is not a problem, rather a legitimate error which requires the client of the code to increase resource uri specificity to avoid situation when a different resource is located by mistake.

alexo commented 11 years ago

Hmmm... weird. Apparently when the following classloader is used: Thread.currentThread().getContextClassLoader() all resources from maven repo (not only those that a part of the classpath) are loaded. I'm not even sure it is a problem with maven, webjars-locator or something else....

alexo commented 11 years ago

Apparently this fails only when using maven plugin. When using runtime solution (a filter used in a webapp deployed with jetty) everything works fine.

Maybe a different classloader should be used for maven plugin only?

mwanji commented 11 years ago

OK, I hadn't tried the filter yet. But not every JAR from the repo is on the classpath, only the ones in wro4j-extensions and the overridden webjars. I'll try to play around with the maven plugin to see if I can find some more info.

alexo commented 11 years ago

I think the problem is with wro4j-maven-plugin. There is a code responsible for extending classpath which is inspired from http://teleal.org/weblog/Extending%20the%20Maven%20plugin%20classpath.html

As a result, the extended classpath has more dependencies (also those which are excluded). I will think about a fix for this. If you have any suggestion, let me know.

Thanks, Alex

mwanji commented 11 years ago

I go it to work with the filter, but then added Ember template compilation and am getting another failure, with both the Maven plugin and the filter. This version is here: https://github.com/mwanji/wro4j-webjar-versions/tree/webjar_not_found

When building its init script, EmberJs looks for the jquery WebJar and can't find it (I'm using the WebJars bundled directly into wro4j-extensions). It seems the WebJarAssetLocator's fullPathIndex is empty.

Am I doing something wrong here?

alexo commented 11 years ago

You should add jquery webjar explicitly, because it is not added transitively by handlebars yet.

mwanji commented 11 years ago

D'oh! I thought I'd seen it in the list. Sorry about that.

mwanji commented 11 years ago

Not sure if this is a problem with wro4j, webjars-locator or something else, but this fails on JBoss 7.1, even though it works on Tomcat.

On JBoss, the WebJarAssetLocator's fullPathIndex really is empty. In my case, it doesn't pick up jquery.js whether it's included transitively, directly or even if I copy it into src/main/resources (using the webjars folder structure).

mwanji commented 11 years ago

I've spent some time with the Maven plugin, but it's not obvious to me what a solution would be. The problem seems to be that the current thread's context classloader already contains wro4j-extension's bundled webjars, then the project's Maven-defined webjars are added to the new classloader. Removing classes or resources from a classloader doesn't seem to be an option.

Maybe we could add a ConflictResolver to webjars-locator that would be called when multiple versions are found. Default would throw an exception and the Maven plugin could use another that chooses latest version.

What do you think?

alexo commented 11 years ago

The problem is definitely in wro4j-maven-plugin. There should be a way to identify the runtime dependencies and use those in the custom classLoader. I'm working on it, but didn't find yet a solution.

mwanji commented 11 years ago

But isn't it a problem that the bundled webjars are already on the classpath, so the scanning that webjars-locator does will always find them?

alexo commented 11 years ago

The maven plugin explicitly creates a custom ClassLoader. The problem is that it search also in excluded dependencies...

mwanji commented 11 years ago

Yes, but those excluded dependencies are in the parent classloader before the custom one is created.

I tried copying the parent's URLs to a new classloader and setting its parent to another new classloader with only the Maven runtime dependencies, but that led to ClassCastExceptions, probably because the classloader is part of a class's signature.

alexo commented 11 years ago

I got the same error. This happens because the same class is loaded with two different classLoaders. Tricky one..