Problems trying to create a library jar with embedded gems

80 views
Skip to first unread message

Abel Salgado Romero

unread,
Aug 22, 2015, 9:50:32 AM8/22/15
to JRuby Gradle
Hi,

I am trying to create a simple jar with some gems embedded amb I having some issues. One seems to be a bug, the rest are more design doubts.
Since I can get long, I think we can discuss it here insted of GitHub, bt let me know if you prefer to move this there.

* First the bug, when I create a simple project with the jar plugin I use this configuration:

-----
dependencies {
    jrubyJar "rubygems:prawn:$prawnGemVersion"
}
jrubyJar {
    initScript library()
}
-----

Since I don't want it to be runnable i set it to library, however when I run the task I get this:

-----
:jruby-with-jar:jrubyJar FAILED

FAILURE: Build failed with an exception.

* What went wrong:
A problem was found with the configuration of task ':jruby-with-jar:jrubyJar'.
> No value has been specified for property 'mainClass'.
-----


To me, the fact that it requires a mainClass seems contrary to what the documentation states here http://jruby-gradle.org/jar/#library:
"A library jar isn’t really much more than a container which includes the configured gems and jar dependencies inside of the packaged.jar file."

* Now, the doubts

Seems to me that the jar plugin is aimed to make Ruby easy to execute and it tries to embedd everything inside a fat jar. It does not take into consideration that:
  • jRuby can be added in the classpath on runtime. For instance, to be able to use different jRuby versions
  • The jar does not need to embedd anything other than it's own java code and gems
Are my assumptions corrent?
If they are, using the jar plugin is not useful and we have to rely on the base plugin with some small hack. Basically this:

----
dependencies {
    // If we use the jar plugin, we could use jrubyJar too (I think)
    gems "rubygems:asciidoctor:1.5.2+"
    gems "rubygems:prawn:$prawnGemVersion"
}

// Set the files we want to copy from the gems. We don't need all
def gemFiles = fileTree(jruby.gemInstallDir) {
    include 'specifications/*.gemspec'
    include 'gems/*/lib/**'
    include "gems/*/data/fonts/*"
}

// copy the required gem files to the resources folder
jrubyPrepare << { // See PS note
    copy { // bundles the gems inside this artifact
        from gemFiles
        into sourceSets.main.output.resourcesDir
    }
}

// Add gems processing to ensure gems are included during task 'jar'
processResources.dependsOn jrubyPrepare 
----

What do you think? Do you think it makes sense to be able build jars like that with the jar plugin or do you think we should rely on the hack?
The way I see it, it does make sense. Specialy since the "library()" options seems to be for that case. What I miss are the options to:
  • Be able to avoid including rubygems:jar-dependencies, org.jruby:jruby-complete, org.jruby.mains:jruby-mains as dependencies. Seeing the code should not be complicated, the thing is how to do it, I'm not sure what's better: a new extension or in the JrubyJar task?
  • Be able to apply file filters on the dependency section to be able to get what we do with "getFiles" in the example above. This is really not 100% necessary but helps making jars smaller.

PS: Also, instead of copying the files we coul add them to the jar, but I am not sure what's best. Anyway, that's another subject.
----
jar {
    from gemFiles
}
----

R. Tyler Croy

unread,
Aug 22, 2015, 6:22:51 PM8/22/15
to jruby-...@googlegroups.com
(replies inline)

On Sat, 22 Aug 2015, Abel Salgado Romero wrote:

> I am trying to create a simple jar with some gems embedded amb I having
> some issues. *One seems to be a bug, the rest are more design doubts*.
> Since I can get long, I think we can discuss it here insted of GitHub, bt
> let me know if you prefer to move this there.
>
> ** First the bug, when I create a simple project with the jar plugin I use
> this configuration:*
>
> -----
> dependencies {
> jrubyJar "rubygems:prawn:$prawnGemVersion"
> }
> jrubyJar {
> initScript library()
> exclude '**/*.gem' //
> From https://github.com/jruby-gradle/jruby-gradle-plugin/issues/200
> }
> -----
>
> Since I don't want it to be runnable i set it to library, however when I
> run the task I get this:
>
> -----
> :jruby-with-jar:jrubyJar FAILED
>
> FAILURE: Build failed with an exception.
>
> * What went wrong:
> A problem was found with the configuration of task
> ':jruby-with-jar:jrubyJar'.
> > *No value has been specified for property 'mainClass'.*
> -----


This definitely sounds like a bug to me, our integration test coverage of the
library jar is apparently not sufficient :/


>
> To me, the fact that it requires a mainClass seems contrary to what the
> documentation states here http://jruby-gradle.org/jar/#library:
> "A library jar isn???t really much more than a container which includes the
> configured gems and jar dependencies inside of the packaged.jar file."


*nods*


> ** Now, the doubts*
>
> Seems to me that the jar plugin is aimed to make Ruby easy to execute and
> it tries to embedd everything inside a fat jar. It does not take into
> consideration that:
>
> - jRuby can be added in the classpath on runtime. For instance, to be
> able to use different jRuby versions
> - The jar does not need to embedd anything other than it's own java code
> and gems
>
> Are my assumptions corrent?


The self-contained execution mode of the fat jar is intended for this purpose,
the library jar is a usecase I think I'm less qualified to speak to since it's
largely desired by Schalk.


Personally, I don't have a use-case for using a jar as a bucket of Ruby
dependencies and/or jar dependencies. I'd be very interested in hearing more
about your desired use-case and what you're trying to accomplish.



> If they are, using the jar plugin is not useful and we have to rely on the
> base plugin with some small hack. Basically this:
>
> ----
> dependencies {
> // If we use the jar plugin, we could use jrubyJar too (I think)
> gems "rubygems:asciidoctor:1.5.2+"
> gems "rubygems:prawn:$prawnGemVersion"
> }
>
> // Set the files we want to copy from the gems. We don't need all
> def gemFiles = fileTree(jruby.gemInstallDir) {
> include 'specifications/*.gemspec'
> include 'gems/*/lib/**'
> include "gems/*/data/fonts/*"
> }
>
> // copy the required gem files to the resources folder
> jrubyPrepare << { // See PS note
> copy { // bundles the gems inside this artifact
> from gemFiles
> into sourceSets.main.output.resourcesDir
> }
> }
>
> // Add gems processing to ensure gems are included during task 'jar'
> processResources.dependsOn jrubyPrepare
> ----
>
> *What do you think?* *Do you think it makes sense to be able build jars
> like that with the jar plugin or do you think we should rely on the hack?*
> The way I see it, it does make sense. Specialy since the "library()"
> options seems to be for that case. What I miss are the options to:
>
> - Be able to avoid including rubygems:jar-dependencies,
> org.jruby:jruby-complete, org.jruby.mains:jruby-mains as dependencies.
> Seeing the code should not be complicated, the thing is how to do it, I'm
> not sure what's better: a new extension or in the JrubyJar task?
> - Be able to apply file filters on the dependency section to be able to
> get what we do with "getFiles" in the example above. This is really not
> 100% necessary but helps making jars smaller.
>
>
> PS: Also, instead of copying the files we coul add them to the jar, but I
> am not sure what's best. Anyway, that's another subject.
> ----
> jar {
> from gemFiles
> }

I don't entirely see your solution as a hack :) How is this jar that is being
created consumed? I want to make sure I understand as much of the use-case as
possible because I'm having difficulty wrapping my head around it right now



Cheers
- R. Tyler Croy

------------------------------------------------------
Code: <https://github.com/rtyler>
Chatter: <https://twitter.com/agentdero>

% gpg --keyserver keys.gnupg.net --recv-key 3F51E16F
------------------------------------------------------
signature.asc
Reply all
Reply to author
Forward
0 new messages