Build automation to create a jar file with differences only - java

At my current company we build major releases about twice a year, and throughout the year, when bugs are fixed or new enhancements added, we build service packs to release.
A service pack would basically be a .jar file that is dumped onto the clients machine, and since it is first on the classpath, that is then the code that will execute. (If you do not know what I am talking about - sorry, this might be old school).
The jar file contains only the changed class files and it is normally assembled by hand, by the developer on the job.
I am using hudson for above mentioned steps. If it is possible to specify that hudson to look at two revisions and put the differences between them to a service pack (class files into a sp.jar). This would enable us to automate our deployment of enhancement or bug fixes and it would definitely have added advantage.
If anyone know of such functionality or setup, could you please share your online resources?
Thanks

Using ant script you can achieve the output:
See some tool which can help you.
clirr
java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar
Or JAPICC
japi-compliance-checker OLD.jar NEW.jar
Or PkgDiff
pkgdiff OLD.jar NEW.jar

Related

Why is the java cookbook depending on so many other cookbooks?

I'm trying to run the open-source Java cookbook using chef-solo and although it shouldn't require any other cookbooks, chef keeps saying that a cookbook required to run this one is missing. First it asked me to install apt, then homebrew, then _build_essentials_. It seems like a never ending list of cookbooks. What am I doing wrong?
This is how I'm running the cookbook:
chef-solo -c solo.rb -o recipe[java]
Where solo.rb is a configuration file with the path to the cookbooks folder.
The same thing also happens when I try to run the WAS cookbook.
In short: Chef does not (yet) support conditional dependencies. That's why all cookbooks that provide resources or recipes that might be used need to be declared as dependency.
The Java cookbook uses resources from many other cookbooks to install Java on different systems, e.g., Windows, Linux, MacOS etc. Therefore, it makes use of other cookbooks, that provide resources for e.g. installing a package under Windows, adding an APT repository etc.
In order to allow the cookbook to either include a recipe or use a resource (e.g. apt_repository) from another cookbook, this one has to be specified as dependency so that it is loaded prior to executing the cookbook (e.g. Java). Otherwise, this resource/recipe would not be known to Chef.
So all of these cookbooks will be loaded during the Chef run, but their code will not be executed. While this feels a bit annoying, esp. in your case when you obviously manually download the cookbooks, this isn't so disturbing when you use Berkshelf for dependency resolution. This is highly recommended.

How Do I Install a Jar?

I was reading some documentation for db2jcc4.jar when something caught my attention in the following (emphasis added):
The following command will retrieve the JCC driver version if executed from the command line:
java com.ibm.db2.jcc.DB2Jcc -version
Or for drivers that are not yet installed:
java -cp ./db2jcc.jar com.ibm.db2.jcc.DB2Jcc -version
All I have is the db2jcc4.jar file - it didn't come with an installer or anything. I can run the second command and it works fine, but the first gives me this stack trace:
Exception in thread "main" java.lang.NoClassDefFoundError: com.ibm.db2.jcc.DB2Jcc
Caused by: java.lang.ClassNotFoundException: com.ibm.db2.jcc.DB2Jcc
at java.net.URLClassLoader.findClass(URLClassLoader.java:434)
at java.lang.ClassLoader.loadClassHelper(ClassLoader.java:665)
at java.lang.ClassLoader.loadClass(ClassLoader.java:644)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:358)
at java.lang.ClassLoader.loadClass(ClassLoader.java:627)
Could not find the main class: com.ibm.db2.jcc.DB2Jcc. Program will exit.
This tells me that the jar is not yet installed. In all the time I've worked with Java, I've never heard of installing a jar. How can I make it so that the first command works instead of having this issue and printing a stack trace? How can I install a jar?
It looks to me like the second command includes a flag, -cp, which modifies the classpath. I'm guessing that means that all I need to do is move my jar file into a specific directory. I tried putting it in /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.33.x86_64/jre/lib but that didn't make it so the second command would work. I'm stumped and would appreciate any suggestions for where exactly I need to move this jar for it to be considered installed.
There is no such thing as "installing" a jar. To be used by a Java application, jars have to be accessible in the classpath. Take a look at this link:
http://docs.oracle.com/javase/tutorial/essential/environment/paths.html
By installing the java jar they meant that the jar is available to your program (physically present and found in your class path). If the Path to the jar was not setup then you have to options:
+ copy the jar file to your existing path
+ include the jar file in the command line
java -cp <path_to>/db2jcc.jar com.ibm.db2.jcc.DB2Jcc -version
It looks to me like the second command includes a flag, -cp, which modifies the classpath. I'm guessing that means that all I need to do is move my jar file into a specific directory.
I would say that you need to explicitly include the jar file itself on the classpath. Personally, I generally do not attempt to "install" a jar as you describe, but rather create some sort of script or executable jar file that will facilitate the establishment of the correct classpath.
EDIT: In the context of deploying code to an application server, then "installing" the jar would make sense--typically there's a shared lib folder available on an application server where you can simply drop the jar and the code will become available to all the applications running on the server--this can become a bit of a management headache, however and I often will prefer to have a completely self-contained deployment over sharing jar files between applications--YMMV, however.
You commented thus:
Your link has this comment - (Classes that are part of the JRE, JDK platform, and extensions should be defined through other means, such as the bootstrap class path or the extensions directory.) - How would I go about adding the jar through that?
That is a bad idea, for (at least) the following reasons:
Putting stuff into the extensions directory is going to potentially affect every Java application that you execute. Not just the application that you are trying to "install". In some cases, this may to lead to unexpected breakages due to conflicting versions, etcetera.
When you update the Java installation, the standard installer, RPM or whatever is going to create a new installation tree. But it won't copy anything from the existing installation. So a Java update is likely to break any application that depends on stuff in "extensions".
If you try to solve the above problems by "embedding" a Java installation, you risk losing track of where your Java installations are. This makes applying Java security patches problematic. And of course, embedded JREs take up a lot of disc space ... at ~100Mb a time.
I suspect that "Installing a JAR" is a poorly chosen terminology that likely means placing the jar on the JVM classpath" - i.e. in order to make it available to an application. The recommended ways of doing so vary depending on the Java platform (whether it is a server platform or a client side platform).
For example, on a Java EE server, you could package the jar file within the application, or define it as a shared library, and attach it to the server's classloader or the application's classloader to make it available to that application. Third party applications, such as various IBM products, will come with their own instructions as to how to 'install' a db2jcc4 driver.

How do I run dcm4che tools from command line after compilation?

I want to use the dcm2json tool, part of the dcm4che3 toolkit, but I cannot figure out how to compile and execute the command line tool. Having run
$ git clone https://github.com/dcm4che/dcm4che.git
$ cd dcm4che
$ mvn install
in the dcm4che directory root as outlined in the installation manual, all I get from compilation is a jar dcm4che/dcm4che-tool/dcm4che-tool-dcm2json/target/dcm4che-tool-dcm2json-3.3.5-SNAPSHOT.jar and a class file dcm4che/dcm4che-tool/dcm4che-tool-dcm2json/target/classes/org/dcm4che3/tool/dcm2json/Dcm2Json.class. There is no tool to execute. I can execute the standalone tools downloaded from http://sourceforge.net/projects/dcm4che/files/dcm4che3/3.3.3/ but sadly dcm2json isn't included in this (most recent sourceforge) release.
Does anyone know from where I can download a dcm2json executable or how to compile it? Any help would be really, really appreciated.
(Yes I did Google. A lot.)
dcm4che project has a sub-project called dcm4che-assembly that after running mvn install on the parent dcm4che project, produces a zip that assembles all runnable artifacts, including dcm2json.
If you are curious about how you can get the sh/bat script to run it, then dcm4che-assembly is where you have to look.
In fact, this zip assembly is the same as you download in the binary package.
Hope it helps!
I was also curious about this, so I investigated it some. I don't have a final answer, but I'll post what I've found so far in the hopes that it'll be useful to someone else, and might be the first step to an answer.
It seems that mvn install, after it does its thing, puts a whole bunch of stuff in ~/.m2. The jar files in there don't seem to run as you might expect, and based on the files in the git repo in dcm4che-assembly/src/bin, it seems they need a wrapper to run right. My preliminary toying with the wrappers doesn't seem to work—I get errors like the following:
Error: Could not find or load main class org.dcm4che3.tool.dcm2json.Dcm2Json
These wrapper files really seem to want to be installed somewhere (like /usr/local/bin?), but they do not seem to be.
On the other hand, more recent binaries are now available (currently up through 3.3.7, while git is 3.3.8-SNAPSHOT), and I'm able to use the dcm2json tool available in those. Interestingly, that executable is also a wrapper, nearly identical to the one in git. Further investigation of why it works and the one it git doesn't may lead to an answer of why the dcm4dch3 tools don't magically run after being installed.
And of course the key lies in understanding how the maven framework works.

Java on demand build system

I have a vague memory that I've seen a build system for Java or some other JVM lang which you could run in continous mode (so to speak). This would make the build system run in the background, watching the source dir for changes. As soon as a source file changes, the build system kicks in and re-runs relevant parts of the build process to produce a fresh artifact.
Ring any bells?
Thanks
Is it the gradle daemon?
This keeps gradle running in the background because it has long start up times - and scans the file system to identify when files change.
There are lots of engines that support continual checkouts/building/testing (e.g. Jenkins nee Hudson, CruiseControl, TeamCity etc.).
If you're looking at JVM languages other than Java, then (for example) the Maven Scala plugin supports continuous building and testing upon file changes. e.g.
$ mvn scala:cctest
will run the compile/test cycle in a loop watching for source changes and acting upon them.
If your build tool or language doesn't support this natively, it's trivial to write a shell script to watch a directory structure and execute another script/tool upon change. See this SO question for solutions.
I figured out that it was in fact sbt that I meant. There is another question here on SO relating to how to build Java projects: Use SBT to Build Pure Java Project. Thanks everyone for your help.

Determine unused jars by code coverage?

I have a project with a million jars (well, a lot). They came to me by maven, and I only use a small set of functionality. For cleanness sake, I was wondering with jars I could do without.
My first thought was to run the program with a code-coverage tool, and then find the classes that are touched.
Has anyone done this before? Or are there smarter tricks to achieve the same?
You can run the project using the -verbose:class VM option. This will print for all loaded classes where they are loaded from. Using some smart parsing app/grep/regexp will allow you to filter the jar names into a set of unique entries and tell you which are used.
I think this would be easier because it will automatically tell you if a class is used and if so in which jar.
Of course the problem with this and code coverage is that it will be possible that you delete a jar that is only used in some exceptional case, but your compiler will complain if you deleted one or two too many, leaving you with the (mostly not too complicated) task of finding which jar the class is in.
Possible suggestion when using linux:
java -verbose:class <your startup command here> | grep "\[Loaded" | grep -o "from .*\]" | cut -c 6- | sort | uniq
If you aren't using linux, then save to a file, get a linux machine and run on linux (or use something to run bash commands on windows)
Consider using a tool that already exists, like Dependency Finder or JDepend.
As with all static analysis tools, the use of reflection or DI frameworks can throw this off; I've resorted to custom tools that use this and other inputs to figure things out, although it's still static.
For full runtime usage info you can use Thirler's solution, although whether or not it's complete may depend on which code paths are followed.
You can use Maven Dependency Plugin for analysing your dependency tree. It will also suggest you the dependecies which are downloaded/added to your project because they are dependent to any other jars.
Do run a mvn dependency:tree and see if you are using few unrequired jars.

Categories