Beanアクションを動的に呼び出す複合コンポーネントがあります。
<composite:interface>
<composite:attribute name="actionMethod" method-signature="java.lang.String action()"/>
</composite:interface>
<composite:implementation>
<p:menubar autoDisplay="false" styleClass="subMenu">
<p:menuitem>
<h:commandButton action="#{cc.attrs.actionMethod}" value="#{bundle.CreateSaveLink}" styleClass="smallButton button buttonSave"/>
</p:menuitem>
</p:menubar>
</composite:implementation>
また、セキュリティを実装するためにActionListenerクラスも定義しました。
public class SecurityActionListener extends ActionListenerImpl implements ActionListener {
private static final Logger log = Logger.getLogger(SecurityActionListener.class);
private String isCasEnabled;
public SecurityActionListener() {
isCasEnabled = PropertyUtility.isCasEnabled();
}
@SuppressWarnings("unused")
@Override
public void processAction(final ActionEvent event) {
if(!isCasEnabled.equals("true")) {
super.processAction(event);
return;
}
final FacesContext context = FacesContext.getCurrentInstance();
final Application application = context.getApplication();
final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
// Action stuff
final UIComponent source = event.getComponent();
final ActionSource actionSource = (ActionSource) source;
MethodBinding binding;
binding = actionSource.getAction();
final String expr = binding.getExpressionString();
if (!expr.startsWith("#")) {
super.processAction(event);
return;
}
final int idx = expr.indexOf('.');
if (idx <0) {
log.error("Errore nella formattazione della chiamata al metodo: " + expr + ". No '.' found");
return;
}
final String target = expr.substring(0, idx).substring(2);
final String t = expr.substring(idx + 1);
String method = t.substring(0, (t.length() - 1));
final int idxParams = method.indexOf('(');
if (idxParams >=0) {
method = method.substring(0,idxParams);
}
final MethodExpression expression = new MethodExpressionMethodBindingAdapter(binding);
final ELContext elContext = context.getELContext();
final ExpressionFactory factory = context.getApplication().getExpressionFactory();
final ValueExpression ve = factory.createValueExpression(elContext, "#{" + target + '}', Object.class);
final Object result = ve.getValue(elContext);
// Check if the target method is a secured method
// and check security accordingly
final Method[] methods = result.getClass().getMethods();
for (final Method meth : methods) {
if (meth.getName().equals(method)) {
if (meth.isAnnotationPresent(CustomSecurity.class)) {
final CustomSecurity securityAnnotation = meth.getAnnotation(CustomSecurity.class);
log.debug("Function to check security on: " + securityAnnotation.value());
SecurityUtility.checkSecurity(securityAnnotation.value());
} else {
super.processAction(event);
}
break;
}
}
log.warn("No method: " + method + " found in: " + methods + ", for object: " + result);
}
}
commandButtonのアクションが標準的な方法で定義されている場合:
<h:commandButton action="#{bean.action}" value="test" />
すべてがOKで、ActionEventによってリスナー内のBeanとアクションを検出できますが、複合コンポーネントとこのコードでは、実際のアクションパラメーターに関する情報がありません。
ブレース表記を使用した場合も同じ問題が発生します:#{beanName['action']}。この場合、デバッグモードでは、メソッドExpressionImplおよびVariableMapperImplとバインドされているオブジェクトTagMethodExpressionを確認できます。ここで、マッピングbeanName-> "real_bean_name"
複合コンポーネントまたはブレース表記によって生成された場合、ActionEventによってBeanとアクションを取得する方法はありますか?
ありがとう!