What would be the most efficient design pattern/coding practice to share services between two web applications, that access resources (properties files for example), without duplicating code in both web applications?
Two web applications running on Tomcat that each read a properties file and some Environment entries in Tomcat's context.xml. This works fine but basically I've only duplicated the code that do the reading into both web applications. Is it good design and/or programming practices to duplicate code like that?
I thought about creating a JAR file that would contain the services (interfaces and implementations for them) and a singleton that would be the entry point to get a hold of the services. I've read and searched and came up with a singleton:
public class PropertyService {
private static volatile ExternalPropertyService eps;
private static volatile SettingsPropertyService sps;
private static volatile AuditPropertyService aps;
private PropertyService () {
}
private static class ServiceHolder {
private static final PropertyService propertyService = new PropertyService();
}
public static PropertyService getInstance() {
return ServiceHolder.propertyService;
}
public ExternalPropertyService getExternalPropertyService() {
ExternalPropertyService tmp = eps;
if (tmp == null) {
synchronized(this) {
tmp = eps;
if (tmp== null) {
tmp = new ExternalPropertyServiceImpl();
eps = tmp;
}
}
}
return tmp;
}
// Rest of the property member accessors omitted
}
Singleton is lazy-loaded (Initialization on demand holder) and the services are also lazy-loaded (Double-checked locking). Basically the singleton is just wrapping the services. Is it needed or even wise to have it? Services read, cache and refresh the values and they are synchronized and thread safe.
If I put this JAR in Tomcat's common folder it would be picked up by the common classloader and made available to both web applications. Both web applications would also use the same singleton as it was found by the common classloader right? Is it thread safe? From what I can gather it should be.
Am I doing something wrong here? Is there a better way of doing this?