Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make javax.servlet-api a 'provided' dependency not 'compile' #50

Merged
merged 2 commits into from
Dec 14, 2012
Merged

Make javax.servlet-api a 'provided' dependency not 'compile' #50

merged 2 commits into from
Dec 14, 2012

Conversation

benjchristensen
Copy link
Contributor

Make javax.servlet-api a 'provided' dependency for compilation but not transitive.

Trying to make it so it doesn't force a servlet version or a specific jar. Nothing about the implementation requires anything higher than Servlet 2.x.

…t transitive.

Trying to make it so it doesn't force a servlet version or a specific jar. Nothing about the implementation requires anything higher than Servlet 2.x.
@benjchristensen
Copy link
Contributor Author

Justin (@quidryan), is this a satisfactory approach with Gradle to mark the Servlet jar as only needed for compilation but not a transitive dependency that forces builds to the declared version?

The specific issue here is that Sun published 2.2 to 3.0 beta as javax.servlet:servlet-api (http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22javax.servlet%22%20AND%20a%3A%22servlet-api%22) but then Oracle published 3.0.1 onwards as javax.servlet:javax.servlet-api (http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22javax.servlet%22%20AND%20a%3A%22javax.servlet-api%22) so I can only use one of them, I can't put a range from 2+ and work with both.

I have chosen 3.x as the newest (which is already 1 1/2 years old) but don't want builds forced to either one.

@quidryan
Copy link
Contributor

There isn't a provided scope out-of-box in Gradle, so I wouldn't expect this specific merge to work. The closest is the one added by the war plugin, which adds providedRuntime and providedCompile. There are ways to replicate "provided", I'll suggest something soon for this.

This merge stills implies that 3.0 of the servlet-api is available at runtime, which it might not be (i.e. using Tomcat 6). You're right that you can't simply use a range, blame Oracle for this, but since it's going into a provided scope, it's sorta moot what it's called. I would suggest sticking with 2.5 of the servlet, especially if that's all that you're using, specifically javax.servlet:servlet-api:2.5. 3.0 is different enough that it's not worth touching, e.g. it added extra bounds to the return type on getParameterMap(), which can break code.

@benjchristensen
Copy link
Contributor Author

Justin, I thought we already had solved the 'provided' functionality, as we use it in hystrix-core => https://github.com/Netflix/Hystrix/blob/master/hystrix-core/build.gradle

I'll downgrade to 2.5.

benjchristensen added a commit that referenced this pull request Dec 14, 2012
…ency

Downgrade to javax.servlet:servlet-api:2.5 instead of 3.0
@benjchristensen benjchristensen merged commit e388f82 into Netflix:master Dec 14, 2012
@quidryan
Copy link
Contributor

The provided scope is a Hystrix thing only, i.e. it's not in gradle-template, so I wasn't too familiar with it. I'm not so sure that the way it's implemented will get you the right behavior, specifically the "compile.extendsFrom provided" line will make any dependencies still show up as dependencies, which defeats the point. I added a slightly different provided scope to the gradle-template project, I'll make a pull-request with the merge in it.

@benjchristensen
Copy link
Contributor Author

The way I had confirmed it was working was that when I download dependencies from Maven Central for hystrix-core the JUnit jar is not included:

  • archaius-core-0.4.1.jar
  • commons-lang-2.6.jar
  • hystrix-core-1.1.0.jar
  • slf4j-api-1.7.0.jar
  • commons-configuration-1.8.jar
  • commons-logging-1.1.1.jar
  • jsr305-2.0.0.jar

That is using this maven file:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.netflix.hystrix.download</groupId>
        <artifactId>hystrix-download</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>Simple POM to download hystrix-core and dependencies</name>
        <url>http://github.com/Netflix/Hystrix</url>
        <dependencies>
                <dependency>
                        <groupId>com.netflix.hystrix</groupId>
                        <artifactId>hystrix-core</artifactId>
                        <version>1.1.0</version>
                        <scope/>
                </dependency>
        </dependencies>
</project>

@quidryan
Copy link
Contributor

That definitely looks good. Yeah, what you have is working. I'm going to finish up adding it to gradle-template, so at least you're in sink with the other projects.

@benjchristensen
Copy link
Contributor Author

So would it make sense for me to also change this:

compile 'javax.servlet:servlet-api:2.5'

to this:

provided 'javax.servlet:servlet-api:2.5'

This would mean the servlet jar isn't pulled in, but the expectation is always that someone is deploying a servlet to a servlet container (Tomcat, Jetty, JBoss etc) that will already have all of those libs.

@quidryan
Copy link
Contributor

Yes. This is one of the quirks of provided, it does imply that your users know about it. In contrast, you can put the dependency into the runtime configuration, which explicitly says you want this dependency at runtime but then most build tools will then package it up into a war, where it'll conflict with the container parent classloader. It's mostly a flaw in the original servlet specs that cause this weird situation.

BTW, Java should solve something like thing via Jigsaw, and then have your war state what it wants for dependencies, and if it's already in the runtime, ignore it.

@benjchristensen
Copy link
Contributor Author

Agreed on all of those points.

For this particular case I think I'm going to do the 'provided' solution since there is never a time when running a servlet is not going to be in a container with the proper runtime libs already there.

I'd rather optimize for the normal case and not cause version collisions between 2.x and 3.x - particularly because the state of Maven Central doesn't let me give a range and forces me to pick one or the other.

Are you okay with me choosing that solution considering none of them are ideal?

@quidryan
Copy link
Contributor

Sounds good. I think there is an issue with "compile.extendsFrom provided" when publishing to ivy though, but we can talk about that on the pull request I'll be making.

@benjchristensen
Copy link
Contributor Author

Done in commits 9dec369 and 7b05350

@quidryan
Copy link
Contributor

Sent #51 to integrate provided from
gradle-template.

On Fri, Dec 14, 2012 at 12:23 PM, Ben Christensen
[email protected]:

Done:

9dec3699dec369
7b053507b05350


Reply to this email directly or view it on GitHubhttps://github.com//pull/50#issuecomment-11390889.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants