JarSplice is an application that builds a fat jar, with the main difference being that JarSplice will build invocation scripts and include native resources.
The main weaknesses of JarSplice seems to be its lack of build tool integration, its (apparently) unmaintained status, and its lack of source code availability (even though it’s described as being under the BSD license).
A “fat jar” (or a “shaded jar”) is a jar file that has been bundled with a project’s full set of required resources.
To explain, imagine that we have a Java project called “foo“, that depends on an external project, called “bar.”
For foo to run properly, then, our runtime classpath must contain foo.jar:bar.jar (in some order, although the order can be significant); both files must be present for the classloader to read in order for the project to run.
A “fat jar,” however, includes all of the resources from the classpath in a single jar. The build would extract every class from both foo.jar and bar.jar and built a new jar – named, for example, foo-all.jar – and therefore only this file would be required in order to run the project, since it has every resource that the prior classpath held.
However, this only works for Java resources; it doesn’t include native resources, like LWJGL‘s or SQLite‘s binary components. If foo uses SQLite, then the computer that foo is running on has to have SQLite deployed as a system library in order for foo to run.
This is what JarSplice addresses; it does bundle SQLite or LWJGL resources into the fat jar.
Again, the main weakness of JarSplice is that it’s not integrated into a build tool, so invoking it is an external mechanism for deployment. Development seems to have stopped (the home page says the code is BSD-licensed but no reference to the code exists.) Luis Quesada Torres built a command-line tool, JarSplicePlus; there are forks of that project that seem like there’s some promise for the future.
Feel free to participate and comment.
Author: dreamreal
Getting a usable, non-localhost IP address for a JVM
I recently had a task where I needed to inform a docker image of the host OS’ IP address. (The docker image needed to make an HTTP call to the host machine, for testing purposes.) However, it’s not trivial to find code to actually get a host machine’s IP address. Here’s some code in Kotlin (and in Java) to accomplish the task; I can’t say it’s perfect (and won’t) but it worked for me, and hopefully this can serve as a tentpole for perhaps better code.
There are two pieces of code here; both eliminate the 10.*.*.* network. If you don’t need that network to be eliminated, well, remove that line.
Kotlin
import java.net.NetworkInterface
fun getAddress(): String {
return NetworkInterface.getNetworkInterfaces().toList().flatMap {
it.inetAddresses.toList()
.filter { it.address.size == 4 }
.filter { !it.isLoopbackAddress }
.filter { it.address[0] != 10.toByte() }
.map { it.hostAddress }
}.first()
}
Java
The Java code’s a lot more convoluted, and isn’t helped at all by the requirement for a means by which to convert an Enumeration to a Stream (copied shamelessly from “Iterate an Enumeration in Java 8“, by the way.) However, it’s functionally equivalent to the Kotlin code. If it can’t find a valid address or an internal exception is thrown, a RuntimeException is created and thrown.
private staticStream enumerationAsStream(Enumeration e) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( new Iterator () { public T next() { return e.nextElement(); } public boolean hasNext() { return e.hasMoreElements(); } }, Spliterator.ORDERED), false); } public static String getAddress() { try { Optional address = enumerationAsStream(NetworkInterface.getNetworkInterfaces()) .flatMap(networkInterface -> networkInterface.getInterfaceAddresses().stream() ) .filter(ia -> !ia.getAddress().isLoopbackAddress()) .map(InterfaceAddress::getAddress) .filter(a -> a.getAddress().length == 4) .filter(a -> a.getAddress()[0] != 10) .findFirst(); if (address.isPresent()) { return address.get().getHostAddress(); } else { throw new RuntimeException("Address not accessible"); } } catch (SocketException e) { throw new RuntimeException(e); } }
Summary
This is not perfect code, I wouldn’t think. It was thrown together to fit a specific need, and ideally should have been easily located on StackOverflow or something like that.
Interesting Links – 2017/Jun/12
- picocli, a command-line parser. Apache-licensed; seems similar to JCommander with fewer dependencies.
- 9 Logging Sins in your Java Applications details, well, nine possible logging problems. It’s stuff worth thinking about.
- Five Things You Didn’t Know About… Java Database Connectivity, from IBM developerworks, walks through some things about JDBC that you might not have known. I learned about at least two things that were added since the last time I took a good look at JDBC. (I’m offering no hints about which things they were.)
Interesting Links – 2017/Jun/5
- iciql is a type-safe, model-based wrapper for JDBC… another entry in a fairly large set of libraries designed for that purpose.
- “Cassandra vs. MongoDB” walks through the two datastores, comparing and contrasting.
- DZone published “What Archive Format Should You Use, WAR or JAR?“, suggesting that Docker makes .war files more relevant again.
- Need to extract an HTML page’s main content? Consider Snacktory.
Interesting Links – 2017/May/25
- How Fonts are Fueling the Culture Wars is an article talking about, well, font usage and what specific fonts mean, which has only a tangential relation to Java — but think about it in terms of user experience, too. Do you think the user experience of Java communicates a specific mode of thought? If so, what would it be? (And no, “Duhhhh” is not a valid answer!)
- From DZone: The Soon-to-Be-Hated Object Locator presents a pattern for a type of God Object, except possibly restricted in scope enough to not earn the full derision that a God Object deserves… maybe.
- Also from DZone: The Genius of the Law of Demeter, an article with far less controversy than a God Object would create. The short form of the Law of Demeter says that you call methods on objects that your class owns directly:
this.getFoo().bar()is okay, butthis.getFoo().getBar().baz()is not (and, as usual, there’s more to it than this.) - Stack Overflow: Helping One Million Developers Exit Vim documents the usage patterns for questions that … help developers exit
vim.Vimisn’t especially common for Java developers (although it happens) – but still! What a great editor! How user-friendly does an editor have to be that one in 20000 visits to Stack Overflow is specifically about how to exit the editor? (And now I wonder how many visits are about exiting Emacs, too…) - Java 9 expert group minutes: http://openjdk.java.net/projects/jigsaw/spec/minutes/2017-05-18 – it’s good to keep up on the current status, because the implications of every choice made are pretty serious. The second set of minutes are also available.
- vJUG24 is back! (… I didn’t know what this was until someone sent it to me.)
Interesting Links – 22/May/2017
Interesting Links – 8/May/2017
- Excellent advice for developers who design APIs, no matter who is consuming those APIs: “Building for Builders: Stripe’s 8 Tips for Designing APIs and Supporting Developers“
- Artificial intelligence is everywhere these days. Here’s “Every single Machine Learning course on the internet, ranked by your reviews“
- A cool discrete mathematics library, written in Kotlin: KotlinDiscreteMathToolkit.
- From DZone: Understanding When to Use RabbitMQ or Apache Kafka. Short form: RabbitMQ is for lazy developers; AMQP message queues does most of the work for you at the cost of throughput (which is still high for most projects!), and Kafka does almost none of the work for you but can support much higher throughput. Your humble editor’s advice, earned by experience: if you’ve got the right developers and the time to put into it, Kafka can handle much more throughput than RabbitMQ can, but .. be prepared to make sure you have the right developers and the time to put into it. Otherwise, RabbitMQ (or equivalents) will do fine.
- Druid is a high-performance, column-oriented, distributed data store. Haven’t tried it, it just looked interesting.
- Not Java, but relevant: MP3 licensing has changed! The MP3 format is now available for use by pure open source applications. Woo! Now if we could get JPEG unencumbered in the same way…
DropWizard Metrics Advice
I was working on an application with DropWizard, and I was having trouble getting my own metrics to show up in the display. The Metrics Getting Started is useful, and it actually showed me what I needed, but didn’t make it obvious enough for me.
What I needed was, in DropWizard Metrics parlance, a “meter.” This gives me performance data over time; basically, every time an event happens, I’d mark it and thus be able to see how busy the system was in the last minute, the last five minutes, and the last 15 minutes.
I followed the Metrics Getting Started:
- I got a
MetricsRegistry(by usingnew MetricsRegistry()) - I created a
Meterby callingregister.meter(name)if necessary (and stored theMeterin a map so I could retrieve it again at will) - I marked an event by calling
Meter.mark()
But at no point was I able to see the meter displayed in the DropWizard servlet.
The reason is because I created my own MetricsRegistry. One right way to do it is documented; it’s to use SharedMetricRegistries.getDefault(); instead (which gets you a MetricsRegistry that is displayed automatically).
Note that the DropWizard documentation is not wrong – it just steps past something that most people probably want by default.
Interesting Links – 2017/May/1
- Crafting perfect Java Docker build flow, which addresses the “bare minimum you need to build, test and run my Java application in Docker container.”
- Also relevant: manorrock/maven, a docker container that delivers a specific version of Maven / OpenJDK for Continuous Integration purposes.
- From DZone: Using Java 8? Please Avoid Functional Vomit
- “The Complete Beginners’ Guide to Artificial Intelligence” is a very high-level view of AI. It won’t teach you much about AI if you know much, but it’s a good starting point in case you’re wondering where what you think of AI fits in.
- Another from DZone, appropriate after “LinkedList vs. ArrayList“: Learning Big O Notation With O(n) Complexity
- Not Java-related, but development-related: Teamwork and mental illness in the workplace. Important note: one in four people suffer from mental illness. If you’re in a team of eight, that means that statistically at least two of your coworkers suffer from something that can’t be seen.
If you have a teammate who suffers from mental illness, I’d encourage you to champion (heart and balance) within your team. Be an ally. Help create a safe and inclusive space. Not only because it’s the right thing to do, but because being around people different from you broadens your horizons and builds empathy. And empathy for others makes you better at just about every job.
Interesting Links – 2017/Apr/26
Yes, it’s been a while, I’ve been busy and I’m the only curator of this content:
- Courtesy of The Introduction of Java Memory Leaks, Javosize, the “free next generation java profiler” — and a commercial product, Plumbr (with a free trial available.)
- On
Optional.isEmpty()… – a fascinating email from Dalibor Topic. Great and funny reading. - Courtesy of selckin, Stephen Colebourne has a series on the Java Platform Module System.
- More on Java 9, not much of it complimentary yet: Critical Deficiencies in Jigsaw.
- Our friends at ZeroTurnaround (builders of JRebel) offered a Maven cheatsheet — oddly enough, it uses a really verbose way to set the Maven build version to 1.8, but it’s good.
… and just because I have a weird sense of humor:
randomUser> This code would run really well if it didn't keep waiting for the PRNG to determine the sign of a random number.