Java

19 posts

Writing RPM files … in plain Java

Now creating an RPM file is easy. There are a lot of tutorials out there on how write a SPEC file and build your RPM. Even when you are using Maven … with the exception that when you are on Windows or Mac OS X, the Maven RPM plugin will still try to invoke rpmbuild in order to actually build the RPM file. The maven bundle simply creates a SPEC file, layout out the payload data and lets rpmbuild do the processing.

My task now was to make it possible for Eclipse NeoSCADA to create configuration RPMs directly from inside the Eclipse IDE (running in Java), without the need to have rpmbuild on a Windows platform. Since I did write an RPM reader for Package Drone before, I did know a bit about the RPM file format. So this shouldn’t be a big deal?! … How naive ;-)

Continue reading

Java 8 streaming – or not?

One of the most advertised use cases of the new lambdas in Java 8 is the possibility to stream collections and transform it. The “series of tubes” has a lot of examples on how to do this, I just wanted to look at it from a different perspective, readability.

So starting with a real-life problem of a map Map<ResultKey, List> result which I want to transform into a Set<String>.

Before Java 8, I had something like:

[code language=”java”]
Set<String> ids = new HashSet<> ();
for ( List<ResultEntry> list : result.values () ) {
for ( ResultEntry entry : list ) {
if ( entry.getAction () == Action.DELETE ) {
String id = entry.getArtifact ().getId ();
ids.add ( id );
}
}
}
[/code]

Now, with Java 8, I can do:

[code language=”java”]
Set<String> deleteSet = result.values ().stream ()
.flatMap ( list -> list.stream () )
.filter ( entry -> entry.getAction () == Action.DELETE )
.map ( entry -> entry.getArtifact ().getId () )
.collect ( Collectors.toSet () );
context.deleteArtifacts ( deleteSet );
[/code]

Neither one is shorter nor seems less complex from an initial view. So, which one is better?

Maven Tycho/JGit based build timestamps and the “target” directory

Now when you build OSGi bundles using Maven Tycho, you probably ran into the issue of creating a meaningful version qualifier (remember, an OSGi versions always is major.minor.micro.qualifier, so no dash and definitely no -SNAPSHOT).

There are a few approaches ranging from fully manual assignment of the build qualifier, simple timestamps and timestamps based on the last Git change.

The background

The latter one is described in the “Reproducible Version Qualifiers” wiki page of Tycho as a recipe to create the same qualifier from the same source code revision.

Actually the idea is pretty simple, so instead of the current timestamp, the last relevant change in the git repository, for the directory of the bundle, is located and then used to generate the timestamp based qualifier.

As a side note: Personally I came to the conclusion, that this sounds great in the beginning, but turns out to be troublesome later. First if all, the Build Qualifier plugin conflicts with the Source Ref Plugin, which generates a different manifest. Both plugins find different last commits and therefore a different MANIFEST.MF gets generated. So two builds produce two bundles, with the same qualifier, but actually (due to the MANIFEST.MF) different content, with two different checksums, which causes issues later on and has to be cleaned up by some baseline repository matching. In addition you simple cannot guarantee that two different builds come to the same result. Too many components (actually Maven and the local host) are outside of the source code repository and still influence the output of the build. But this post is about the JGit based timestamps ;-)

A simple configuration using the Git based approach looks like this in the parent pom file:
[code language=”xml”]
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<version>${tycho.version}</version>
<dependencies>
<dependency>
<groupId>org.eclipse.tycho.extras</groupId>
<artifactId>tycho-buildtimestamp-jgit</artifactId>
<version>${tycho-extras.version}</version>
</dependency>
</dependencies>
<configuration>
<timestampProvider>jgit</timestampProvider>
<jgit.ignore>
pom.xml
</jgit.ignore>
</configuration>
</plugin>
[/code]

As you can see, there is a configuration property jgit.ignore which allows to exclude a set of files in the search of the last relevant commit. So git changes, which are only changing files which are ignored, are also ignored in this search for the last modification timestamp. Since the pom.xml will probably just get changed to point to a different parent POM, this seems like a good idea.

The problem

Now what does happen happen, when there are uncommitted changes in the working tree? Then it would not be possible for the build to determine the last relevant commit, since the change is not committed! Maven Tycho does provide a way to handle this (aka “Dirty working tree behaviour”) and will allow you to ignore this. Which might not be a good idea after all. The default behavior is to simply error and fail the build.

For me it became a real annoyance when it complained about the “target” directory itself. The truth is, this output directory should be added to the “.gitignore” file anyway, which would then also be respected by the git based build timestamp provider. But then again it should not fail the build just because of that.

Solution

But the solution to that was rather trivial. The jgit.ignore property follows the git ignore syntax and also allows to specify directories:

[code language=”xml”]
<jgit.ignore>
pom.xml
target/
</jgit.ignore>
[/code]

There are two things which have to be kept in mind: each entry goes to a new line, the root of the evaluation seems no the be the root of the project, so using “/target/” (compared to “target/“) does not work.

Programmatically adding a host key with JSch

This article explains how to programmatically add a host key in Java with JSch. I did update the article early 2018, taking care of the missing argument to the add method.

Every now and then you stumble over an issue which seems easy in the beginning, but turns out to be something out of the ordinary.

For example establishing an SSH connection to a Linux server using Java. Of course there is the JSch library, which is also in Eclipse Orbit. So this sounds like an ideal solution when developing with OSGi.

However pretty soon I ran into the case that I did not want to write all host keys into my “known_hosts” file, but would like to provide the host key to each new connection which is being created. And while JSch can do a lot of things, all sample projects somehow assume you are writing a Swing application, with full user interface, re-using all existing SSH options and configuration files.

But I did want to create a server side solution, embedded in OSGi, which allows to store the username, password and hostkey in a server side data store which can then be used to establish the connection.

So initially I got an “com.jcraft.jsch.JSchException: UnknownHostKey” exception. Not very helpful since it only contains a string with the key’s fingerprint instead of the full key. Asking Google for help brings up few solutions like this one on Stackoverflow.

However simply disabling the host key check was not an option. And is not a good idea in most cases.

Gladly JSch allows to programmatically add host keys. Although the approach is rather undocumented. At least it seems that way.

Creating a new Jsch instance allows to specify the location of the host keys, but also allows to add them manually:

String keyString = "....";

// parse the key
byte [] key = Base64.getDecoder().decode ( keyString ); // Java 8 Base64 - or any other

JSch jsch = new JSch ();
HostKey hostKey = new HostKey ( info.getHostname (), key );

// add the host key
jsch.getHostKeyRepository ().add ( hostKey, null );

Basically this does the trick. The only question is, what exactly is they “keyString”. It is not the fingerprint from the exception and it is not the full line from your known hosts file, just the last segment.

So for example if your “known_hosts” entry is:

|1|DvS0JwyQni+Jqoht2n8BSYQjze4=|zHORICsezHdR1nIYhqsOxrgnUe4= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwht8wWW+cqmGJa5KrgfgydvlgHxSmlV+8oSUINSm8ix+wG87jQHz56MeaFf0F3IvxiivfvIUxBGlb05CZC1rCTfinvS7H1ktDIwVUK3gv+SGNYtGGwWbtg+oMXAevpV5pMTvDS7Ue6OUnSXGDbAxcqXBA+ApKCG5oizhyrtzOrU=

Then the “keyString” is:

AAAAB3NzaC1yc2EAAAABIwAAAIEAwht8wWW+cqmGJa5KrgfgydvlgHxSmlV+8oSUINSm8ix+wG87jQHz56MeaFf0F3IvxiivfvIUxBGlb05CZC1rCTfinvS7H1ktDIwVUK3gv+SGNYtGGwWbtg+oMXAevpV5pMTvDS7Ue6OUnSXGDbAxcqXBA+ApKCG5oizhyrtzOrU=

Problem solved ;-)

Update

After I received a few comments which asked for a missing parameter of the add method (the original blog post only had one argument) I did re-check and also noticed a (second) required argument. I am not sure if I missed this in the original post or if the API has evolved over time. So I did check out what this parameter is about and updated the blog post accordingly.

The second argument is an instance of UserInfo and it if safe to pass in null. UserInfo is a callback type interface which the caller can provide in order to pass on questions from the Jsch code to the end user. In this particular case the JSch method might ask if the parent directories of the host file should be created if they don’t already exists. At the time of writing it seems safe to pass in null if they do exist.

If you can’t be sure that they exist, then you could create them yourself before calling the add method. Or create a bogus “yes” implementation of UserInfo. Manually ensuring that the directories do exist seems the better way to me as otherwise you wouldn’t really know to which question you would actually answer “yes” with your implementation of UserInfo.

If you pass in null and the directories do no exist, then the host key will not be added and the add method will silently fail.

Access to WMI in Java using Eclipse SWT OLE integration

Today I ran into a problem which could easily solved using a short WMI query. The problem was that the query must be executed within a Java UI application. Googling for a solution I came only up with either quite some ugly workarounds (like generating a VBScript fragment, forking off the VBScript runtime and parsing the result) or some full blown COM/DCOM interfaces (like J-Integra or J-Interop). Although I really like J-Interop (we are using it for DCOM when accessing OPC server in OpenSCADA Utgard) it has some drawbacks. For J-Interop every access (even local access) is a network based access. Since J-Interop only supports DCOM it is free of any platform specific code but required the machine to be accessible using “remoting” functionality (DCOM). Since I wanted to query the WMI from a UI application and I am sure that the WMI query will stay on the Win32 version of the application I was not keen on adding “remoting” as a requirement to the UI application.

After some digging I remembered that SWT brings an OLE interface which provides direct COM access. So I started poking around and finally come up with a solution that works quite well.

For the impatient: The full source code is available from github https://github.com/ctron/wmisample and the screenshot is here.

Continue reading

Workaround for LoadTimeWeaver issue with JBoss 6 and Spring 3

A possible workaround for the LTW issue that appeared in JBoss 6 using Spring 3 (SPR-7887) is to add an empty jboss-scanning.xml file to EAR and WAR files.

The reason to this issue as explained by one comment that JBoss pre-loads classes when scanning for annotations. Which triggers the class loader before Spring has a chance to add the AspectJ transformer to the class loader. The LTW support of Spring loads fine but after all classes are loaded.

Adding the empty jboss-scanning.xml to EAR and WAR files will skip the scanning for the modules and trigger the transformer later.

Example for jboss-scanning.xml:

[sourcecode language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>

<scanning xmlns="urn:jboss:scanning:1.0">
</scanning>
[/sourcecode]

Thanks to Marius Bogoevici and Costin Leau for looking into this issue.

Combo viewer requirements

Today I tried to create a combo viewer in Eclipse with a different approach than the it seems the widgets was designed. I have an object which has to main properties an ID and a descriptive name. While this is nothing unusual following requirements seems to be:

The list of the combo box should show the label while the text input field of the combo box should show the id of the object. Using Eclipse Databinding this seems to be an impossible task (if you know a way please post it at stackoverflow). Continue reading

Equinox Remote Terminal Console

Although Equinox offers some sort of remote TCP console it is not what you actually want to have. Being limited to one session, having not authentication and allowing the user to execute any command and shut down the OSGi container is not an option for a productive system.

In OpenSCADA we faced the same problem so we simply developed an OSGi Remote Console based on Apache Mina.

Our equinox console works around the limits of the original OSGi TCP console and can simply be dropped in as a replacement.

SVN Link to the project: http://pubsvn.inavare.net/openscada/modules/aurora/trunk/org.openscada.osgi.equinox.console/

Also we played a little bit with an IRC bot that exposes the OSGi console of Equinox to an IRC server. This is not really tested and just a proof of concept. But it works. If you like check out http://pubsvn.inavare.net/openscada/modules/aurora/trunk/org.openscada.osgi.equinox.ircbot/ and play with it ;-)