I'm trying to embed jruby in a weblogic app to run sass/compass with no luck ;-(
This is what've done so far:
Install sass/compass GEMS:
java -jar jruby-complete-1.7.10.jar -S gem install -i . compass --no-rdoc --no-ri
Create a jar that contains all the gems
jar uf jruby-complete-1.7.10.jar -C sass-compass .
Check that the new jruby-complete-1.7.10.jar contains all the gems:
java -jar jruby-complete-1.7.10.jar -S gem list
*** LOCAL GEMS ***
bouncy-castle-java (1.5.0147)
chunky_png (1.2.9)
compass (0.12.2)
fssm (0.2.10)
jruby-openssl (0.9.3)
json (1.8.0 java)
krypt (0.0.1)
krypt-core (0.0.1 universal-java)
krypt-provider-jdk (0.0.1)
rake (10.1.0)
rdoc (4.0.1)
sass (3.2.14)
So far, so good, I verify that my new uber jruby-complete-1.7.10.jar contains sass and compass gems
Enters weblogic (Weblogic 11 - Oracle 10.3.6)
I create a WebApp with a servlet that uses JRuby to compile sass/compass css and put it inside an EAR
Deploy the ear so the structure is like:
MyEAR
|-APP-INF
| |-classes
| |-lib
| |-jruby-complete-1.7.10.jar <- my jruby jar that contains sass/compass gems
|-META-INF
|-MyWAR
|-META-INF
|-WEB-INF
|-classes
| |-MyServlet.class <- the servlet that compiles sass
|-lib
|-web.xml
When I call the servlet to compile some sass/compass css, I get the following error:
LoadError: no such file to load -- sass/plugin
require at org/jruby/RubyKernel.java:1083
require at classpath:/META-INF/jruby.home/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:55
(root) at :2
In order to compile my sass/compass styles I've to run the following ruby script:
require 'rubygems'
require 'sass/plugin'
require 'sass/engine'
source = '...the scss code....'
engine = Sass::Engine.new(source,{ :syntax => :scss, :compass => {:css_dir => '/styles',:js_dir => '/scripts',images_dir => '/images'} })
result = engine.render
So in my servlet I use jruby like:
ScriptingContainer rubyEngine = new ScriptingContainer(LocalContextScope.CONCURRENT);
String rubyScript = ...
final StringWriter rawScript = new StringWriter();
rawScript.append(rubyScript);
rubyScript.flush();
String compiledCSS = rubyEngine.runScriptlet(theScript)
.toString();
** NO LUCK ** I got the LoadError: no such file to load -- sass/plugin
So I tried to set the LOAD_PATH like:
List<String> paths = new ArrayList<String>();
paths.add("classpath:/gems/sass-3.2.14/lib");
rubyEngine .setLoadPaths(paths);
** NO LUCK EITHER **
¿any idea?
Thanks in advance
The solution as Tom's clue said was putting sass/compass gems path at the LOAD_PATH.
So the script to make sass/compass run under weblogic 10.3.6 was:
sassGemDir = 'D:/compass-gems/gems/sass-3.2.13/lib'
compassGemDir = 'D:/compass-gems/gems/compass-0.12.2/lib'
chunkyPngGemDir = 'D:/compass-gems/gems/chunky_png-1.2.9/lib'
fssmGemDir = 'D:/compass-gems/gems/fssm-0.2.10/lib'
$LOAD_PATH.insert(0,sassGemDir,remoteSassGemDir,compassGemDir,chunkyPngGemDir,fssmGemDir)
require 'rubygems'
require 'sass/plugin'
require 'sass/engine'
source = '...the scss code....'
engine = Sass::Engine.new(source,{ :syntax => :scss,:compass => {:css_dir => '/styles',:js_dir => '/scripts',images_dir => '/images'} })
result = engine.render
NOTE:
Finally I didn't managed to make jruby load sass/compass from a JAR so there's NO need to create an uber-jar that contains jruby-complete and sass/compass (step 2 in my question)
The only change in the ruby-script to run sass/compass from a JAR is:
sassGemDir = 'classpath:/gems/sass-3.2.13/lib'
compassGemDir = 'classpath/compass-0.12.2/lib'
chunkyPngGemDir = 'classpath/gems/chunky_png-1.2.9/lib'
fssmGemDir = 'classpath/gems/fssm-0.2.10/lib'
BUT when I run sass/compass loading from the uber-jar I got two errors:
compass's sprite-importer.rb failed to load sprite_importer.erb file since it was loaded like:
TEMPLATE_FOLDER = File.join(File.expand_path('../', __FILE__), 'sprite_importer')
so I changed sprite-importer.rb to:
TEMPLATE_FOLDER = File.join( File.expand_path(File.join(File.dirname(__FILE__))),'sprite_importer')
and this problem went away
compass's frameworks.rb failed to load the frameworks dir: jruby cannot load a dir's contents when the dir is inside a JAR (I susspect it's an error with java 6 or jrockit, which is the JDK I use in weblogic 10.3.6)
I could not find a solution for this problem so I switched to load sass/compass to be loaded directly from the filesystem and NOT from a JAR file
FINAL NOTE
All the problems with the GEMs LOAD_PATH and compass being loaded from within a JAR were NOT an issue when running inside TOMCAT under Java 7
Hope this helps someone who's trying to run sass/compass using an embeded jruby
Related
I have a basic java app using java.awt Swing UI and I want to create a snap for it so when it's installed there is a launcher available and my UI Launches. I use gradle and the jar task to create a jar which works fine.
Naturally I have in a class that when called loads my app just fine:
package com.foo
class Bar() {
static void main(String... args) { launchUI() }
}
I created a snap folder at the root of the project and a snap.yaml where i followed the instructions on https://snapcraft.io/docs/java-applications so i have a snap yaml that produces a snap file which also installs fine:
name: deepthought
base: core18
version: '0.0.7'
summary: ""
icon: gui/foo.png
description: |
Computes the ultimate answer for life the universe and everything
grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots
# This doesn't work
#apps:
# htmldoc:
# command: desktop-launch $SNAP/bin/foo.sh
## desktop: share/applications/htmldoc.desktop
# plugs: [home, network, x11]
parts:
foopart:
plugin: gradle
source: https://github.com/bsautner/foo.git
source-type: git
gradle-options: [] # suppress running of tests and run the war task
gradle-output-dir: build/libs
I've spent quite some time trying to figure out:
If i create a shell script to run a java -jar foo.jar command it ends up in the /snap directory but it's not on the users path so they can't get to it
I've tried creating launchers but always get an error that my launcher can't be found, if i put it in my root folder as /bin/launch.sh snap can't find it and if i put it in the snap/bin/ folder i also get errors to not put things in the snap folder
When I do install my snap, i don't see where it puts my jar i want to execute, so i can't write a script that does that
I'd really appreciate if anyone can share a working snap.yaml for a java program with a launcher and if there is any mention of a path to something that you note where those files are in relation to the path of the /snap/snap.yaml file
ok figured it out - the docs don't say this but the files are relative to the root of the project so even though the yaml says this is the launch
apps:
cmd3:
command: usr/bin/foo.sh
foo.sh should be in the root of the project and the orginize section here moves it to the bin dir
foo:
plugin: gradle
source-type: local
source: .
build-packages:
- openjdk-11-jdk
stage-packages:
- openjdk-11-jdk
- x11-utils
organize:
${SNAPCRAFT_PART_BUILD}/jg-snap: usr/bin/foo.sh
The jar is in the /snap/foo/current/usr/jar directory
When I use the javapacker command, I get a NoSuchFileException when it should copy the libraries to the app folder. I'm running the following command:
javapackager -deploy -nosign -v -native image -name test
-appclass test.Test
-srcdir "E:\projects\test\target"
-srcfiles test-1.0.jar;lib
-outdir "E:\projects\test\target\dist"
Anything seams to work fine, but i get the NoSuchFileException inside the output and the libraries inside the lib folder are missing (did not get copied).
Running [D:\Java64\jdk-9.0.4\bin\java.exe, -version]
Creating app bundle: test in E:\projects\test\target\dist
"Adding modules: [java.rmi, java.sql, javafx.web, ... long list ...
outputDir = E:\projects\test\target\dist\test\runtime
modulePath = [D:\Java64\jdk-9.0.4\jmods]
addModules = [java.rmi, java.sql, javafx.web, ... long list ...
limitModules = []
excludeFileList = .*\.diz
stripNativeCommands = true
userArguments = {}
Using default package resource [icon] (add package/windows/test.ico to the class path to customize)
Using default package resource [Template for creating executable properties file.] (add package/windows\test.properties to the class path to customize)
Running [D:\Java64\jdk-9.0.4\bin\javapackager.exe, --icon-swap, C:\Users\XXX\AppData\Local\Temp\fxbundler15945263774290817340\windows\test.ico, E:\projects\test\target\dist\test\test.exe]
Icon File Name: C:\Users\XXX\AppData\Local\Temp\fxbundler15945263774290817340\windows\test.ico
Executable File Name: E:\projects\test\target\dist\test\test.exe
Running [D:\Java64\jdk-9.0.4\bin\javapackager.exe, --version-swap, C:\Users\XXX\AppData\Local\Temp\fxbundler15945263774290817340\windows\test.properties, E:\projects\test\target\dist\test\test.exe]
Resource File Name: C:\Users\XXX\AppData\Local\Temp\fxbundler15945263774290817340\windows\test.properties
Executable File Name: E:\projects\test\target\dist\test\test.exe
Exception: java.nio.file.NoSuchFileException: E:\projects\test\target\lib\animal-sniffer-annotations-1.14.jar -> E:\projects\test\target\dist\test\app\lib\animal-sniffer-annotations-1.14.jar
Config files are saved to C:\Users\XXX\AppData\Local\Temp\fxbundler15945263774290817340\windows. Use them to customize package.
Result application bundle: E:\projects\test\target\dist
I don't know what the following line of the output is trying to tell me. The file clearly exists inside my lib folder and the javapackager did find it itself by looking inside the lib folder, that I provided with the -srcfiles test-1.0.jar;lib argument.
Exception: java.nio.file.NoSuchFileException: E:\projects\test\target\lib\animal-sniffer-annotations-1.14.jar -> E:\projects\test\target\dist\test\app\lib\animal-sniffer-annotations-1.14.jar
Any idea why javapacker complains that the file would not exist?
As per https://docs.oracle.com/javase/9/tools/javapackager.htm#JSWOR719,
-srcfiles should be provided with a list of files. lib is a directory. I would try using -srcdir.
Also, if you get
Exception: java.lang.Exception: Error: Modules are not allowed in srcfiles
it means you have to use --module-path, and then set the main module using -m <module name>
I have previously been deploying a java application successfully in Cloud Foundry. However, now the developers have added a shared library compiled from C. I have added the .so to the .zip file (I'm using universal packager and deploying to Cloud Foundry by zip file) and ensured the .so is executable. However, when I deploy I get an error:
2016-12-23T14:39:01.013+00:00 [STG/0] [OUT] -----> Java Buildpack Version: eba4df6 | git://github.com/cloudfoundry/java-buildpack.git#eba4df6
2016-12-23T14:39:01.017+00:00 [STG/0] [ERR] [Buildpack] ERROR Compile failed with exception #<RuntimeError: No container can run this application. Please ensure that you’ve pushed a valid JVM artifact or artifacts using the -p command line argument or path manifest entry. Information about valid JVM artifacts can be found at https://github.com/cloudfoundry/java-buildpack#additional-documentation.
2016-12-23T14:39:01.017+00:00 [STG/0] [ERR] No container can run this application. Please ensure that you’ve pushed a valid JVM artifact or artifacts using the -p command line argument or path manifest entry. Information about valid JVM artifacts can be found at https://github.com/cloudfoundry/java-buildpack#additional-documentation.
2016-12-23T14:39:01.022+00:00 [STG/0] [ERR] Failed to compile droplet
2016-12-23T14:39:01.024+00:00 [STG/0] [OUT] Exit status 223
So my understanding is that I need to created a Custom Buildpack from the Java Buildpack. However, I am getting stuck with the code at this point:
https://github.com/ONSdigital/java-buildpack/blob/master/bin/compile#L28
# Adding crf tagger library
status "Adding crf tagger support"
cp $bp_dir/parsers/src/main/resources/libbackend.so $build_dir/vendor/
# update the PATH
status "Building runtime environment"
mkdir -p $build_dir/.profile.d
echo "export PATH=\"$HOME/bin:\$HOME/vendor/:\$PATH\";" > $build_dir/.profile.d/crftagger.sh
echo "export LD_LIBRARY_PATH=\"\$HOME/vendor/\";" >> $build_dir/.profile.d/crftagger.sh
From what I can gather I only need to modify the compile stage. What do I need to do to copy over the .so and have the Buildpack run successfully.
Please take a look to this https://docs.cloudfoundry.org/devguide/deploy-apps/deploy-app.html#profile
Pre-Runtime Hooks that's you need. I can't give you more details because you haven't provided enough information (project structure, do you have .profile in you root and etc.).
If you need to add shared libs try to use attr_reader :additional_libraries https://github.com/cloudfoundry/java-buildpack/blob/master/docs/extending-droplet.md
I have a maven project which will generate a JAR file, if you build it as Maven Install.
Inside this project, I have a code like this -
public class GameBot extends GameController {
public int botNumber = 1
Static String botName = "Bot1";
...// Rest of the code..
}
I want to create around 150 JAR files from this project with incremented botNumbers. For example - JAR File 1 should contain botNumber = 1 and botName = Bot1
JAR file 2 should contain botNumber = 2 and BotName = Bot2 .. So on till 150.
I used to build each of these manually and now it looks cumbersome to build each time this way. Because, if I make any small change in the code, I have to build all 150 Files again.
Does any one have some suggestions as in Can I automate the process and get all 150 JAR in a folder built for me?
Thanks.
Why dont you externalize the botNumber to a property file and using shell script or batch file create the property file and build the maven project.
Java Code
Properties properties = new Properties();
properties.load(this.getClass().getResourceAsStream("/bottest.properties"));
botNumber = Integer.parseInt(properties.getProperty("botnumber"));
botName = "Bot"+botNumber;
Shell Script
#!/bin/sh
mvn clean;
for i in {1..5}
do
echo "botnumber=$i" > ./src/main/resources/bottest.properties;
mvn install -Dmaven.test.skip;
cp target/bottest-1.0-SNAPSHOT.jar target/bootest$i.jar
done
Batch File
echo off
call mvn clean
for /l %%x in (1, 1, 5) do (
echo botnumber=%%x > .\src\main\resources\bottest.properties
call mvn install -Dmaven.test.skip
copy target\bottest-1.0-SNAPSHOT.jar target\bootest%%x.jar
)
The above example is for 5 times.
I've to "compile" compass files dynamically in my java soft'. So, following explications found on stackoverflow, I've done these steps :
Get JRuby (1.7.3), configure PATH to jruby.jar and binaries (gem, rake ...) and learn to launch ruby script from Java
Get compass and dependancies gems into a local directory, using following command line
gem install -i ./compass compass
=> So I get a directory ./compass/ containing bin, cache,doc, gems & specifications directories.
Put gems in a jar using following command line (think to use a jar name which is not the same as the gems, to avoid JRuby "require" the jar instead of the gems)
jar cf compass-lib.jar -C compass .
Write a test script test.rb in local directory to test my jar. It contains :
require 'compass'
Compass.add_configuration(
{
:project_path => '.',
:sass_path => 'styles/scss',
:css_path => 'styles/css'
},
'custom' # A name for the configuration, can be anything you want
)
Compass.compiler.compile('test.scss', 'test.css')
Execute this script with JRuby, with following command line :
jruby -I . -rcompass-lib.jar test.rb
And get this error ...
Unable to load Sass. Please install it with one of the following commands:
gem install sass --pre
LoadError: no such file to load -- jar:file:C:/jruby-1.7.3/lib/jruby.jar!/gems/s
ass-3.2.8/lib/sass/../sass
require at org/jruby/RubyKernel.java:1027
require at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at jar:file:C:/jruby-1.7.3/lib/jruby.jar!/gems/sass-3.2.8/lib/sass/ver
sion.rb:5
require at org/jruby/RubyKernel.java:1027
(root) at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:1
require at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:36
require at org/jruby/RubyKernel.java:1027
(root) at jar:file:C:/jruby-1.7.3/lib/jruby.jar!/gems/sass-3.2.8/lib/sass.rb:
9
(root) at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:1
require at org/jruby/RubyKernel.java:1027
require at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:60
(root) at jar:file:C:/jruby-1.7.3/lib/jruby.jar!/gems/compass-0.12.2/lib/comp
ass/dependencies.rb:6
each at org/jruby/RubyArray.java:1613
(root) at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:1
require at org/jruby/RubyKernel.java:1027
require at c:/jruby-1.7.3/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at test.rb:1
An idea of the problem and, maybe, of solution ? ;) Thanks by advance.
[UPDATE #1]
After Jörg W Mittag obvious suggestion, the error disapear. Thanks ;) Now, it just don't find the scss file, so it's a "normal problem" ;)
[UPDATE #2]
Having used compass with success in IRB, it's time to transpose the test through Java. So, I wrote some lines in Java to execute my ruby script, using only absolute path to avoid problems in a first time.
InputStream myFile = ISRessources.getFile("C:/Path/To/My/test.rb");
new ScriptingContainer().runScriptlet(myFile, "test.rb");
But ... how to "load" my compass-lib.jar ? What's the equivalent of the -r in JRuby ? I've tried to includ gems into jruby.jar, to add compass-lib.jar in externals jars in java build path, but both don't work, I still have :
LoadError: no such file to load -- compass
require at org/jruby/RubyKernel.java:1027
(root) at test.rb:1
Any idea ?
The error message says:
Unable to load Sass. Please install it with one of the following commands:
gem install sass --pre