Last month, I had to develop a Proof-of-Concept web application for a potential customer. Everything went fine, but at the end of the meeting, the customer asked "Surely you will give us the demo so we can play with it further on our own". I was pretty sure of my craft, so I had no problem about bugs and yet I gently refused anyway. Why so? Because I didn’t want to risk that my customer open the WAR and see how I made things happen.
Afterwards, I spent much time thinking how I could have done things differently, so that next time I will be the one to propose to let the demo in my customer’s hands. The following is the result of these thoughts.
This is the solution I choosed on the spur of the moment. It think it has many drawbacks, though.
There are two basic choices for it: either host the webapp on your own infrastructure or host it on a third-party’s. Hosting it on your infrastructure is a good idea, since it will fit your need. However, this requires a competent and willing IT team. Using a third party is tricky since you’re basically giving away both your responsibilities and your ability to do something.
Morevover, depending on where you host your application and your customer’s location, this could have response time issues and thus impact your demo’s image very negatively. Remember this is a POC, so the customer should focus on features, not performance.
Java code can be easily decompiled: I remember there’s a tool in the JDK but I mostly use JAD since my beginnings in the Java world.
Only two things are lost when compiling code: comments and parameter names; class names, method names and attribute names are kept by the compiling process, as well as imports. Thus, decompiling Java code gets you most of the important stuff.
I already used obfuscation some years ago, in order to let contractors use a proprietary framework on site without so much risk to code decompiling with the yGuard product. yGuard let you define your API, which will be kept. All other classes and their associated members will be renamed with gobbledygook such as a, b, string and such in the compiled code. Code obfuscated with yGuard is very hard (but not impossible) to read.
Using obfuscation, whether with yGuard or another tool, has three main disadvantages. First, you’ll have to define your API, meaning you’ll have to manually set one by one all entry points of your application. These entry points are all files that are out of the scope of the obfuscator and that references your classes:
- for standard application, this means the main class
- for web applications, this means servlets
- for Spring applications, this means beans referenced by Spring beans definitions files
Moreover, since the obfuscator only works on Java references, and thus not on Strings, you can kiss all your reflection code good bye. Of course, this is not the case of all applications, but if you think of obfuscating your code in the future, this means a constraint on your design.
Last but not least, most applications are nowadays done through configuration files. I wrote of Spring above, but it also properties files, deployment descriptors, and so on. These files are out of the scope of the obfuscator but they can give some pretty good idea about the code itself. Of course, for Spring files, you can also use annotations, but then, that’s another constraint you have to consider from the start.
And now for something completely different
Sorry for this Monty Python reference… And yet, as seen from the previous possibilities, there truly is a need for something else, off the traditional paths.
The only thing truly satisfying I found so far is Excelsior’s Jet product. It produces an executable (one version for Windows, one for Linux) that is fully self contained. Decompiling such code does take much more effort than decompiling simple Java bytecode. From my point of view, I don’t think that’s impossible (I’ve learned nothing is in computers) but shouldn’t be worth the effort in most cases.
Using JET is a multi-step process done in two applications.
Notice that JET let you create executable from web applications running on a Tomcat as well as standard Java SE or even Eclipse RCP applications!
JET’s features include:
- system properties settings, meaning your executable will already be configured as you need
- choice over the final format of the application: fully contained executable or executable with attached libraries
- integration on the platform: this way, the executable will show information about the application the platform way
- trial version time expiration if the need be
- how your application launches and runs: splash screen, icon and console
- optimization of the application: a dummy run let the compiler see how the application works and do what is needed to improve its performance considering its usage
Once you’ve described your project in the format JET wants, the time is to do the real work: package your application.
Here you can also:
- choose additional components that will make way into your applications, such as the JRE itself. This means your application can really be contained in a fully independent executable!
- detach a subset of the JRE and make it available on a web server of your choosing. This way, you only package what you use but prepare the rest to download if the need be
- choose the packaging format: an installer or the executable itself
The only I found lacking so far is that JET does not provide Maven integration out-of-the-box. Since I do not give my web applications every day, it’s something I can live with…
Having tried the three options (hosting, obfuscating and JET), I am to say I find the latter to be the most powerful tool in my toolbox as of now.
Next time I am faced by a customer asking for my demo, I won’t bang my head against the wall to find the right solution, I will reply "Of course" on the fly, knowing JET will handle it for me.