
Many of the action bean annotations are related to dependency injection navigation. In this section we look at annotations supplied with Strecks which are also used in action beans, but are not related to dependency injection or navigation.
The @Controller annotation is necessary for every action bean because it
identifies the controller action which will execute the action bean's methods.
The controller action identified using this annotation must be interface compatible with
the action bean. Every controller action defines an interface which collaborating
action beans must implement. The action bean which attempts to use this
controller action must implement the interface.
Consider for example the following action bean:
@Controller(name = BasicController.class)
public class ExampleBasicAction implements BasicAction
{
    public String execute()
    {
        return "success";
    }
}
The action bean implements the interface BasicAction. This corresponds with the
BasicController's @ActionInterface annotation, 
which specifies the interface 
that the action bean should implement, as shown below:
@ActionInterface(name = BasicAction.class)
public class BasicController extends BaseBasicController
{
    protected ViewAdapter executeAction(Object actionBean, ActionContext context)
    {
        //implementation omitted
    }
}
| Location | Class declaration | 
| Purpose | Identify the controller implementation class | 
| Usage | Every action bean needs to contain a @Controllerannotation | 
The @InitMethod annotation is used to indicate an action bean method which should be executed
after dependencies have been injected, but before any interceptors or action bean interface
methods are called. The method annotated using the @InitMethod annotation must
return void and cannot define parameters. The init method can be used to perform post-dependency 
injection initialisation tasks. A (rather trivial) example is shown below:
@Controller(name = BasicController.class)
public class ExampleLifecycleAction implements BasicAction
{
    private static int initCount;
    @InitMethod
    public void init()
    {
        initCount++;
    }
    
    public String execute()
    {
        return "success";
    }
    public String getMessage()
    {
        return "init() called " + initCount;
    }
}
Note that in this example, the initCount 
field is static because the action bean
is instantiated on a per-request basis.
The @InitMethod annotation does not take any parameters.
The @CloseMethod annotation is the analogue of the
@InitMethod annotation. It is executed after the action bean methods as well as
any post-execution interceptors are called. Also, it will always be called. For
example, if one of the post-execution interceptors throws an exception, this
will be logged, but the subsequent close method will still be called. An example is
shown below.
@Controller(name = BasicController.class)
public class ExampleLifecycleAction implements BasicAction
{
    private static int closeCount;
    
    public String execute()
    {
        return "success";
    }
    public String getMessage()
    {
        return "close() called " + closeCount;
    }
    
    @CloseMethod
    public void close()
    {
        closeCount++;
    }
}
Like @InitMethod annotation, 
the @CloseMethod annotation does not take any parameters.
Struts includes a LookupDispatchAction which is useful in handling submission
of forms containing multiple buttons. When using LookupDispatchAction, you need to
implement an abstract getKeyMethodMap() to determine a mapping from
message keys (used to name the buttons) to method names.
Streck's replacement for LookupDispatchAction is through the use of controllers
which implement the LookupDispatchActionController interface. Two implementations are
provided: 
BasicLookupDispatchController and NavigableLookupDispatchController.
Action beans which use these controllers define a message key to method mapping not through
an abstract method implementation, but through the use of the @DispatchMethod annotation.
An example is shown below, with method implementations omitted:
@Controller(name = NavigableLookupDispatchController.class)
public class ExampleNavigableLookupSubmitAction implements NavigableSubmitAction
{
    public void preBind()
    {
    }
    
    public void execute()
    {
    }
    @DispatchMethod(key = "button.add")
    public void insert()
    {
    }
    @DispatchMethod(key = "button.delete")
    public void delete()
    {
    }
    public void cancel()
    {
    }
    @NavigateForward
    public String getResult()
    {
        return "success";
    }
}
| Location | Method to be executed in multi-button form | 
| Purpose | Executes request processing logic specific to one of the buttons in a multi-button form | 
| Usage | In action beans which use NavigableLookupDispatchControllerorBasicLookupDispatchControlleras action controllers | 
Strecks provides mechanisms not only for action beans to be injected with Spring beans, 
but also for action beans themselves to be Spring beans. This is achieved
using the @SpringBean annotation, as shown in the example below:
@Controller(name = BasicController.class)
@SpringBean(name = "springActionBean")
public class SpringControlledAction implements BasicAction
{
    private String message;
    private SpringService springService;
    public String execute()
    {
         //execute SpringService methods
    }
    public void setSpringService(SpringService service)
    {
        this.springService = service;
    }
}
Note the absence of the @InjectSpringBean 
annotation for setSpringService(). 
This is because dependency injection of Spring beans is provided by the Spring
container. Note that use of Spring beans as action beans does not stop any
of the Strecks annotation-based dependency injectors from being used.
The Spring application context needs to be initialized
using an entry such as the following in web.xml.
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-context.xml</param-value>
</context-param>
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
Of course, the Spring configuration file needs a bean entry corresponding
with the name used in the @SpringBean annotation.
The bean needs to be defined as a non-singleton 
(i.e. with singleton = "false")
| Location | Class declaration | 
| Purpose | Identify the action bean as a Spring action bean | 
| Usage | The Spring application context must be present. The action bean must be configured as a non-singleton Spring bean in the Spring application context, under the name used in the annotation |