Classpath Scanning: Hidden Spring Gems


Class path scanning is not a trivial task in Java. There is no standard way to do it.

Fortunately, Spring framework can help here, as it does in many other aspects. It has an option for implicitly detecting the candidate components by scanning the classpath and matching it against the filters. But all you can do with standard Spring configuration is auto-creation of a  bunch of beans and possbly autowire them to some other bean.

What if you don’t want to create beans, but just want to find specific classes and create their instances later? This can be accomplished by using ClassPathScanningCandidateComponentProvider – class that provides magic behind the Spring’s class path scanning. Using it I created a simple utility class which can be used as a basis for your specific class scaners:


public class ComponentClassScanner extends ClassPathScanningCandidateComponentProvider {

	public ComponentClassScanner() {
		super(false);
	}

	@SuppressWarnings("unchecked")
	public final  Collection getComponentClasses(String basePackage) {
		basePackage = basePackage == null ? "" : basePackage;
		List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>();
		for (BeanDefinition candidate : findCandidateComponents(basePackage)) {
			try {
				Class cls = ClassUtils.resolveClassName(candidate.getBeanClassName(),
						ClassUtils.getDefaultClassLoader());
				classes.add((Class) cls);
			} catch (Throwable ex) {
				ex.printStackTrace();
			}
		}
		return classes;
	}

}

Here the example of specific class scanner to load classes inherited from JComponent and marked with @PreferencePage annotation:


class PreferencePageClassScanner extends ComponentClassScanner {

	public PreferencePageClassScanner() {
		super();
		addIncludeFilter( new AssignableTypeFilter(JComponent.class));
		addIncludeFilter( new AnnotationTypeFilter(PreferencePage.class));
	}

}

Now we have a very powerful tool, which gives us plug in-like abilities. The program can scan the class path for specific services or GUI components and if they are present – load them. Even thaw this solution does not go as far as real plug in framework, it still allows for a greater degree of decoupling in your application.

Advertisements

Minimizing TableModel maintenance


Implementing TableModel in your Swing application is relatively simple.  One of the straight-forward ways to do it was always to use switch statements to return or save data according to row/column number. And this is were the problem is. Every time you need to change default sequence of your columns you have to touch all methods with the switch statements.

The solution I came up with is very simple and is based on Java enums.

Define your columns as enum inside of your table model. This will be the default sequence of your columns. All you have to do now is to convert from column index to enum according to the sequence of enums. After that you can implement your switch statements using enums instead of column index. Going one step farther we can convert enum to column title. This brings us to an idea of class to support such table model implementation. I called it TableColumDefinitionSupport. Here it is.


public final class TableColumnDefinitionSupport {

	public interface ITableColumDefinition {
		String getTitle();
	}

	private TableColumnDefinitionSupport() {}

	public final static > getDefinition( Class cls, int index ) {
		return cls.getEnumConstants()[index];
	}

	public final static > String getTitle(T columnDef) {
		return columnDef instanceof ITableColumDefinition?
                     ((ITableColumDefinition)columnDef).getTitle(): enumToName(columnDef);
	}

	private static > String enumToName(T columnDef) {
		return columnDef == null? null:
		       StringUtils.capitalize( columnDef.name().replace('_', ' ').toLowerCase());
	}

}