I'm looking at an application and it has the following statements
executeProcess("java.exe -cp { 500-characters worth of stuff } someProg");
This is done several times through the program, since this application launches other programs to perform certain tasks. The previous developers decided to just copy and paste again and again as long as it works.
The problems I have with this are
it's redundant. That classpath is copied a dozen times. I can refactor it and move it to a single location, so that's easy to deal with for now and makes life easier for the next guy that might have to maintain this thing.
everytime a program adds a new dependency, I need to update the class path. All of our libraries are stored in a single folder (with subfolders for different libraries), so I can't just use wildcards because they do not check recursively: -cp "path/to/lib/*
Currently I'm the only one maintaining our entire tool set, so if I add a library, I know what to do to make it work, but in general this seems like bad practice.
What are some ways to make these process calls easier to manage?
You can add it as an environment variable and then refer to that, if
that is feasible.
As you already suggested, you can refactor it to a
single location.
I have had good experience with using ant and maven-ant-tasks for launching java applications without managing the classpath manually. Of course, in order to do that you would have to use maven for build/dependency management or at least install your jars to a local nexus instance.
The end user needs to checkout a maven project that declares a list of top level runtime dependencies (transitive dependencies will be resolved automatically, for libraries that are maven projects) that also contains some ant scripts with targets that execute the application.
You will have to figure out how the java application will know the actual location of the ant scripts (an env variable maybe?), but it's an extremely superior solution to manual jar and classpath management.
This might look like a gargantuan task - and it kind of is - but the benefits of transparent jar version and classpath management are so huge, that I cannot even dare to remember how we did it in my current company before setting up the infrastructure for this.
Also, note that apart from installing ant (with maven-ant-tasks) and maven (with nexus configured) everything else you need to launch is on the SCM.
Related
I think it goes without saying that I should be able to use Oracle's own JDK with JavaFX (from gluonhq) to build a distributable jar file that users can just USE.
After an exhaustive search, much reading (24 hours or more over the last few months)and finally this Google search query:
how to make a fat jar -maven -gradle -scala -eclipse -ant -docker -hadoop -netbeans -jerkar -phy -mozni -yogurt -pizza - throwing -python -bacon
I'm absolutely at the end of the road. Why on earth is this so much work? How can I build a JavaFX application and give it to people that want to actually use it without knowing anything else except how to use the application itself?
This has been answered a few times already for Maven and Gradle. Build tools make things way easier than doing it on command line, and not only because of the dependency management.
Since you ask specifically about command line, there is already a full set of instructions documented for it here: https://openjfx.io/openjfx-docs/#modular.
Non modular App
The section Non-Modular from CLI covers JavaFX non-modular projects from command line, and gives you the whole set of instructions to create an old classic fat jar, where all the dependencies, including the JavaFX ones, are bundled all together.
There is a note that warns you not to use this procedure:
Warning: This is a discouraged tedious error-prone manual process that should be avoided by using the Maven's shade plugin or the Gradle's jar task, in case jlink is not applicable.
After you get the fat jar (it can be cross-platform), you can distribute it, and your user will need to have Java installed and run:
java -jar myFat.jar
Modular App
The section Modular from CLI covers JavaFX modular projects from command line, and refers to the use of the jlink command, in terms of distribution, as it creates a custom image that you can send to your users. It is not a fat jar, but it will allow you sending a zip to your user that needs only to be unzipped and run like:
hellofx/bin/java -m hellofx/hellofx.HelloFX
In this case your user won't even need to have Java installed.
And with a little bit of extra work you can also create a batch, so you can run:
hellofx
However, if you still want to do a fat jar with a modular app, you can still apply the exact same instructions from the non-modular apps. In this case, you will probably have to remove the module-info.java file, as it doesn't really makes sense at this point.
Other options
You still have a few more options to distribute your application.
Custom Java+JavaFX image
Another option, covered in the same document, section Custom JDK+JavaFX image, explains how to create your own "JDK" that includes JavaFX. Then you will produce your jar as usual in Java 8 and you will be able to run it with:
/path/to/custom/java -jar myFat.jar
Note that there are already some JDK distributions that bundle JavaFX, like this one.
jpackage
jpackage tool is not there yet, but there is an early access: http://jdk.java.net/jpackage/, that is using Java 13-internal. The exiting documentation explains what are the command line options you need to produce a custom image or an installer.
Note that you can still use JavaFX 11 or 12 with this.
Build tools
And finally, you can still decide to use build tools (Maven or Gradle), that will really help you in many ways. See any of the linked questions above.
I have a java project where I use an external jar (not controlled by me).
Until now whenever that a new version of that library is out, I update
my project to use the more recent one, but now is required that the
project uses different versions of that library.
My problem is I don't have any clue how to do that.
How do I tell in java to make the imports according a version of a jar,
What I need to do:
int versionFlag = getVersion2use();
if(verssionFlag = 0){
use imports from last version
}else if(verssionFlag = 1){
use imports from last version 1
} else if(verssionFlag = 2){
use imports from last version 2
}
This is to be used at runtime!
This is usually something that a project will do at build time rather than dynamically at runtime.
That said, here's a good answer on how to add a jar to the system classloader dynamically at runtime, which is something you could work into your general logic above:
How should I load Jars dynamically at runtime?
With respect to imports, there's no way around the fact that you can't dynamically pick your imports. So if you're lucky the two versions have the same basic API. If that holds, add the jar to classloader as early as possible in your app and then develop like normal.
If the two versions have different a different API, however, then you're going to have to write some very convoluted code that tries building objects and almost ubiquitously catches all the many different class load / class incompatibility exceptions (such as ClassNotFoundException). Worse, you'll probably have to do this behind some sort of facade or factory architecture so that you can actually keep running software insulated from all these class loading shenanigans. In short, if the two have different APIs you may actually be better off writing two separate products.
At Runtime
Classes with the same name in the same package follow a first available rule. The first one that is on the classpath is the one that is used.
You can not easily do what you want at runtime without a wrapper program to move the libraries into and out of the system classpath before the Java application is started.
A launcher script/program that dynamically builds the classpath and only includes the version you need of each library and passes it to java -cp is the only way to do what you want at runtime.
At build time
If it is at build time, then just use something like the shade plugin in Maven to build an uberjar with all the required libraries embedded in a single .jar for each of the versions. So 3 versions would be 3 separate uberjar assemblies.
If you can do it at build time, you can use a dependency manager, like Maven.
It provides you with a means to be able to select which versions of which library you use at build-time.
If you need to do this at runtime, you might need to package all libraries in your project. You can use shading (see here) to make sure you don't get import issues, because when importing different versions of libs you end up with similar imports.
Shading can help you make for example:
com.foo.Class in jarv1
com.foo.Class in jarv2
To become
com.foo.v1.Class in jarv1
com.foo.v2.Class in jarv2
This will make sure your code can still use all libs you want.
I have two computers, and want to share a java project in eclipse by saving and opening the project from my USB stick.
But I can't seem to get it to work very easily.
What steps do I need to take to set this up properly?
These things should be discouraged. My advice is using an SCM (Source Control Management)
like Git and keep a repository on the external drive (if using Git, a bare repository on the USB stick and a local repository on each machine). At the beginning you'll spend quite some time getting used to, but it will pay soon (you'll have descriptive changelogs and disaster recovery facilities)
Eclipse has support for Git via Egit, and for SVN builtin.
When you share a project like this, you may encounter troubles related to classpath references to external JARs, which may be overcome by
using a lib/ folder (thus keeping the JARs under version control)
using an environment variable like $JAVA_LIB
using some dependency manager like Maven or Ivy (again, there are lots of stuff, but will pay even in the short term)
For existing project that you don't want to put under version control, you can simply (again, there may be missing library errors) use the menu File > Import > General > Existing projects into workspace
I strongly recommend using a cvs, svn, or other version control repository for this purpose. Trying to manage it manually is eventually going to bite you.
But if you insist, the best way I know of is to create the project in Eclipse by un-selecting the Use Default Location option in the New Java Project wizard. That allows you to specify an external location for the project contents, in your case the USB drive. You'll have to make sure of a few things:
that the USB drive is always plugged in while Eclipse is running.
Refresh the entire Project each time you move the USB drive from one computer to the other.
Any references to JARs are either internal to the project (eg, in a /lib folder inside the project) or use Classpath Variables.
It's going to be quite tedious, which is why it's always recommended to not try this and use a version control repository instead.
I do this. With some projects I have in SVN or GIT. For me it's more important to have only one eclipse and one workspace. Unfortunately this limits to Windows (or one os). The trick is to ensure that it always has the same drive letter. I tried with subst first, but I forgot to often. But using the drive manager from Windows everything works fine.
I see reference of ant a lot but I don't get exactly what its meant to do? from what i've heard its supposed to compile your projects but can't i just do that by clicking Run->Run in eclipse?
Edit : I guess I should rephrase my question. I already know that ant is a 'build automation software', my question is, what exactly is build automation? I thought that you're supposed to test your app, and when it is running you click the 'build' button in eclipse or through command-line java, and it makes a .jar file out of it? So why do you need to 'automate' this process?
I already know that ant is a 'build automation software', my question is, what exactly is build automation? I thought that you're supposed to test your app, and when it is running you click the 'build' button in eclipse or through command-line java, and it makes a .jar file out of it? So why do you need to 'automate' this process?
Not all the Java development is done through eclipse and not all the jars may be built from the command line ( or should be built from the command line ) .
You may need additionally run test cases, unit tests, and many, many other process.
What ant does, is provide a mechanism to automate all this work ( so you don't have to do it every time ) and perhaps you may invoke this ant script each day at 6 p.m.
For instance, in some projects, a daily build is needed, the following are the task that may be automated with ant, so they can run without human intervention.
Connect to subversion server.
Download/update with the latest version
Compile the application
Run the test cases
Pack the application ( in jar, war, ear, or whatever )
Commit this build binaries to subversion.
Install the application in a remote server
Restart the server
Send an email with the summary of the job.
Of course for other projects this is overkill, but for some others is very helpful.
rogeriopvl is absolutely correct, but to answer your "can't I just do that by clicking Run->Run in Eclipse?" question: that's fine for a project that you're working on on your own, and don't need a repeatable, scriptable build in multiple environments.
If you're working on an open source project, however, or professional software which needs to be able to build on a build server etc, requiring a particular IDE to be running isn't a good idea.
Ant is used to automate a build process, but a build process is often much more than compiling. Ant has "tasks" that can be used to perform miscellaneous useful functions. You can create your own task to do just about anything by writing a java class and telling ant where to find it. You can then mix and match these tasks to create targets that will execute a set of tasks.
You can also set up a dynamic environment in which to build your application. You can set up property files to hold variables that can be used in the build process, i.e. to hold file paths, class paths, etc. This is useful for instance to differentiate between test and production builds where deployment paths, database instances, etc. might change. Ant also includes flow control (if, etc.)
Some things I've seen ant do:
Compile code
Use version control to checkout the latest version or to tag the version being built
Run sql scripts to build or rebuild a test database
Copy files from an external resource for inclusion in a project
Bundle code into a jar, war or ear file
Deploy a web application to an application server
Restart an application server
Execute a test suite
Static analysis, i.e. CheckStyle or PMD
Send email to a team to alert them to a build.
Generate files based on information from the build.
Example: I have a jsp in my app that does nothing but display version/build information. It is generated by ant when I run a build, and the production operations team checks this page when they deploy the application to make sure they've deployed the correct build.
In many larger companies (and likely some smaller ones), you'll find that production code is not built by the people who developed it. Instead, the developers may check their code into a source code repository and tag it. Then they give this tag to a build team.
The build team, in a separate (clean) area - possibly on some headless server (i.e. with no GUI) - will then check out the code and run a build script. The build script will be completely independent of the desktop environment/IDE.
This ensures that nothing which happens to be on any one developer's computer is "polluting" the build. (Or, more likely, nothing outside source control is required for the system to work!)
So most software you use will never, ever be built from a developer's desktop.
PS. You might also want to look at the idea of Continuous Integration
The short answer is that Ant is a great way to create a complete project build that is independent of any particular tool any developer may be using. Without an independent build, things can go haywire quickly - especially for large project teams.
And now for the long answer... I have been brought into several projects without any sense of an independent build. On one project, there was one guy who was not a developer that was tasked with building and deploying the software. He had created 147 separate windows batch files to compile each EJB, each servlet, and each client component. There was no error checking for this build. All log messages, including error messages went to standard out. It was up to him to manually recognize by reading this log which exception or message printed was a normal and which message was an error. He also had to deploy this software he just built. Deploying was equally as complex since there were several load-balanced tiers. Each module had to be placed in the right place manually with options setup to match downstream and upstream tiers. Building and deploying this software took him at least 3 days using this method. Of course, only then could anyone determine if the build "worked". Usually, after this period all the programmers would scramble to debug the build. Programmers would say my module works fine in my IDE. I just click run like this, see?
Indeed, the individual software modules usually worked, but the build and deployment was horribly ineffective. And just as bad, it was equally as difficult for anyone to deploy a build to more than one environment. Management would say, ok you now have this build working in our regression testing environment. Now deploy that same build in this other environment so the sales guys can demo up and coming software. That should be simple to do, but it also took at least 2 days, followed by a "debugging the build" period. Builds and deploys were never simple and never accurate. It really slowed the project down.
Anyway, we replaced this entire procedure with a complete Ant based build and deploy mechanism. The end result was that a complete build could be created and deployed in less than 30 minutes, completely automated. The QA guy managing the builds and deploys could keep a whiteboard of which environment had which build deployed to it and which group was using that environment. This was something that was just not possible with the old system.
Ant is for automating software build processes:
http://en.wikipedia.org/wiki/Apache_Ant
Ant allows CRISP (complete, repeatable, informative, schedulable, portable) builds. You can find great info on it in this presentation by Mike Clark and in his book, Pragmatic Project Automation.
Ant is a build tool, akin to makefiles (albeit with a very different syntax in XML). If you're only using Eclipse it's fine to stick to that and you can always convert an Ant build file into an Eclipse project (Eclipse's launch configurations are then, if I remember correctly, the equivalent of Ant's build targets).
If you want to deploy the source code of the application and allow others to easily build or set it up, automating that using Ant is probably not a bad idea. But it's usually not a consistent experience for users or at least I haven't seen much consensus on what targets should be there and doing what so far.
Ant may also be used for regular automated builds (you wouldn't want to hit Run in Eclipse every night, right? :-))
If there's one close to you I think you'd get a lot out of CITCON, the Continuous Integration and Testing Conference. You get to talk with lots of people about the benefits of automation applied to building and testing software.
Basically people use Ant (with other tools) to automate everything they want to have happen after a commit. The basic advantages of such automation are faster, better and cheaper.
Faster because things happen right away without waiting for a human to get around to it.
Better because computers are really really good at doing the same thing the same way every time. (Humans tend to suck at that.)
Cheaper because you have fewer mistake and the mistakes that occur are caught sooner and therefore cheaper to fix.
You are also referring to the ""Export ant buildfile".
If you write your own Ant script for building your application outside eclipse, you can write your own targets that use the Ant task to delegate to the generated build.xml.
Also, you can configure a project's 'builders' (project properties ยป Builders) to run any script (ant or otherwise) you want when you build the project, manually or automatically.
Joel (Spolsky) has a great article on "The Joel Test." Many of them revolve around being able to do important things often, quickly and reliably. One of those things is your build.
Eclipse is using ant for building, running, deploying, ...
"Ant is a Java-based build tool. In theory, it is kind of like Make, without Make's wrinkles and with the full portability of pure Java code." (from link text
I'd like to set up eclipse with a bunch of plugins and DB connection configurations, etc and re-zip it up so my team-mates and new starters can all be working on the same platform easily.
It seems that installing plugins is fine, but when I add in custom jars (e.g. ivy2, ojdbc, etc) they all save with full, absolute paths which probably dont exist on others machines (particularly if they unzip in a different location to me).
Anyway, I'm hoping that this idea is not silly and am working if this sort of process is documented somewhere or if anyone has any tips in general.
Thanks,
I would recommend against requiring all developers to place eclipse in the same location. There are times when some developers may want to try an alternate version of eclipse to explore a technology that requires a different set of plugins or a different eclipse base version.
Let developers install eclipse where they would like.
However, for jars that you need to run plugins (external dependencies that you need to configure for proper plugin usage):
Hardwire a directory for those jars (as opposed to the entire eclipse dir), like c:\eclipse-helpers or something.
To deal with third-party library dependencies (in the code you're developing), you have a few good choices:
Create project(s) to hold the third-party libs and check them into your source version control system (which you are using, right?). You can then add the libs to the build path(s) of the project(s) - make sure you mark them for export in the "order and export" tab of the build path page. You can then simply add these third-party projects as project dependencies.
Reference the third-party jars as CLASSPATH variables when adding them to the build path of your projects. This allows other developers to store the dependencies in different locations. Perhaps define a CLASSPATH variable (in eclipse's Window->Preferences->Java->Build Path->Classpath Variables) called THIRD_PARTY_JARS; each developer can map it to a different path where they want to hold their deps.
Reference the third-party jars as a "user library" (Window->Preferences->Java->Build Path->User library). This is similar to classpath variables, but acts as an explicit set of jars.
Include the third-party jars directly in your projects. Use this option only if you need the deps in a single location.
Although not exactly in line with the direction of the question, you could use Yoxos OnDemand. It allows you to "roll-your-own" Eclipse distro and download it as a zip. They add in their own perspective where you can add more plugins (direct from their repo), or update the plugins that you have.
Although I've never used the feature, you can make make your own stacks and name them, allowing anyone to go to the site later and download it (with the most up-to-date versions of the plugins). Also, dependencies for plugins are resolved automatically if need be.
In eclipse - in many places it's possible to use workspace relative paths or system environment infos to reference external files, too.
Another option could be to place your jars into a workspace project so that every team member can check it out from cvs/subversion/whatever and start working. Working like this ensures a reproducible environment for server builds or for desktops even after years.
Talking about Yoxos...
it provides "Workspace Provisioning" as well. This means you can attach Eclipse Preferences, checkstyle configurations and Mylyn setups additionally to your list of needed tools/plugins for your IDE to your yoxos profile.
This means your team could share a profile and would be able to start working with the same setup regardless of their OS or whatever. (Its possible to use multiple profiles at once, too.)
We did a similar thing with our development environment (it needed both Eclipse and our own plug-in which, in the early stages, had to run in a known location).
We just put it in c:\eclipse_<projName> and made that a requirement for the team. That's probably the easiest solution for you.
It's your team, you can dictate this as a requirement. Unless your team members are absolute idiots, they'll work with you.
I found Yoxos really good and it does very good work in determining dependencies.
Its really a good tool and worth giving a look.
I just started using git to manage my eclipse install. I did a write-up. The approach might work for you, and it's probably worth looking at.
If developers all don't have the same paths on their machine, instead of adding independent JAR files you could create what Eclipse calls a "library" and include a bunch of jars in that. Then another developer just has to change the location of the library and it'll pick up all the jars in there.