Archive

Archive for July, 2010

Managing POM versions

July 26th, 2010 1 comment

This article won’t be long but can be a lifesaver. If you use Maven, how many times did you need to manually update POM versions in an entire modules hierarchy? For me, the answer is: “too many”.

When you project grows to include many Maven modules, releasing a new version can be a nightmare. Sure, you have the maven-release-plugin. It does many things under the cover but in some cases, I saw it fail. What do you do then? You manually change your POM version in your modules hierarchy:

  • the version of the module’s POM
  • the version of the parent’s POM

It’s not only a boring taks, it’s also an error-prone one. Imagine my surprise when I found the maven-version-plugin and its little jewel of a command line:

mvn versions:set -DnewVersion=1.0.1-SNAPSHOT

And presto, the plugin does it all for you, entering each module and changing the previous informations:

[INFO] [versions:set]
[INFO] Searching for local aggregator root...
[INFO] Local aggregation root: D:\workspace\Champion Utilities
[INFO] Processing ch.frankel.champions.license:license
[INFO]     Updating project ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]
[INFO] Processing ch.frankel.champions.license:license-check
[INFO]     Updating parent ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]     Updating project ch.frankel.champions.license:license-check
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]
[INFO] Processing ch.frankel.champions.license:license-common
[INFO]     Updating parent ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]     Updating project ch.frankel.champions.license:license-common
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]
[INFO] Processing ch.frankel.champions.license:license-generation
[INFO]     Updating parent ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]     Updating project ch.frankel.champions.license:license-generation
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT

Give it a try, it’s a real powerful yet easy!

Categories: Java Tags:

Further into CDI

July 13th, 2010 2 comments

In one of my latest articles on CDI, one of the lessons I learned was to use factory methods in order to reduce the number of classes. In this article, I will go into the detail since I think it is of some importance. More basic informations on CDI can be found in some previous posts: overview part 1 and overview part 2.

The naive approach

During school, you were probably taught to create a class for each component. For example, if your application has 4 buttons, North, East, South and West, you’ll have 4 classes. Each class configures its label, its icon and its action, either in the constructor or in some other method.

Note: in CDI, your can annotate such method with @PostConstruct in order for the container to call it just after the constructor.

This produces the following code, when taking Swing as an example:

public class NorthButton extends JButton {

  public NorthButton() {

    // Initializes label
    // Initializes icon
    // Initializes action
  }

  ...
}

Common behaviour and attributes may be factorized into one superclass, thus you end up with 5 classes.

Using the right number of classes is very important in any object-oriented language:

  • If you use too few classes, you run the risk that each class you develop has too many responsabilities and are too big.
  • On the contrary, if you use too much classes, you’ll explode code into many places and it will be a maintenance nightmare. Moreover, in the Sun (Oracle ?) JVM, classes are loaded into the PermGen space which has a fixed size. Who has never seen the dreaded java.lang.OutOfMemoryError: PermGen space?

IMHO, both are good reasons not to create a single class for each instancied component.

The factory approach

The second logical step is to create methods that produce the right instance. In our previous example, that would mean a factory class, with 4 methods to produce buttons, one for each button and probably a 5th method with common behaviour:

public class ComponentFactory {

  @North
  @Produces
  public JButton createJButton() {

    JButton button = new JButton();

    // Set label
    // Set icon
    // Set action

    return button;
  }

  ...
}

Notice that you’ll still need an annotation for each single component:

@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,METHOD,PARAMETER,TYPE})
@Qualifier
public @interface North {}

In our case, that makes @North, @East, @South and @West. If these components are found throughout your application, fine (such as a Cancel button). If not, you still have a class for each component (annotations are transformed into classes at compile-time).

The “generic” annotations approach

CDI let you qualify injection not only from the annotation type but also from some (or all) their elements. We can thus greatly diminish the number of needed annotations. In order to do this, just create an annotation on this model:

@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,METHOD,PARAMETER,TYPE})
@Qualifier public @interface TypeName {

  Class value();

  String name(); }

Now the factory method becomes:

public class ComponentFactory {

  @TypeName(value = JButton.class, name = "North")
  @Produces public JButton createJButton() {

    JButton button = new JButton();

    // Set label
    // Set icon
    // Set action

    return button;
  }

  ...
}

Although this method meets our requirements regarding the number of classes (and annotations), it still has one major drawback: now, it’s the number of methods that is vastly increased. Though not nearly as great a disadvantage as a great number of classes, it makes the code less readable and thus less maintainable.

The fully “generic” approach

CDI let you use an injection point parameter for producer method. This parameter has much information about, guess what… the injection point. Such informations include:

  • the reflection object, depending on injection’s type, respectively Field, Method and Constructor for field, method parameter and constructor parameter injection
  • the required type to inject
  • annotations relative to the injection point

The latter point is what drives what comes next. It means you can annotate your injection point, then get those annotations during producer method execution. In our case, we could have an annotation for each attribute we want to set (text, icon and action). Let’s create such an annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,METHOD,PARAMETER,TYPE})
public @interface Text { String value(); }

Such annotation could be used in the producer method in the following manner:

public class ComponentFactory {
  @Produces
  @TypeName(JButton.class)
  public JButton createJButton(InjectionPoint ip) {

    JButton button = new JButton();

    Annotated annotated = ip.getAnnotated();

    if (annotated.isAnnotationPresent(Text.class)) {

      Text textAnnotation = (Text) annotated.getAnnotation(Text.class);

      String text = textAnnotation.value();

      button.setText(text);
    }

    // Set icon
    // Set action

    return button;
  }
}

Now, the only thing you have to do is annotate your button field like so:

public class Xxx {

  @Inject
  @TypeName(JButton.class)
  @Text("North")
  private JButton northButton;

  ...
}

This will get us a button with “North” as label. And nothing prevents you to do the same with icon and action.

Morevover, with just text, you could go further and manage internationalization:

@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,METHOD,PARAMETER,TYPE})
public @interface Text {

  // Key in the properties file
  String value();

  // Path to the resource bundle
  String resourceBundle() default "path/to/resource/bundle";
}

This annotation could also be reused of other components that manage text, such as labels.

Conclusion

There’s no right or wrong approach in using CDI. However, the latter approach has the merit of being the most powerful. Additionally, it also let you write code relative to a component type in one single place. This is the road I’ve taken so far, and I’m very satisfied with it.

Categories: Java Tags:

Safely give away your demo applications

July 5th, 2010 No comments

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.

Online hosting

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.

Obfuscation

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
  • etc.

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.

JET

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

JetPack II

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…

Conclusion

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.

Categories: Java, Product review Tags: