It is not possible to achieve what you wish to do in a supported way because that class was not build to be public extension point.
However, if you really want to extend it and keep all the functionality inherited from the parent class then you need to do quite a few things:
- Create a class that extends
JPADAOFactory
in a package under com.tridion.storage
;
- Annotate it with
@Component(...)
and @Scope("singleton")
;
- Make sure it implements
ApplicationContextAware
;
- Make sure you force the setting of the private field (
applicationContext
) which you inherit from JPADAOFactory
;
- Override the methods you're interested in;
- Configure it in cd_storage_conf.xml.
Keep in mind that this extension is not supported by Tridion, is a bit hackish and it's not the only (hackish) way to do it.
Next, I will include some sample code to exemplify what I just described. Again, this is just an example (not beautiful code, not thread safe, no errors handled):
@Component("JPADAOExtensionFactory")
@Scope("singleton")
public class JPADAOExtensionFactory extends JPADAOFactory
implements ApplicationContextAware {
/**
* Static variable which will be set by the Singleton instance managed by Spring
* and used by the instance created through Reflection by Tridion code during
* initialization.
*/
private static ApplicationContext APPLICATION_CONTEXT;
/**
* Constructor called by Spring when init is done.
*/
public JPADAOExtensionFactory() {
//not important what we send. This instance is never going to be used
super(null, "MSSQL");
}
/**
* Constructor called by Tridion at app start-up (after the Spring
* init has happened).
*/
public JPADAOExtensionFactory(String storageId, String dialect) {
super(storageId, dialect);
}
/**
* The method we actually want to override.
*/
public void commitTransaction(String transactionId) throws StorageException {
super.commitTransaction(transactionId);
// TODO: do my stuff
}
/**
* Override this method so we can set the application context on the
* private field we inherit from JPADAOFactory.
*/
public void configureBundle(Configuration storageDAOBundleConfiguration)
throws ConfigurationException {
// first set the right value for the private field
// called 'applicationContext'
try {
setPrivateField(this, "applicationContext", APPLICATION_CONTEXT);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
}
// configure the bundle like we normally do
super.configureBundle(storageDAOBundleConfiguration);
}
/**
* Method called by Spring.
* @see ApplicationContextAware#setApplicationContext(ApplicationContext)
*/
@Override
public void setApplicationContext(final ApplicationContext applicationContext)
throws BeansException {
APPLICATION_CONTEXT = applicationContext;
}
/**
* Utility method using Reflection to be able to set the private field
* we inherit from our parent class.
*/
private static void setPrivateField(final Object fieldOwner,
final String fieldName, final Object value)
throws NoSuchFieldException, IllegalAccessException {
final Field privateField = getPrivateFieldRec(fieldOwner.getClass(),
fieldName);
if (privateField != null) {
final boolean accesible = privateField.isAccessible();
privateField.setAccessible(true);
privateField.set(fieldOwner, value);
privateField.setAccessible(accesible);
}
}
private static Field getPrivateFieldRec(final Class<?> clazz,
final String fieldName) {
for (Field field : clazz.getDeclaredFields()) {
if (fieldName.equals(field.getName())) {
return field;
}
}
final Class<?> superClazz = clazz.getSuperclass();
if (superClazz != null) {
return getPrivateFieldRec(superClazz, fieldName);
}
return null;
}
}
Hope this helps.