Thanks Costin. It turns out that we actually have to handle errors in afterPropertiesSet. It's probably possible to do this with Spring AOP, but I ended up just using AspectJ:
Code:
public aspect OptionalBeanRecovery {
private boolean OptionalBean.failed = false;
private String OptionalBean.beanName;
public void OptionalBean.onError(Exception e) {
logWarn("Unable to initialize "+beanName, e);
}
public void OptionalBean.setBeanName(String name) {
beanName = name;
}
public String OptionalBean.getBeanName() {
return beanName;
}
void around(OptionalBean optionalBean) : execution(void afterPropertiesSet()) && this(optionalBean) {
try {
proceed(optionalBean);
} catch (Exception e) {
optionalBean.failed = true;
optionalBean.onError(e);
}
}
void around(OptionalBean optionalBean) : execution(void destroy()) && this(optionalBean) {
if (!optionalBean.failed) {
proceed(optionalBean);
}
}
}
public interface OptionalBean extends InitializingBean, BeanNameAware {}
public class OptionalConnectorServerFactoryBean extends ConnectorServerFactoryBean implements OptionalBean {
public void onError(Exception e) {
logWarn("Unable to set up remote JMX connector. This is often caused by having another server trying to use the same ports. Root cause:", e);
}
// boilerplate code to provide a hook for advising
public void afterPropertiesSet() throws JMException, IOException {
super.afterPropertiesSet();
}
// boilerplate code to provide a hook for advising
public void destroy() throws IOException {
super.destroy();
}
}