How to create symlink in rpm to files provided by external rpms? - java

I'm trying to package two symlinks to corresponding jars provided by external dep1.rpm and dep2.rpm. These are declared as dependencies in my-app-extra.spec:
Requires: dep1
Requires: dep2
I have my %install symlinking their jars (%dep1jar, %dep2jar):
%install
%{__install} -d -m 0755 $RPM_BUILD_ROOT%{_javadir}
%{__install} -d -m 0755 $RPM_BUILD_ROOT%{_javadir}/%{my_app}
pushd $RPM_BUILD_ROOT%{_javadir}/%{my_app}
for jar in %dep1jar %dep2jar
do
ln -sf ../"${jar}" "${jar}"
done
popd
but the rpmbuild fails with:
ERROR: link target doesn't exist (neither in build root nor in installed system):
/usr/share/java/my-app/dep1.jar -> /usr/share/java/dep1.jar
Add the package providing the target to neededforbuild and Requires
// same error for dep2.jar
error: Bad exit status from /var/tmp/rpm-tmp.31253 (%install)
Is there any way to circumvent this rpmbuild check?
Background
I have a java application that (optionally) requires two external libraries to provide extended functionality. To install these libraries, I have created dep1.rpm and dep2.rpm that store the jars under %_datadir/java and an additional my-app-extra rpm that should symlink those under %_datadir/java/my-app (following some apparently established java-packaging conventions under linux).
But I'm failing to find how to force rpmbuild to build this rpm without declaring the external libraries as BuidRequires and having them installed first.
What I want
This is in summary what I'm after (simplified, as the complete solution involves versioning):
/usr/share/java/dep1.jar (from dep1.rpm)
/usr/share/java/dep2.jar (from dep2.rpm)
/usr/share/java/my-app/dep1.jar -> ../dep1.jar (from my-app-extended.rpm)
/usr/share/java/my-app/dep2.jar -> ../dep2.jar (from my-app-extended.rpm)
Note: I'm now exploring the possibilities of rpm subpackages, but I somehow expect this to be possible without subpackaging.

I could make it work 'touching' the targets and excluding them from the files. In my-app-extra.spec:
%install
%{__install} -d -m 0755 $RPM_BUILD_ROOT%{_javadir}
%{__install} -d -m 0755 $RPM_BUILD_ROOT%{_javadir}/%{my_app}
pushd $RPM_BUILD_ROOT%{_javadir}/%{my_app}
for jar in %{dep1jar} %{dep2jar}
do
# touch! rpmbuild aborts the build if symlink targets missing!
touch ../"${jar}"
ln -sf ../"${jar}" "${jar}"
done
popd
# more stuff ...
%files
# ...
# Exclude dummy (touched) files!
%exclude %{_javadir}/%{dep1jar}
%exclude %{_javadir}/%{dep2jar}
%{_javadir}/%{my_app}/%{dep1jar}
%{_javadir}/%{my_app}/%{dep2jar}

Related

jpackage creates 2 copies of JRE

I use jpackage (with JDK 14) for creating a standalone JavaFX application.
The output of jpackage looks strange, it consists of two the same copies of JRE and all files in app folder, except App.cfg file, can be deleted without any problem.
Does jpackage can do not generate unnecessary files?
What I have:
I have a simple project created from Maven archetype org.openjfx:javafx-archetype-simple:0.0.3.
And I just added maven-shade-plugin for creating jar with dependencies and a simple launching class for it (like NewMain class here).
I do:
mvn package
mvn javafx:jlink
jpackage --package-type app-image --dest targetApp --name App --runtime-image target/image --main-jar testApp-1.0-SNAPSHOT.jar --input target
As result I have two folders with JRE (absolutely the same ones):
targetApp\App\runtime
targetApp\App\app\image
And all files (and folders) (JRE (~53 MB), Jar (~9 MB), classes...) in targetApp\App\app can be safely deleted, except App.cfg file.
After deleting these files I run targetApp\App\App.exe and it works fine.
The deleting reduces the size of App from 118 to 56 MB.
An additional question: I use Windows and jpackage generates the result for Windows (a lot of dll files and exe), do I can create a standalone application in Windows for Mac and Linux?
You get this result because you already created an uber-jar which contains everything in addition to what you specified via --input target which, according to the documentation, has the following effect.
All files in the input directory will be packaged into the
application image.
Try whether it works to just remove the option --input target or don't create the uber-jar. Instead use the maven-dependency-plugin to copy all dependencies into a single folder, say target/libs, and then explicitly specify --input target/libs.
Your second question:
You cannot cross-create applications for other targets, if that is your question.
You might want to check out the JPackageScriptFX project on GitHub. It contains a sample multi-module maven project structure and build scripts for Mac and Windows that will build all available package types and executables for both platforms. You can find it here: https://github.com/dlemmermann/JPackageScriptFX
My solution without Oracle's jpackage: AdoptOpenJDK + jpackager + macOS => .pkg, .dmg
Download AdoptOpenJDK_13. Unzip and put into /Library/Java/JavaVirtualMachines/adoptopenjdk-13.jdk
Download jpackager for (in my case osx) from https://mail.openjdk.java.net/pipermail/openjfx-dev/2018-September/022500.html. Unzip.
Copy jdk.packager.jar and jpackager to the /Library/Java/JavaVirtualMachines/adoptopenjdk-13.jdk/Contents/Home/bin (!!!)
In /yourworkspace/target should be the programA.jar file. (In my case it is a small program created with OpenJFX + openjdk13)
The /yourworkspace/jlink denotes on your JRE with bin,lib etc. you might have created via jlink. (In my case I have my custom JRE + JavaFX modules)
The /yourworkspace/icons contains .icns .
create jpackager.command file in your workspace with the content:
#! /bin/bash
ABSPATH=$(cd "$(dirname "$0")"; pwd -P)
launcher=`ls $ABSPATH/target/*.jar`
for eachfile in $launcher
do
if [ -f "$eachfile" ];then
echo Creating .pkg ...
echo "$eachfile"
basename="${eachfile##*/}"
/Library/Java/JavaVirtualMachines/adoptopenjdk-13.jdk/Contents/Home/bin/jpackager \
create-installer \
--runtime-image $ABSPATH/jlink \
--name ProgramA \
--input $ABSPATH/target \
--main-jar $basename \
--version 1.0 \
--copyright "Nikita Gromov 2020" \
--name "ProgramA-macos" \
--mac-bundle-name "ProgramA" \
--output $ABSPATH/appimage \
--icon $ABSPATH/icons/20200220101822955_easyicon_net_32.icns
fi
done
Double click on jpackager.command which is located in /yourworkspace and wait until the jpackager has created ProgramA-macos-1.0.pkg and ProgramA-macos-1.0.dmg under /yourworkspace/appimage
My solution without Oracle's jpackage: AdoptOpenJDK + jpackager + Windows => .msi
Install WiX (!!!) Important step.
Download AdoptOpenJDK_11. Will be installed under C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot
Download jpackager (in this case win) from https://mail.openjdk.java.net/pipermail/openjfx-dev/2018-September/022500.html. Unzip.
Copy jdk.packager.jar and jpackager to the C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot\bin (!!!)
In /yourworkspace/target should be the programA.jar file. (In my case it is a small program created with OpenJFX + openjdk11)
The /yourworkspace/jlink denotes on your JRE with bin,lib etc. you might have created via jlink. (In my case I have my custom JRE + JavaFX modules)
The /yourworkspace/icons contains .icns .
create jpackager.bat file in your /yourworkspace folder with the content:
set openjdk=C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot\bin
set saveto=%cd%
cd %openjdk%
jpackager create-installer --runtime-image %saveto%/jlink --input %saveto%/target --main-jar ProgramA.jar --version 1.0 --copyright "Nikita Gromov" --name "ProgramA-win" --output %saveto%/appimage --icon %saveto%/icons/icon.ico --win-menu --win-shortcut --win-dir-chooser
Note The ProgramA.jar should be in /yourworkspace/target path (!!!)
Double click on jpackager.bat which is located in /yourworkspace and wait until the jpackager has created ProgramA-win-1.0.msi under /yourworkspace/appimage
Custom JRE + JavaFX mods on Windows
Create /yourworkspace/jlink.bat file. The content of it should be:
SET openjdk=C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot\bin
SET fx=C:\Programme\AdoptOpenJDK\javafx-jmods-11.0.2
set saveto=%cd%
cd %openjdk%
jlink --module-path %fx% --add-modules=javafx.base --add-modules=javafx.controls --add-modules=javafx.fxml --add-modules=javafx.graphics --add-modules=javafx.web --add-modules=javafx.media --add-modules=javafx.swing --bind-services --output "%saveto%\jlink"
This creates the /yourworkspace/jlink folder with a custom JRE+JavaFX libraries which you will link to jpackager.

Eclipse cannot find module even the module path is explicitly provided

I have created a module com.company.ep that is located in the source folder com.company.ep. (Yes, I have removed src from the build path and deleted it!) Inside the source folder, I have a couple of packages as the following:
com.company.ep <--- root source folder
com.company.ep.main <--- package 1
com.company.ep.model <--- package 2
com.company.ep.view <--- package 3
// ... more packages
module-info.java
The main class is located in the package com.company.ep.main.Main. In my module-info.java, I have configured the dependencies:
module com.company.ep {
exports com.company.ep.main;
exports com.company.ep.model;
exports com.company.ep.view;
// ... more exports
requires javafx.controls;
requires javafx.graphics;
}
When I tried to launch my program, eclipse told me that:
Error occurred during initialization of boot layer
java.lang.module.FindException: Module javafx.controls not found, required by com.company.ep
So, I tried to run it on the command prompt:
java -p d:\Applications\openjfx-sdk-11\lib;bin -m com.company.ep/com.company.ep.main.Main
bin is the output folder of eclipse, and it worked.
So, I went to Properties → Run/Debug Settings → Main → Show Command Line, it showed:
D:\Applications\openjdk-11.0.1\bin\javaw.exe -Dfile.encoding=UTF-8 -p "D:\Development\Eclipse-Workspace\MyProject\bin" -classpath "D:\Applications\openjfx-sdk-11\lib\javafx.base.jar;D:\Applications\openjfx-sdk-11\lib\javafx.controls.jar;D:\Applications\openjfx-sdk-11\lib\javafx.fxml.jar;D:\Applications\openjfx-sdk-11\lib\javafx.graphics.jar;D:\Applications\openjfx-sdk-11\lib\javafx.media.jar;D:\Applications\openjfx-sdk-11\lib\javafx.swing.jar;D:\Applications\openjfx-sdk-11\lib\javafx.web.jar;D:\Applications\openjfx-sdk-11\lib\javafx-swt.jar" -m com.company.ep/com.company.ep.main.Main
I have created a user library with all JARs added, and the library is added to the project's Modulepath.
Then I have tried to set the module path explicitly in VM arguments in Run/Debug Settings: -p D:\Applications\openjfx-sdk-11\lib, I'd still no luck.
My questions are:
Why javaw.exe?
Why classpath? As my library is added as a module-path entry.
How to configure the module dependencies in eclipse.
I am not sure if I have configured eclipse correctly, or whether it is probably a problem of OpenJDK as it worked when I worked on another computer with Oracle Java SE installed.
Thank you!
The explanation of why Eclipse fails on running your modular project can be found in the OpenJFX docs for Eclipse (modular from IDE section).
As it was already mentioned:
Being a modular project, and since we already added the JavaFX SDK library to the module-path, there is no need to add any VM arguments.
But if you run on Eclipse you will get the mentioned error:
Error occurred during initialization of boot layer
java.lang.module.FindException: Module javafx.graphics not found, required by hellofx
So why is it failing??
As explained in the docs:
This exception happens because the Eclipse ant task overrides the module-path
How does this happen??
Checking the command line applied (Show Command Line from Run Configurations...), you can find out why:
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 \
-p bin/hellofx \
-classpath $PATH_TO_FX \
-m hellofx/org.openjfx.MainApp
If you copy it and paste it and run it in a terminal, it will fail of course with the same message. The reason is that Eclipse doesn't add the JavaFX library to the module path.
If the task generates the wrong arguments, let's try to fix it by adding our own VM arguments by editing Run configurations... and adding -p $PATH_TO_FX:bin/hellofx.
But if you run it, it will fail again.
Let's check why, with Show Command Line from Run Configurations...
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 \
-p $PATH_TO_FX:bin/hellofx \
-p bin/hellofx \
-classpath $PATH_TO_FX \
-m hellofx/org.openjfx.MainApp
As you can see, the user's VM arguments are added before the default ant task arguments, so there are two -p (--module-path) options, and the first one (the user's one with the JavaFX jars) is overridden by the second one (only the project's module), so, again, the JavaFX jars are not added to the module path, and hence you get the error.
So how can we fix it??
As mentioned in the linked documentation, the possible fix is:
To prevent this issue click on Run -> Run Configurations... -> Java Application -> Dependencies, select Override Dependencies... and add -p /path-to/javafx-sdk-11/lib:bin/hellofx, and press Override.
With this solution, you can see it works, and you can check the command line:
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 \
-p $PATH_TO_FX:bin/hellofx \
-p bin/hellofx \
-classpath $PATH_TO_FX \
-p /path-to/javafx-sdk-11/lib:bin/hellofx \
-m hellofx/org.openjfx.MainApp
Basically we are adding again the "right" module path option, after all the failed ones.
While now the project runs, the solution is obviously not nice.
Here you can find a sample referred from the OpenJFX documentation.
EDIT
Based on #kleopatra comments, another workaround to make it work is the following:
For some reason, the library JavaFX11 (that contains modular jars) is not scanned and Eclipse doesn't include those jars into its -p option, but into the classpath:
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 \
-p bin/hellofx \
-classpath $PATH_TO_FX \
...
But, if you add those jars directly to the module path, it will do add them, and this will run fine:
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 \
-p bin/hellofx:$PATH_TO_FX/javafx.base.jar:...:$PATH_TO_FX/javafx.controls \
...
Then with this there is no more need to override the dependencies.
EDIT 2
As #mipa points out in a comment, there was a bug filed on this issue, and it has already been solved. I've tested it with Eclipse 2018-12 M2 (4.10.0M2) Build id: 20181108-1653, and it works with the JavaFX11 library only (as it should):
$JAVA_HOME/bin/java -Dfile.encoding=UTF-8 \
-p bin/hellofx:$PATH_TO_FX/javafx.base.jar:... \
-m hellofx/org.openjfx.MainApp

Why is my docker CI image not reproducible / running everywhere

I have a Dockerfile for doing CI.
It uses the contents of a third party tarball which in-turn includes parts of Java Runtime (yes its ugly).
$ git clone xxx
$ cd xxx
$ docker build .
During execution the Dockerfile on ONE host requires ".../jre/.../server/libjvm.so" and executed on ANOTHER host requires ".../jre/.../client/libjvm.so" from that tarball.
The Docker version is everywhere 1.7.1
Nothing is ADDED to the container besides the git repo folder (./) and the tarball.
How is this possible?
Are there any shared environment variables implicitly passed to docker?
This is how the Dockerfile looks like:
FROM ubuntu:14.04
...
WORKDIR /
RUN wget http://SOME-URL TOOL-PACKAGE
RUN tar xf TOOL-PACKAGE
...
# setup some envs
ENV
# extend PATH
ENV PATH $PATH: ...
...
COPY ./ src
WORKDIR src
# use tool to generate some input files
RUN SOME-TOOL-BINARY-WHICH-USES-JRE
# continue build with make
RUN make
When you have the possibility to modify the java execution in your build process you could pass the -client or -server parameter explicitly to choose whether the client or server JVM should be used.
For details you could have a look at this other stackoverflow question.

jRuby gem in a jar generates directory instead of jar

I'm using jruby and have been putting my gems in a jar like this
java -jar jruby_complete.jar -S gem install -i gem_jar.jar nokogiri erubis
This creates a jar "file" and correctly installs the gems. I can add this jar "file" to my search path and my project will run, however when I go to do a distribution build in netbeans, it complains about the gem_jar being a directory.
A .jar is just a zipped directory, or so I thought, so I ran
zip gem_jar.zip gem_jar; mv gem_jar.jar gem_jar.old; mv gem_jar.zip gem_jar.jar
Netbeans no longer complains, but the project won't run. How have I failed at coercing my gem jar into an actual compressed jar file?
The issue is that the -i flag on jruby is not creating a jar. That was a false assumption on my part. The correct method is this
java -jar jruby_complete.jar -S gem install -i gem_jar nokogiri erubis
jar cf gem_jar.jar -C gem_jar .

How can I validate CSS on internal web pages?

I want to check internal web pages, so I cannot use the W3C validation service directly. I managed to run the XHTML validator locally, however, I have some problems with the css-validator. I do not really want to setup Tomcat or Jigsaw in order to be able to run Java servlet, and the commandline option gives me an error message
Exception in thread "main" java.lang.NoClassDefFoundError:
org.w3c.tools.resources.ProtocolException at
org.w3c.css.css.CssValidator.main(CssValidator.java:164)
How can I validate local CSS on a Linux box?
That jar is runnable, but it needs some extra libraries.
Examine the MANIFEST.MF file:
$ unzip -p css-validator.jar META-INF/MANIFEST.MF
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.0
Created-By: 1.6.0_26-b03 (Sun Microsystems Inc.)
Main-Class: org.w3c.css.css.CssValidator
Class-Path: . lib/commons-collections-3.2.1.jar lib/commons-lang-2.6.j
ar lib/jigsaw.jar lib/tagsoup-1.2.jar lib/velocity-1.7.jar lib/xerces
Impl.jar lib/xml-apis.jar lib/htmlparser-1.3.1.jar
You need all the jars mentioned in Class-Path. You can download them from the maven repository using this script:
#!/bin/bash
set -e
mkdir -p lib
curl -LO http://www.w3.org/QA/Tools/css-validator/css-validator.jar
echo "\
http://repo1.maven.org/maven2/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
http://repo1.maven.org/maven2/commons-lang/commons-lang/2.6/commons-lang-2.6.jar
http://repo1.maven.org/maven2/org/w3c/jigsaw/jigsaw/2.2.6/jigsaw-2.2.6.jar jigsaw.jar
http://repo1.maven.org/maven2/org/ccil/cowan/tagsoup/tagsoup/1.2/tagsoup-1.2.jar
http://repo1.maven.org/maven2/org/apache/velocity/velocity/1.7/velocity-1.7.jar
http://repo1.maven.org/maven2/xerces/xercesImpl/2.11.0/xercesImpl-2.11.0.jar xercesImpl.jar
http://repo1.maven.org/maven2/nu/validator/htmlparser/htmlparser/1.2.1/htmlparser-1.2.1.jar\
" | while read url shortname; do
if [ -z "$shortname" ]; then
shortname="${url##*/}"
fi
curl -L -o "lib/${shortname}" "${url}"
done
After doing that, it works:
$ java -jar css-validator.jar --output=soap12 file:badcss.html
{vextwarning=false, output=soap12, lang=en, warning=2, medium=all, profile=css3}
<?xml version='1.0' encoding="utf-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<m:cssvalidationresponse
env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
xmlns:m="http://www.w3.org/2005/07/css-validator">
<m:uri>file:badcss.html</m:uri>
<m:checkedby>http://jigsaw.w3.org/css-validator/</m:checkedby>
<m:csslevel>css3</m:csslevel>
<m:date>2013-03-12T06:40:09Z</m:date>
<m:validity>false</m:validity>
<m:result>
<m:errors xml:lang="en">
<m:errorcount>1</m:errorcount>
<m:errorlist>
<m:uri>file:badcss.html</m:uri>
<m:error>
<m:line>8</m:line>
<m:errortype>parse-error</m:errortype>
<m:context> h1 </m:context>
<m:errorsubtype>
exp
</m:errorsubtype>
<m:skippedstring>
100%
</m:skippedstring>
<m:message>
Property fnt-size doesn't exist :
</m:message>
</m:error>
</m:errorlist>
</m:errors>
<m:warnings xml:lang="en">
<m:warningcount>1</m:warningcount>
<m:warninglist>
<m:uri>file:badcss.html</m:uri>
<m:warning>
<m:line>5</m:line>
<m:level>0</m:level>
<m:message>You should add a 'type' attribute with a value of 'text/css' to the 'style' element</m:message>
</m:warning>
</m:warninglist>
</m:warnings>
</m:result>
</m:cssvalidationresponse>
</env:Body>
</env:Envelope>
You can invoke the W3C validator from the command line:
Command-Line use
Any computer with Java installed can
also run the validator from the
terminal/console as a commandline
tool. Download the css-validator.jar
jar archive (or build it with ant jar)
and run it as :
java -jar css-validator.jar http://www.w3.org/
Note : the css-validator.jar file must
be located at the exact same level as
the lib/ folder to work properly.
Update: To get it to work, I checked out the full distribution from CVS and ran ant using the included build.xml. It downloaded all dependencies except for servlet.jar. To deal with that, I downloaded the binary distribution of Tomcat 6 and extracted it. Then, I edited the build.xml for css-validator to reflect the location of servlet.lib:
<property name="servlet.lib"
value="E:/Downloads/apache-tomcat-6.0.20/lib/servlet-api.jar"/>
Then ran ant again. This produced the css-validator.jar file in the top level of the directory checked out from CVS with the lib subdirectory containing the other jars it depends on. Then, I was able to run the validator successfully:
C:\Temp\validator\2002\css-validator> java -jar css-validator.jar http://www.unur.com/
For the lazy, here's a script I wrote to do what Sinan suggests:
#!/bin/sh
# W3C CSS Validator Install Script --------------
# installs W3C CSS Validator
# requires: ant, wget, javac
# see: http://jigsaw.w3.org/css-validator/DOWNLOAD.html
# see: http://esw.w3.org/CssValidator
# see: http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/
# see: http://stackoverflow.com/a/3303298/357774
##wget "http://www.w3.org/QA/Tools/css-validator/css-validator.jar"
#sudo aptitude install -y ant # uncomment if you don't have ant
CVSROOT=:pserver:anonymous:anonymous#dev.w3.org:/sources/public cvs checkout 2002/css-validator
mkdir 2002/css-validator/lib
TOMCAT6_VERSION='6.0.45'
wget "http://www.apache.org/dist/tomcat/tomcat-6/v$TOMCAT6_VERSION/bin/apache-tomcat-$TOMCAT6_VERSION.tar.gz"
tar xvf apache-tomcat-$TOMCAT6_VERSION.tar.gz
mv apache-tomcat-$TOMCAT6_VERSION/lib/servlet-api.jar 2002/css-validator/lib/servlet.jar
rm -rf apache-tomcat-$TOMCAT6_VERSION apache-tomcat-$TOMCAT6_VERSION.tar.gz
cd 2002/css-validator
ant jar
# usage example: java -jar css-validator.jar "http://csszengarden.com/"
That should work, at least until the next software dependency update breaks the ant build script (feel free to parameterize versions).
Hope this helps!
You can now use the new Linux command line tool htmlval for checking HTML and CSS. It should definitely work for validating local CSS on a Linux box.
Note: I'm the developer.

Categories