Giter VIP home page Giter VIP logo

jruby-gradle-jar-plugin's Introduction

jruby-gradle-jar-plugin's People

Contributors

mkristian avatar ysb33r avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

jruby-gradle-jar-plugin's Issues

shadowjar should not be an implicit dependency

When I remove the line pulling in shadowjar from the plugins repository, my gradlefile fails now.

FAILURE: Build failed with an exception.

* Where:
Build file '/usr/home/tyler/source/github/blick/build.gradle' line: 36

* What went wrong:
A problem occurred evaluating root project 'blick'.
> Could not find method shadowJar() for arguments [build_53hpiloh3ahr8sdm93qjclshj9$_run_closure5@4d3c6593] on root project 'blick'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 17.618 secs

IMHO, since we need shadowjar to build jars properly, it should be an explicit dependency, what do you think @ysb33r ?

jars bundled into gems should not be unzipped

Some gems include jar files within their codebases which they require to function correctly.

Setting aside whether or not I think this is a "good idea" or not, the jar plugin should not futz with the contents of gems that are being included in the shadow jar.

See johnrengelman/shadow#111 for the upstream question about how to accomplish this

allow the jrubyJar taks to use an alternative "gems" dependencies

currently the JRubyJar task depends on jrubyPrepare from the base plugin and defaultGems() does use it.

you can supply and alternative gems directory - in this case the dependency to jrubyPrepare should be dropped. not sure what happens with the jars directory . . . the code feels half baked here.

Fat jar configuration should be maintained through the jrubyJar task

All configuration that has to deal with the creation of a self-contained executable JRuby jar artifact should be managed under the jrubyJar task, e.g.

jrubyJar {
    initScript 'app.rb'
    defaultMain() /* optional, present unless otherwise specified */
    defaultGems() /* optional, present unless otherwise specified */
    configuration configurations.compile /* dependencies in this configuraiton are shaded in */
}

This task would take the ruby files added to the main sourceset and pull them into the jar

if there is not META-INF/init.rb just do not try to require it

the META-INF/init.rb is something which comes from jruby-rack and is meant as way to setup the ENV used by jruby-rack. warbler uses it as well in the same manner for runnable jars., i.e. when it detects a rack application it will include ENV['RACK_ENV']='production'

whether the warbler defaults and magic makes sense I do not know, but if there is no such init.rb file, just do nothing and continue launching.

see also
https://github.com/mkristian/jruby-mains/blob/master/src/main/java/de/saumya/mojo/mains/JRubyMain.java#L65

TODO list for 0.1.4

We need to do the following before releasing 0.1.4

  1. Merge #38
  2. Remove support for and dependencies on shadowJar
  3. Update the README with the new documentation - Explicitly state that it is a breaking change.
  4. Mark the new jruby-mains as @Incubating
  5. Update Spock framework to 1.0
  6. Remove maven { url 'http://dl.bintray.com/rtyler/jruby' }
  7. Delay the use of JrubyVersion until last possible moment (see jruby-gradle/jruby-gradle-plugin#115)
  8. FIx the hard-coded 0.2.0 in JRubyJarPlugin - https://github.com/jruby-gradle/jruby-gradle-jar-plugin/pull/38/files#diff-0db12cd653b5b3468ac21351b2bf8466R73

Following the README yields "there is no initScript configured" from gradle task execution

https://github.com/jruby-gradle/jruby-gradle-jar-plugin#executable-jar-controlling-the-ruby-entry-point-script

Stacktrace:

runUserAcceptanceTests task with environment: development
Snapshot Version: 1.0.0-SNAPSHOT
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jrubyPrepareGems UP-TO-DATE
:jrubyPrepareJars UP-TO-DATE
:jrubyPrepare UP-TO-DATE
:shadowJar

FAILURE: Build failed with an exception.

* What went wrong:
there is no initScript configured

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.StopExecutionException: there is no initScript configured
    at com.github.jrubygradle.jar.JRubyJarConfigurator.applyConfig(JRubyJarConfigurator.groovy:164)
    at com.github.jrubygradle.jar.JRubyJarConfigurator.this$dist$invoke$1(JRubyJarConfigurator.groovy)
    at com.github.jrubygradle.jar.JRubyJarConfigurator$1.methodMissing(JRubyJarConfigurator.groovy)
    at com.github.jrubygradle.jar.JRubyJarConfigurator$1.beforeExecute(JRubyJarConfigurator.groovy:215)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:83)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:31)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy10.beforeExecute(Unknown Source)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:76)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:80)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:51)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)

build.gradle

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "com.github.jruby-gradle:jruby-gradle-plugin:0.1.17"
    classpath "com.github.jengelman.gradle.plugins:shadow:1.2.1"
    classpath "com.github.jruby-gradle:jruby-gradle-jar-plugin:0.2.1"
    classpath "org.ajoberstar:gradle-git:0.13.0"
  }
}

jrubyJar {
    jruby {
        initScript "bin/my-executable"
    }
}

Environment Details:

> gradle --version

------------------------------------------------------------
Gradle 2.2.1
------------------------------------------------------------

Build time:   2014-11-24 09:45:35 UTC
Build number: none
Revision:     6fcb59c06f43a4e6b1bcb401f7686a8601a1fb4a

Groovy:       2.3.6
Ant:          Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM:          1.8.0_05 (Oracle Corporation 25.5-b02)
OS:           Mac OS X 10.9.5 x86_64

> java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

reproducible builds with gem dependencies

the nature of using version ranges in dependencies is that the transitive dependency hull of the project can/will change over time. this means it is NOT possible or very difficult to reproduce a build from the past. for a library this is probably less a problem since there you want to keep the version ranges open (and/or hope semantic versioning works). for other projects like a rails-app or a sinatra-app I want to be able to rerun the build which went into production anytime in future.

in ruby world there is bundler which helps to address the problem by locking down the version of ALL dependencies.

to use gradle + bundler side by side is probably the way to go:

  • bundler will manage the gem dependencies
  • gradle will manage your build artifact or assembly

Should the jar plugin disable the java plugin's jar task and archive?

When using the jar plugin with the 'java' plugin applied there are two archives in the artifacts list, one for the default 'jar' and one for the 'shadowJar' that would be generated.

If you want to use uploadArchives the task will fail unless you have existing Java code that would go into the default 'jar' task

I've disabled this behavior with:
'''
jar.enabled = false
configurations.archives.artifacts.removeAll { it.archiveTask.is jar }
'''

But wonder if the jar plugin should handle this in some form or fashion

Plugin should have a JRubyFatJar type which can be extended

Much of this behavior I think should be consolidated into a JRubyJar task type which inherits from Jar and provides all the necessary "fat jar" functionality that we need.

I would like to be abler to extend this functionality, e.g.:

task serviceJar(type: JRubyFatJar) {
    dependsOn myOtherCustomTasks
    archiveName 'foobar'
    from('special/dir')
}

To where the .jrubydir and other fat-jar magic are applied when my "foobar.jar" is created.

That'd be nice.

jar plugin doesn't specify the jruby dependency

From this code

[8:52:40] tyler:jruby-gradle-example git:(master) $ ./gradlew jar
:jrubyJavaBootstrap UP-TO-DATE
:compileJava
/usr/home/tyler/source/github/javaone-jruby-demo/jruby-gradle-example/build/generated/java/META-INF/gradle-plugins/bootstrap.java:3: error: package org.jruby.embed does not exist
import org.jruby.embed.ScriptingContainer;
                      ^
/usr/home/tyler/source/github/javaone-jruby-demo/jruby-gradle-example/build/generated/java/META-INF/gradle-plugins/bootstrap.java:4: error: package org.jruby.embed does not exist
import static org.jruby.embed.PathType.*;
                             ^
/usr/home/tyler/source/github/javaone-jruby-demo/jruby-gradle-example/build/generated/java/META-INF/gradle-plugins/bootstrap.java:5: error: package org.jruby does not exist
import org.jruby.CompatVersion;
                ^
/usr/home/tyler/source/github/javaone-jruby-demo/jruby-gradle-example/build/generated/java/META-INF/gradle-plugins/bootstrap.java:40: error: cannot find symbol
    private ScriptingContainer container;
            ^
  symbol:   class ScriptingContainer
  location: class JarMain
/usr/home/tyler/source/github/javaone-jruby-demo/jruby-gradle-example/build/generated/java/META-INF/gradle-plugins/bootstrap.java:10: error: cannot find symbol
        container = new ScriptingContainer();
                        ^
  symbol:   class ScriptingContainer
  location: class JarMain
5 errors
:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 28.611 secs
[8:53:13] tyler:jruby-gradle-example git:(master) $ 

Issue with rake running with incorrect path

Expected java -jar build/libs/example.jar -T to output a list of rake tasks inside the .jar, instead rake appears to be running from and searching for tasks in the current directory.

Rakefile

puts File.expand_path(File.dirname(__FILE__) + '/tasks')
# Load all our tasks from the tasks directory
Dir[File.expand_path(File.dirname(__FILE__) + '/tasks/*.rake')].each do |f|
  load f
end

In my codebase, .rake files are located inside lib

   lib/tasks/
   lib/tasks/example_task.rake
   Rakefile

In the .jar the tasks directory is in the root...

   29 tasks/
   30 tasks/example_task.rake
   31 Rakefile

When I run java -jar build/libs/example.jar -T any tasks I have locally (outside the .jar) are output instead of tasks bundled into the .jar

allow the user of JRubyJar task to pick the DuplicatesStrategy

due to some existing duplicates between the .jrubydir files generated by the base plugin and the JRubyJar task the strategy is set to EXCLUDE.

it almost looks like the base plugin does not need to generate those '.jrubydir' files and this could solve this problem.

jrubyJar shouldn't require the jar task to execute

With @mkristian's recent changes being merged, it is now impossible to build a jrubyJar (fat jar) without also producing a jar artifact.

:jar SKIPPED
:jrubyJar

FAILURE: Build failed with an exception.

* What went wrong:
Cannot expand ZIP '/home/tyler/source/lookout/metron/build/libs/metron-3.0+0fd969d.jar' as it does not exist.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

This dependency link should be broken and the jrubyJar task should be able to contruct its tree on its own without requiring that the jar task also execute.

In effect, I should be able to disable the jar task and still execute jrubyJar

classloader semantics

jruby has two classloaders:

  • the classloader with jruby itself - main-classloader
  • each runtime has its own classloader which has the main-classloader as parent - jruby-classloader

so jar-dependencies and jbundler uses require 'some.jar' which loads this jar into the jruby-classloader
this is a dynamic process and completely inside the realm of ruby code.

this allows the ruby code to decide which jars to load and which one not to load. this is something I used yesterday for a workaround:

https://github.com/lookout/leafy/blob/master/leafy-metrics/leafy-metrics.gemspec
declares slf4j-simple which is never used during runtime:
https://github.com/lookout/leafy/blob/master/leafy-metrics/lib/leafy-metrics_jars.rb

currently it is used only when running tests.

now the gem-artifacts from the torquebox maven repository can have jar dependencies and jruby-gradle-jar-plugin readme basically says to use shadowJar to bundle them into a uberjar. this changes the classloader semantic drastically since all the jars are part of the main-classloader now and this one is static and outside the control of the ruby code.

with my example of leafy-metrics this means slf4j-simple is always part of the main-classloader and the ruby code can NOT decide to NOT use the jar.

so the proper way to bundle jar-dependencies would to build a local maven repository at the root of the jar: i.e. the org.slf4j:slf4j-api:1.7.7 artifact should be located org/slf4j/slf4-api/1.7.7/slf4j-api-1.7.7.jar and let jar-dependencies load it - let the ruby code decide whether when to load it ;)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.