
February 20, 2009 09:27 by
Simon
I had some code which was used to translate from a business entity to a data transfer object, I wanted to put this code in a library to re-use it across multiple projects. The initial version of the translator was made up of the main translator which implements the singleton pattern and an abstract "entity" translator, subclasses of which are then written for each translation required e.g. Entity A -> DTO B. In the constructor of the main (singleton) translator a list of entity translators was created so that when the translate method is called, this list can be searched to determine whether a translator exists to perform the translation. Moving the translator to a library meant that the ceation of this list could no longer be harcoded and the solution to this was to use the service provider model facilitated by the ServiceLoader class in Java.
The entity translator abstract class was as follows:
public abstract class EntityTranslator {
...
/**
* Translates from a bean to an entity.
* @param value the bean to translate.
* @return the entity.
*/
public abstract TEntity translateToEntity(TBean value) throws EntityTranslatorException;
/**
* Translates from an entity to a bean.
* @param em the entity manager.
* @param value the entity to translate.
* @return the bean.
*/
public abstract TBean translateFromEntity(TEntity value) throws EntityTranslatorException;
}
The Translator class then uses the ServiceLoader to search for all implementations of the EntityTranslator class and adds them to the list.
...
import java.util.ServiceLoader;
...
public final class Translator {
private static Translator singleton = null;
private List> translators = new ArrayList>();;
private Translator() {
registerTranslators();
}
/**
* Adds all of the translators available.
*/
private void registerTranslators() {
@SuppressWarnings("unchecked")
final ServiceLoader loader = ServiceLoader.load(EntityTranslator.class);
for (EntityTranslator translator : loader) {
if (translator != null) {
translators.add(translator);
}
}
}
...
}
The final thing to do is to create a META-INF/services directory in the jar file that you are using the library in. This must contain a file with the fully qualified name of the abstract class (or interface) beingimplemented (e.g. com.sharpcoder.library.EntityTranslator) and then in that file must be a line with the fully qualified name of each class that extneds the abstract class (e.g. com.sharpcoder.project.CompanyTranslator.
15865274-00d3-49f4-bf6f-ff2e8d07e3de|1|5.0