How to run Saxon from command line - java

Can anyone please post detailed, step-by-step instructions how to install Saxon (10 HE) and how to run a transformation from the command line in MacOS (10.13.6)?
I have installed Java on my computer.
I have downloaded the SaxonHE10-6J.zip file from SourceForge.
Based on the recommendation here I have placed the saxon-he-10.6.jar in the myUserName/Library/Java/Extensions folder.
I then opened the Terminal application and entered a command based on this answer:
java -jar saxon-he-10.6.jar -'/Users/myUserName/Documents/path/to/mystylesheet.xsl' -s:'/Users/myUserName/Documents/path/to/some.xml'
This results in:
Unable to access jarfile saxon-he-10.6.jar
All my attempts, including moving the .jar file to the /Library/Java/Extensions directory or including a full path to the .jar file within the command failed with the same error message.
Please note that I am not a Java developer and I do not intend to use this in an application. All I want is to be able to perform an occasional transformation.
I should also note that the locations of my XML and XSLT files may change from one case to another. I would like to be able to keep the .jar file in a constant location and supply the paths to the XML and XSLT files as required - IOW, I want to have a command template where I only need to change the 2 filepaths (and possibly add some options to the transformation).
What do I need to do?

Eventually I got it working. Although these are not exactly the detailed, step-by-step instructions I was hoping for, I will summarize here what I have learned so far. Hopefully this will save someone the hours of frustration I had to go through.
Make sure you have Java installed on your computer. If not, download
from Oracle and install.
Download Saxon from SourceForge. Unzip and place it anywhere on your
hard disk, except:
do not place it in /Library/Java/Extensions or in myUserName/Library/Java/Extensions;
do not place it within a folder whose name contains a / (see below for description).
To initiate a transformation, make your command:
java -jar 'path/to/saxon-he-10.6.jar' -xsl:'path/to/mystylesheet.xsl' -s:'path/to/some.xml'
Alternatively, you can use:
java -cp 'path/to/saxon-he-10.6.jar' net.sf.saxon.Transform -xsl:'path/to/mystylesheet.xsl' -s:'path/to/some.xml'
This form can be also used to run XQuery by changing
net.sf.saxon.Transform to net.sf.saxon.Query.
For adding more options and/or parameters to your command, see the
instructions given here:
https://www.saxonica.com/html/documentation10/using-xsl/commandline/
but do not follow the instructions at the top of the page regarding
the form of the basic command.
Corrections/additions are most welcome.
Description of the problem with folder name containing /:
Put all 3 files (saxon-he-10.6.jar, mystylesheet.xsl and
some.xml in a folder named XML/RSS in my Documents folder;
Ran the following command:
java -jar '/Users/myUserName/Documents/XML:RSS/saxon-he-10.6.jar' -xsl:'/Users/myUserName/Documents/XML:RSS/mystylesheet.xsl' -s:'/Users/myUserName/Documents/XML:RSS/some.xml'
Received the following error:
Error: Could not find or load main class net.sf.saxon.Transform Caused by: java.lang.ClassNotFoundException: net.sf.saxon.Transform
Moved only the .jar file to the parent folder and ran the following
command:
java -jar '/Users/myUserName/Documents/saxon-he-10.6.jar' -xsl:'/Users/myUserName/Documents/XML:RSS/mystylesheet.xsl' -s:'/Users/myUserName/Documents/XML:RSS/some.xml'
Result: successful transformation.
Moved the .jar file back, renamed the folder to XMLRSS and ran the
following command:
java -jar '/Users/myUserName/Documents/XMLRSS/saxon-he-10.6.jar' -xsl:'/Users/myUserName/Documents/XMLRSS/mystylesheet.xsl' -s:'/Users/myUserName/Documents/XMLRSS/some.xml'
Result: successful transformation.

I don't ever use it myself: however myUserName/Library/Java/Extensions is special as far as the classpath is concerned (you don't need to put JAR files in this directory on the classpath), but it's not special as far as the -jar option is concerned - that needs to be an absolute or relative filename in the normal way and has nothing to do with the classpath.
If you've chosen to put the JAR file in this magic location, then I would use the command java net.sf.saxon.Transform options to pick Saxon up from the classpath rather than identifying the -jar location directly.
There are good reasons for NOT putting Saxon in this magic location, however; one reason is it will affect applications that don't actually want to use Saxon (they might be written to use some other XSLT processor, and you might not actually be aware that they use XSLT at all, until they stop working).

Related

Override ClassPath in Bash script to run Java application

I am trying to run a simple Java application in Unix. My Java application read a config file from a directory at run-time. I placed the files in /tmp/paddy/. I created a simple bash script to run a application.
I tried like below and it gives me "no main manifest attribute, in app.jar" error
#!/bin/bash
java -cp ".:./config/*.*" -jar "app.jar" com.test.MainClass
And tried with below command This time my application is running but couldnt find the aconfig file so it throw me NullPointerException - (since it couldnt load the config file)
#!/bin/bash
java -cp app.jar com.test.MainClass
What is the correct way to override classpath in Java -cp command ? I was searching over the internet, but couldnt get any good answers. I dont have any issues running in windows. Only in linux and I am pretty new to the linux environment.
You have four separate issues here.
-jar and -cp don't work together
If you use the -jar switch, the classpath is taken from the Class-Path manifest entry in the jar's manifest, and that is all that will happen - the -cp switch (and the CLASSPATH environment variable) are completely ignored. The solution is to fix your jarfile, which ought to have that classpath entry.
That's not how bash works.
Separate from that issue, your -cp parameter is broken.
*.* in.. linux...? That's late 90s DOS, mate!
It's java doing the parsing of that *, which is unique, because in linux it's normally bash doing it, but that doesn't work here, because bash will be adding spaces, and java needs colons/semicolons, which is why java does it itself. The point is, java is rather limited and only understands a single *. Which bash will mess up. So, there is really only one way to do this.
Single quotes.
One star.
For example:
java -cp '.:./config/*' com.test.MainClass
You don't seem to understand how classpaths work
Each individual entry in a classpath must be either:
A directory which contains classfiles.
A jar file
Note how it specifically cannot be 'a directory that contains jar files', and also cannot be 'a class file'; that is not a thing. The * is the usual treatment: It takes every file in the directory you padded with /* and considers them all to be part of the classpath.
So, if you write: java -cp ., that will not include app.jar. If you write java -cp './config/*', that will not include any class or config files hanging off of ./config (only jar files located there).
That's not how config files work
Including config files on the classpath is not how its done. You can, of course. This doesn't do anything whatsoever, unless you are using SomeClass.class.getResource or some other variant of getResource (those are no good, you should be using SomeClass.class.getResource or SomeClass.class.getResourceAsStream, but I digress), in which case, don't do that. Those aren't intended for config files, those are for static files (files that never change, such as, say, a 'save to cloud' icon for your swing user interface application). If you are doing that, you'd need to include ./config (and not './config/*') in your classpath, but it would be a better idea to fix your code.
config files should be in the user's home directory - System.getProperty("user.home"). You should consider the directory that contains the jar file(s) as the place where the executables live, and those are not necessarily editable by the user, and surely the point of a config file is that you can edit them. Hence why using the classpath for these is not how it is done.

Fiddly thing to do with \bin directory in Eclipse

This has really got me baffled.
In my Eclipse workspace I have a project called "Java scratchpad". In "Package Explorer" you see "src" (Source Folder) under this and then "root" (Package). Under "root" is a .java file called "LoggingTest.java".
So the path to this java file is "G:\My Documents\software projects\workspace\Java scratchpad\src\root\LoggingTest.java".
When I run the following code in Eclipse:
Path currentRelativePath = Paths.get("");
String s_currRelPath = currentRelativePath.toAbsolutePath().toString();
String pathWithForwardSlashes = s_currRelPath.replace( "\\", "/" );
System.out.println( "path " + pathWithForwardSlashes );
The result is
path G:/My Documents/software projects/workspace/Java scratchpad
But... when I am running the same piece of code at the Command Prompt I have to start in the following directory:
G:\My Documents\software projects\workspace\Java scratchpad\bin
... and then go > java root.LoggingTest at the prompt.
The output from the above bit of code is then:
path G:/My Documents/software projects/workspace/Java scratchpad/bin
In other words, when you run the thing at the Command Prompt you are running a .class file under the \bin directory, but when you run in Eclipse, the Eclipse framework "pretends" that the bin directory doesn't exist.
And the upshot is that I get different values for the "current relative path" (CWD) depending on whether I'm running in Eclipse or at the Command Prompt. If I want to make or use a directory relative to the CWD I'm going to get different values depending on whether I'm running in Eclipse or at the Command Prompt.
I'm feeling quite slow tonight. What should I do? Is there a way of detecting whether a project is being run in Eclipse or at the Command Prompt? Or should I simply try to detect whether the path ends in "\bin" and remove those four characters to make the paths equivalent?
later
Just adding a note in reply to the comment from E-Riz:
It's a simple thing: I want to create logs and I want to create Lucene indices... and to keep things in one location (at this stage anyway) I just want to put this output in a location such as ...\Java scratchpad\output\indices\[name of index] or, respectively, ...\Java scratchpad\output\logging\[name of log].
And, yes, of course at present I do know the absolute path involved here... however, as the name suggests, this is a "scratchpad" or test area... so then this code which uses the CWD to determine where to put or find logs or indices can be used more generically, without having to know the absolute paths involved.
But it has to work either in Eclipse or at the command prompt...!
NB my current workaround is indeed to check whether pathWithForwardSlashes ends in "\bin", and if so to delete these last 4 chars. I can't be the only person to have encountered this oddity. Bet there are cleverer solutions!
There's a couple of facts that you should know or keep in mind:
At runtime, Java can (should) be given a classpath to work with; the default application classpath is just . (the current directory where java was invoked from). That's why it seems to you that you must run your program from the \bin directory of your project; because you haven't told the JVM anywhere else to look for classes. You should be setting the runtime classpath when running your application, which can be done a variety of ways but for simple programs is often done via a batch file or shell script. Note that using -cp to specify the classpath will be crucial when you depend on any JARs.
In Eclipse, since applications aren't run via a command-line, Eclipse has Launch Configurations that encapsulate all the details necessary for launching a program (in "run" or "debug" mode). Here's a decent tutorial (although a bit dated; you can find lots more info about Launch Configurations out there on the Interwebs. The key piece of configuration you're looking for is on the Arguments tab, where you can specify the working directory for a program launch config. The default is the project's root directory. See how that's different than when you've been running your on command line? That explains the difference you're seeing in output. You could change the working directory in the Eclipse Launch Configuration, but I tend to prefer to keep it as the project root.
So, you have a couple of options to make things consistent: use a script/batch to run your app on the command-line, specifying -cp so the JVM knows where your class files are (and any other JARs it might need down the road, too); or, reconfigure your Eclipse launch to match where you run from on the command line. I think the (by far) preferable option is the first one.
Having said all that, you should usually not need to do any path manipulation at all when it comes to files/resources in Java. Everything is relative to either the current working directory where Java was run from, or the classpath.

Running a java project in terminal with multiple .java files (multiple attempts described inside)

I have been doing a coding exercise inside the IntelliJ IDEA Community Edition 14 IDE, using OpenJDK.
The project is split over 4 .java files all in the same package.
My end goal is to run this in the terminal/bash (I use System.console().readLine() which doesnt play nicely in the IDE's console).
I've tried navigating to the directory where these 4 files reside (they all reside in the same dir) and tried:
javac -classpath . BibliotecaApp.java Book.java BookManager.java LibraryDB.java
This creates 4 corresponding .class files fine.
The Main is in bibliotecaApp.java/class, so I try run it by:
java BibliotecaApp
But I get the error
Exception in thread "main" java.lang.NoClassDefFoundError: BibliotecaApp (wrong name: com/twu/biblioteca/BibliotecaApp)
Plus about 13 lines of specifics.
Now googling this error seems to be a class path problem, and this is where I get stuck.
From places I've read, usingecho $PATH gives me:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
This is still from the directory of the .java files above.
That path means nothing to me. I have no idea what it is or what it does, or what even a classpath is! Theres alot of resources out there on setting a classpath, but they aren’t helping me because I don't know what it's meant for.
That was a dead end for me. I tried to create a .jar instead using IDEA's Build Artifacts as seen HERE. It created a .jar file but when I navigate to that directory and try run it via:
java -jar biblioteca_jar
I get
Error: Invalid or corrupt jarfile biblioteca_jar
Another issue is that in the file explorer, the file actually comes out as biblioteca.jar, but ls on that dir shows biblioteca_jar. Is that normal?
The code is on my GitHub if that helps anything
https://github.com/botagar/twu-biblioteca-JohnGeddes
Based on your compiler step, change this
java BibliotecaApp
to
java -cp . BibliotecaApp
Which will add the current directory to the classpath for the java runtime environment. See also the Oracle Technote Setting the Class Path.
A jar file is a kind of zip, and should have a .jar extension. So this
java -jar biblioteca_jar
should probably be
java -jar biblioteca.jar
And you can check if the file is valid with any zip archive reader. Including jar itself,
jar tvvf biblioteca.jar
Edit
Based on your comments below,
cd ~/Documents/ThoughtWorks Uni/TWU_Biblioteca-master/src/
and then
java -cp . com.twu.biblioteca.BibliotecaApp

'Java' is not recognized as an internal or external command and program running

This is probably the most frequent question you get in the world, and I apologize, but I have to ask anyway. I recently downloaded the newest version of java (1.7.0_45-b18), and I recently finished making a small program for a local community of mine in Eclipse. I'd like to share it with them so anyone can run it by clicking it, but opening the jar file just hasn't seemed to work for me.
I attempted opening it with command prompt by using
java -jar StatCalc.jar
but it always tells me
'java' is not recognized as an internal or external command, operable program or batch file.
I looked up many solutions for this, the most common being to change your Path. So I went to the environment variables, and changed the path to
C:\Program Files (x86)\Java\jre7\bin\java.exe
But it still gives me the same result. Only when the directory is exactly in java, and the jar file is in the java bin folder can I run the program. I wan't any person to be able to run this.
How do I get command prompt to work and allow this program to be run by both me and other people in this small community?
The path shouldn't contain the executable itself - just the directory containing java.exe. So you want this on your path:
C:\Program Files (x86)\Java\jre7\bin
Restart your console, check that the path is correct (just run path and look at the output) and all should be well.
Note that if you're going to be developing Java code, you should probably use the JDK path instead of the JRE path. For example, my path contains c:\Program Files\Java\jdk1.7.0_17\bin. (Yes, I need to update :)
I hope you do not have changed your PATH variable, only added (...);C:\Program Files (x86)\Java\jre7\bin\ (on UNIX systems, use a colon (:) as the separator instead) at the end. Otherwise, you will have many issues with all other Windows applications. Note that you must add the folder that contains java.exe, not the path to the executable itself.
Then, try to restart your Command-Line or even your Windows session.
Optional: You may set JAVA_HOME to specify JDK location. See this link.
Here you have a tutorial of oracle for setting the path
http://docs.oracle.com/javase/tutorial/essential/environment/paths.html
C:\Program Files (x86)\Java\jre7\bin --> This would be your PATH variable.

7zip command line - Create executable jars

I have an executable .jar-File which works, but I want to add some files to the .jar-File with another program. My idea was to use the 7zip command line extension, but when I try to add something to the .jar-File. I use this command:
7za.exe a -t7z C:\myfiles\thejar.jar C:\filestoadd\* -r
Everytime I try to do this the CMD throws me an error and says:
Error: C:\myfiles\thejar.jar is not supported archive
Well, ok. Then my Idea was to unpack the file thejar.jar, add the files to the directory where the files from thejar.jar were extracted and create a .zip with the extension .jar. When I did this, the file thejar.jar was about 1MB smaller than before with adding files to it. I tried different compression-methods but it was always smaller. When I tried to execute the .jar, an error-message popped up and said Invalid or corrupt jarfile. I already googled my problem, but I haven't got an answer for now... Can you help me?
The simple / recommended solution is to use the jar command that is included in every Java JDK to add the extra files to the JAR.
It is also possible to create a JAR file using JarOutputStream:
How to use JarOutputStream to create a JAR file?
The trouble with using 7zip, or any other "standard" zip utility is that you might accidentally use some modern zipfile feature that the Java utilities don't understand.
You also asked (in comments) if you are permitted to copy the jar.exe and jli.dll from an Oracle JDK / JRE into your own project.
Read the license! We are not lawyers here and we can't give you proper legal advice.
My understanding is that that would be a violation of the Oracle license and copyright. Embedding a full JRE is permitted, but cherry-picking is not permitted.
Consider using OpenJDK instead. The licensing for OpenJDK is GPL based and there are no copyright-based restrictions on redistributing a vanilla distribution. Not even modifying and redistributing it ... so long as you make available source code and build instructions for any changes you make to it1.
Finally, note that this is moot in Java 11 onwards. Oracle now only distributes full JDK's. So that means that if your customer installs "Java" from Oracle, the jar command will be included.
1 - You only have to worry about trademark. Basically, the trademark license says you are not permitted to call a product "Java", etc if it deviates from the "standard" in non-permitted ways. Lookup the details for yourself.
-t7z will create a 7z archive, not a zip. You need -tzip instead.
I know this is an old post but if anyone is searching for info the following works great and makes a jar that will execute correctly, I ran across this post myself looking for info and in the end came up with the following.
For me this method was the easiest way to do what I needed, and just easier and faster then using jar, plus works great as batch file
C:\Progra~1\7-Zip\7z.exe a -tzip -mx9 -spf -r Filename.jar *

Categories

Resources