If a portlet definition includes a validator, the portlet container must create a single validator instance per portlet definition. If the application is a distributed application, the portlet container must create an instance per VM.
While in the current implementation (Branch pluto-1.1, PortletPreferencesImpl.store() ), every time the method store() is called, a new PreferencesValidator instance is created. The validator should have been associated with the portlet definition.
I created an issue for this: http://issues.apache.org/jira/browse/PLUTO-166
I also tried to fix this problem by modifying the
method PortletPreferencesDD.getPreferencesValidator() in
the descriptor-api, as the following:
/**
* Hold the PreferencesValidator instance,
* to ensure that for each portlet definition,
* only one validator instance is created.
*/
private PreferencesValidator validatorInstance = null;
/**
* Get the PreferencesValidator instance instead of
* the class name.
*/
public PreferencesValidator getPreferencesValidator()
throws InstantiationException, IllegalAccessException,
ClassNotFoundException, ClassCastException {
if (validatorInstance == null && preferencesValidator != null) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass(preferencesValidator);
validatorInstance = (PreferencesValidator) clazz.newInstance();
}
return validatorInstance;
}
And I updated the PortletPreferencesImpl accordingly. That works, but is not a good solution. I think the descriptor-api should hold only domain objects created from portlet.xml, and doesn't need to know the portlet API (such as javax.portlet.PreferencesValidator interface).
I am thinking to add a wrapper class for PortletDD, such as PortletDDWrapper, in the container subproject. This class may hold some additional information about the portlet definition (for example, it may hold an instance of PreferencesValidator, to ensure that for each portlet definition, only one validator is created). Then in the container, instead of using PortletDD directly, we may use PortletDDWrapper through which we may get the validator.
If I update the source like this, quite a few classes need to be modified. So I would like to listen to your opinions first.
Regards.
-- /**
* Hold the PreferencesValidator instance,
* to ensure that for each portlet definition,
* only one validator instance is created.
*/
private PreferencesValidator validatorInstance = null;
/**
* Get the PreferencesValidator instance instead of
* the class name.
*/
public PreferencesValidator getPreferencesValidator()
throws InstantiationException, IllegalAccessException,
ClassNotFoundException, ClassCastException {
if (validatorInstance == null && preferencesValidator != null) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class clazz = loader.loadClass(preferencesValidator);
validatorInstance = (PreferencesValidator) clazz.newInstance();
}
return validatorInstance;
}
And I updated the PortletPreferencesImpl accordingly. That works, but is not a good solution. I think the descriptor-api should hold only domain objects created from portlet.xml, and doesn't need to know the portlet API (such as javax.portlet.PreferencesValidator interface).
I am thinking to add a wrapper class for PortletDD, such as PortletDDWrapper, in the container subproject. This class may hold some additional information about the portlet definition (for example, it may hold an instance of PreferencesValidator, to ensure that for each portlet definition, only one validator is created). Then in the container, instead of using PortletDD directly, we may use PortletDDWrapper through which we may get the validator.
If I update the source like this, quite a few classes need to be modified. So I would like to listen to your opinions first.
Regards.
ZHENG Zhong
1 Avenue Alphand
75116 Paris, France
+33 6 76 80 45 90
heavyzheng {AT} gmail {D0T} com
http://heavyz.sourceforge.net
http://heavyz.blogspot.com
http://spaces.msn.com/members/zhengzhong
