In a project using Struts2 (2.3.20) I would like to run through the configured actions (name, class, namespace, method) at application startup.
I'm using
- Struts 2.3.20
- struts-spring-plugin
- struts-convention-plugin
For reference: I've done some work with beans and Struts injection before so not entirely fresh on this, but I'm stuck solving the problem stated here.
Any pointers on how to obtain this would be appreciated.
Further explanation
Reading Andrea's answer below I see I need to explain what I need.
I'm building a application menu builder feature for the application. My plan is to obtain the action configurations and build a tree of "menu nodes" from information in annotations on selected action classes and methods.
My problem with the code from the config-browser is that the Configuration
(xwork) doesn't seem to be available outside of Struts components. Since this is an application startup task it doesn't really fit Struts' MVC component model. I'd like to put the menu building initialization in a ServletContextListener
.
Fake example
Per request here is just the connection actionconfig <-> annotation <-> my_custom_menu. From this I could produce a menu structure provided from the annotations on action classes and methods.
public class ActionMenuBuilderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent arg0) {
List<ActionCfg> actions = Struts.getConfiguredActions(); // thisi is where I'd like some help
for(ActionCfg action : actions) {
MenuAnnotation annotation = getAnnotationFromMethodOrClass(action);
if(annotation != null) {
addMenuItem(action, annotation);
}
}
}
}
Here ActionCfg
is whatever class Struts would return for action configuration, Struts.getConfiguredActions()
would be one or more calls to Struts components and addMenu(...)
is where I add a menu item node to my structure. The structure is later the target from JSP-s to build menus.
I don't know how much more code to write.
My solution
For completeness I thought I'll include what came out of this.
First, I to plugged in into Struts through this
ServletContextListener
:
public class ActionMenuBuilderListener implements
ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent event) {
ActionMenuDispatcherListener listener =
new ActionMenuDispatcherListener();
ServletContext context = event.getServletContext();
listener.setServletContext(context);
Dispatcher.addDispatcherListener(listener);
}
}
Then, I wrote the DispatcherListener
:
public class ActionMenuDispatcherListener implements DispatcherListener {
private ServletContext servletContext;
...
@Override
public void dispatcherInitialized(Dispatcher dispatcher) {
Map<String, PackageConfig> packages = dispatcher
.getConfigurationManager().getConfiguration()
.getPackageConfigs();
Map<String, Map<String, ActionConfig>> runtimeActionConfigs = dispatcher
.getConfigurationManager().getConfiguration()
.getRuntimeConfiguration().getActionConfigs();
for (String packageKey : runtimeActionConfigs.keySet()) {
Map<String, ActionConfig> actionConfigs = runtimeActionConfigs
.get(packageKey);
for (String actionKey : actionConfigs.keySet()) {
ActionConfig actionConfig = actionConfigs.get(actionKey);
PackageConfig packageConfig = packages.get(actionConfig
.getPackageName());
if (packageConfig != null) {
String actionName = actionConfig.getName();
String namespace = packageConfig.getNamespace();
try {
ActionMenu methodAnnotation = getMethodAnnotation(actionConfig);
if (methodAnnotation != null) {
String annotationInfo = methodAnnotation.value();
log.debug("[{}, {}, {}]", namespace, actionName,
annotationInfo);
}
} catch (ClassNotFoundException e) {
log.error("{}: {}", e.getClass().getSimpleName(),
e.getMessage());
}
}
}
}
}
protected ActionMenu getMethodAnnotation(ActionConfig actionConfig)
throws ClassNotFoundException {
String className = actionConfig.getClassName();
String methodName = actionConfig.getMethodName();
Class<?> actionClass = Class.forName(className);
try {
Method method = actionClass.getDeclaredMethod(methodName, null);
ActionMenu annotation = method.getAnnotation(ActionMenu.class);
return annotation;
} catch (NoSuchMethodException | SecurityException e) {
// log.error("{}: {}", e.getClass().getSimpleName(),
// e.getMessage());
}
return null;
}
}
Just in case someone else is thinking along those line :)
PackageConfig packageConfig = Dispatcher.getInstance().getConfigurationManager().getConfiguration().getPackageConfig("default");
. I'll start there and I'll get back to you. – Bateau