Tuesday, June 28, 2011

How to Add Jars at Runtime?

Suppose you have the next project structure:

Here is the source code:

package org.halyph.one;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;

import org.halyph.three.MyClassThree;
import org.halyph.two.MyClassTwo;

public class DynamicClassLoader {
 public static void main(String[] args) throws Exception {
  System.out.println("DynamicClassLoader.main()");

  MyClassTwo myClassTwo = new MyClassTwo();
  MyClassThree myClassThree = new MyClassThree();
  myClassTwo.printMessage();
  myClassThree.printMessage();

 }
}

package org.halyph.two;

public class MyClassTwo {
 public void printMessage() {
  System.out.println("MyClassTwo.printMessage()");
 }
}

package org.halyph.three;

public class MyClassThree {
 public void printMessage() {
  System.out.println("MyClassThree.printMessage()");
 }
}

And each of these classes are packed in separate jar:
  • org.halyph.one.DynamicClassLoader - dynone.jar
  • org.halyph.two.MyClassTwo - dyntwo.jar
  • org.halyph.three.MyClassThree - dynthree.jar
To run this application you should put all these jars on classpath,
E.g. the application output
# java -cp dynone.jar;dyntwo.jar;dynthree.jar org.halyph.one.DynamicClassLoader
DynamicClassLoader.main()
MyClassTwo.printMessage()
MyClassThree.printMessage()

But there are some cases when dyntwo.jar and dynthree.jar jars location can be known during runtime only. And we have to run our application in the next way:
# java -cp dynone.jar org.halyph.one.DynamicClassLoader

Of cause, you'll get the next (or similar) error:
# java -cp dynone.jar org.halyph.one.DynamicClassLoader
DynamicClassLoader.main()
Exception in thread "main" java.lang.NoClassDefFoundError: org/halyph/two/MyClassTwo
        at org.halyph.one.DynamicClassLoader.main(DynamicClassLoader.java:28)
Caused by: java.lang.ClassNotFoundException: org.halyph.two.MyClassTwo
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        ... 1 more

So, how can we solve this problem?
Here is the patched org.halyph.one.DynamicClassLoader:
package org.halyph.one;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;

import org.halyph.three.MyClassThree;
import org.halyph.two.MyClassTwo;

public class DynamicClassLoader {

 public static void main(String[] args) throws Exception {
  System.out.println("DynamicClassLoader.main()");

  String[] jars = new String[] { "dyntwo.jar",  "dynthree.jar"};
  addJarsToClasspath(getRootFolder(), jars);
  MyClassTwo myClassTwo = new MyClassTwo();
  MyClassThree myClassThree = new MyClassThree();
  myClassTwo.printMessage();
  myClassThree.printMessage();

 }

 public static void addJarsToClasspath(String rootFolder, String[] jarNames)
   throws SecurityException, NoSuchMethodException,
   MalformedURLException, IllegalArgumentException,
   IllegalAccessException, InvocationTargetException {

  Method addURL = URLClassLoader.class.getDeclaredMethod("addURL",
    new Class[] { URL.class });
  addURL.setAccessible(true); // you're telling the JVM to override the
         // default visibility

  File[] files = new File[jarNames.length];
  int i = 0;
  for (String jarName : jarNames) {
   files[i++] = new File(rootFolder + jarName);
  }

  // returning the jars to add
  ClassLoader cl = ClassLoader.getSystemClassLoader();
  for (i = 0; i < files.length; i++) {
   URL url = files[i].toURL();
   addURL.invoke(cl, new Object[] { url });
  }
 }

 public static String getRootFolder() {
  String result = null;
  try {
   String qualifiedClassName = DynamicClassLoader.class.getName();

   Class qc = Class.forName(qualifiedClassName);
   CodeSource source = qc.getProtectionDomain().getCodeSource();
   if (source != null) {
    URL location = source.getLocation();
    File file = new File(location.toURI());

    result = file.getParent() + "/";
   } else {
    System.out.println(qualifiedClassName + " : "
      + "unknown source");
   }
  } catch (Exception e) {
   System.err.println("Unable to locate class on command line.");
   e.printStackTrace();
  }
  return result;
 }

}

Here is the output of patched application:

# java -cp dynone.jar org.halyph.one.DynamicClassLoader
DynamicClassLoader.main()
MyClassTwo.printMessage()
MyClassThree.printMessage()

So, two additional methods were added to support this "magic":
  • public static String getRootFolder()- this method simply identifies the folder where dynone.jar (on behalf of org.halyph.one.DynamicClassLoader class) is located. Because for this demo we put all application-related jars in one folder
  • public static void addJarsToClasspath(String rootFolder, String[] jarNames) - and here the "magic" happen. Based on this post on www.velocityreviews.com forums:
There is a well-known hack for dynamically extending the class path.
It generally works, and we use it in production releases of our software. It uses reflection, plus the knowledge that the default ClassLoader *is* a URLClassLoader.
...
As I said, this is a hack, undocumented, and subject to change at any
time. Indeed, there's no guarantee that extant JREs use a URLClassLoader as a default class loader. Moreover, it only works if your program doesn't have a security manager (it probably doesn't), or your code is trusted.
...
We've never seen problems with it, although our software is used on a plethora of different boxes and OSs.
It works for me and I hope it will be useful for you as well.
Happy hacking!

Monday, June 20, 2011

@Override Java Annotation Issue

Let's create one simple interface and class which implements this interface:

public interface IOverride {
    void doSomething();
}
public class Overridden implements IOverride {
    @Override
    public void doSomething() {
    }
}

And compile this stuff on JDK v.1.5:
# javac -d classes src\*.java
src\Overridden.java:2: method does not override a method from its superclass
        @Override
         ^
1 error

Let's try to do the same on JDK v.1.6 - And, You've got no compilation error.
Between Java 5 and Java 6 changes to the specification of @Override have been made. In Java 6 it is possible to add the @Override annotation to methods that implement methods of an interface which is not allowed in Java 5. (http://dertompson.com/2008/01/25/override-specification-changes-in-java-6/)

Also, I've found very interesting discussion on Stackoverflow: http://stackoverflow.com/questions/94361/when-do-you-use-javas-override-annotation-and-why:

Q:
What are the best practices for using Java's @Override annotation and why?
It seems like it would be overkill to mark every single overridden method with the @Override annotation. Are there certain programming situations that call for using the @Override and others that should never use the @Override?

A:
Use it every time you override a method for two benefits. Do it so that you can take advantage of the compiler checking to make sure you actually are overriding a method when you think you are. This way, if you make a common mistake of misspelling a method name or not correctly matching the parameters, you will be warned that you method does not actually override as you think it does. Secondly, it makes your code easier to understand because it is more obvious when methods are overwritten.

Additionally, in Java 1.6 you can use it to mark when a method implements an interface for the same benefits. I think it would be better to have a separate annotation (like @Implements), but it's better than nothing.

Sunday, June 12, 2011

ITEvent 2011, Local Conference – Report

Yesterday (June 11, 2011) I attended the local (Ivano-Frankivsk, Ukraine) IT related conference “itEvent 2011”. I must say I am impressed. There were more than a hundred participants. And it’s amazing. We live in a very small city and this local event/conference waked up so many developers to attend this event.

The conference had three parallel flows/stages. And it’s a good sign. The organizers give us a chance to choose the most preferable topic(s) to attend. Additional good point is that each presentation was shot on video. So, I could see missed interesting topics.

Here is the talks (which I saw and hear) overview:

1. “Two sides of IT interview” by Nataliya Mukhitdunova. To tell the truth I wasn’t expected that such boring subject can be presented in such interesting way. Just wow. The speaker was concentrated on two interview stakeholders: HR and Developer. She clearly defined their goals and expectations, tips for HRs (as interviewer) and for Developers (as interviewee). And this speech was so easy made and “light” that I felt “I’m in right place in right time”. The presenter doesn’t use any slides or other supportive material, she was just well prepared with good background in this area.

2. “Kanban and the creation of the high effective teams” by Sergiy Fitsak and Anatoliy Okhotnikov. I’ve expected to hear some advices, case studies (especially BAD experience) and of cause the process implementation issues. And I’ve got all these. Thanks to the presenters. The one “minus” was that this talk wasn’t well coordinated between two presenters and they overused the presentation’s time limit. They hadn't predicted that they got so many questions and discussions. I can say that this talk really revived the audience. And it was cool.

3. “Facebook as a mobile application platform” by Yevgen Vershynin. The presenter showed us from the very begging what the Facebook platform is and how to use it. This area was absolutely new for me. Additionally, he was well prepared and his speech was very dynamic. And, even more, he showed some passion during the speech. That’s why it was so interest. I must admit that Yevgen (the presenter) showed very high presentation, communication skills, and good domain knowledge. Very impressive.

4. “How to meet customer expectations” by Ruslan Seredyuk. This topic was absolutely new for me. I mean I’ve never thought about “customer expectations” and “what is the successful project”. I like to discover something new. The presenter showed real knowledge which is based on work experience. And it’s very important. Every single case in his presentation had small life sample, which was very useful to demonstrate the all dark places in this mess area (i.e. customer expectations). Again, the presenter was well prepared with real case studies. The one "minus" is that the target audience wasn’t mentioned. And this topic wasn’t dedicated for the junior developers, IMHO.


Now, let’s talk about conference organizations:

Pros:

1. There were a lot of coffee, cakes and water.

2. The registration was straightforward.

3. The atmosphere was VERY friendly.

4. The presentations' quality was good.

5. And the most important, the itEvent organizer overdid their own expectation, they gathered huge amount of IT related people in one place and gave them a chance to talk to each other and share personal knowledge, vision and contacts. As for me, the goal was perfectly achieved.


Cons:

1. I think that Conference, Camp or similar event should have some motto.

2. It’s good to have agenda for every presentation/speech in English as well

3. It’s good to have target audience for every presentation/speech. It’s even more important in multi-target conference (here we can see management, technical and usability directions, etc.)

4. The conference’s web resource is in Ukrainian only. It’s good to have English as well. Also, the web resource structure could be improved.

So, the overall impression is good. This local conference exceeded my expectations. I hope we’ll have the similar event next year.

Monday, June 06, 2011

Top 15 Java Web Resources

Here is the top 15 Java-related resources I'd like to share with you.

Blogs, News aggregator
1.  http://www.dzone.com is a very big aggregator for news, articles, video interviews, tutorials, reviews, and announcements. Also, you can use some particular, dedicated "zones":

http://java.dzone.com - Javalobby
IDEs and Tools:
http://eclipse.dzone.com
http://jetbrains.dzone.com
http://netbeans.dzone.com

This resource contains huge amount of information and you could easily lost there (50-80 new items per day). So, I suggest to use Javalobby as a start point.
2. http://www.infoq.com  News, videos, interviews, conference reports, etc.
3. http://www.java.net Articles, blogs, wiki, news.

Forums and Q&A
4. http://www.javaranch.com is one of the biggest Java forum
5. http://stackoverflow.com it's one of the biggest Q&A site which includes such features as Q&A, forum, wiki, blog, collaboration and community based content moderation.

Videos
6. http://www.java-tv.com Java-TV.com is a directory of videos, interviews and tutorials focused on software development activities with the Java™ programming language.
7. http://www.softdevtube.com SoftDevTube is a repository of videos, interviews and tutorials focused on all software development activities.

Cookbooks
8. http://www.discursive.com/book/322 Common Java Cookbook
This collection provides expert tips for using Java-based utilities from projects such as Apache Commons, Apache Lucene, and Apache Velocity. You don't have to be an expert, the book's solution-based format contains code examples for a wide variety of web, XML, network, testing, and application projects. If you want to learn how to combine common open-source Java utilities to create powerful Java applications and tools, the Common Java Cookbook is for you.
9. http://mindprod.com/jgloss/jgloss.html Canadian Mind Products Java & Internet Glossary
10. http://www.javapractices.com/home/HomeAction.do Collected Java Practices. It offers concise presentations of Java practices, tasks, and designs, illustrated with syntax-highlighted code examples.
11. http://www.leepoint.net/notes-java/index.html Java Notes.
These Java programming notes are written to fill in missing or weak topics in textbooks the Author has taught from.
12. http://www.javamex.com Javamex is the author attempt to gather together information on some of the more intricate aspects of Java programming, building on the experience with the language.
13. http://www.exampledepot.com This site holds all the examples from The Java Developers Almanac and more. Copy and paste these examples directly into your applications. Over a thousand useful examples can be found there.

Other
14. http://javatoolbox.com JavaToolbox.com references the tools you need for Java development.
15. http://www.blackbeltfactory.com On-line community-based exam system

Wednesday, June 01, 2011

How to choose between Scala and Clojure?

vs.

I think it's very popular question nowadays. The Java-haters produce so many buzz around this. So, want you or not, but You passively have been trying to choose the Java.next().

I've found several interesting posts which cover pretty much about this subject:
by Stephan Schmidt
by Lau B. Jensen

 Others
Hint: Try to read comments to these posts, there are very interesting discussions. Some of them are even more useful than the actual post(s)/article(s).

These articles don't give you any advices or strong opinions which language is the best. But, it's a good start point, for sure.