1

I'm having an issue removing the @Action and @Result Convention plugin annotations from an action and replacing them with the equivalent config in struts.xml.

package com.microed.cars.web;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;

import com.opensymphony.xwork2.ActionSupport;

public class HomeAction extends ActionSupport {

    @Action(results = {
            @Result(location = "/jsp/home.jsp")
    })
    @Override
    public String execute() throws Exception {
        return super.execute();
    }
}

When these annotations are there, I can successfully access localhost:port/context/home.action

When I remove the annotations I get 'no result defined for action..... ' struts error, despite there being a 'capture all' result in struts.xml - the entire struts.xml is as follows:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
    "http://struts.apache.org/dtds/struts-2.1.dtd">

<struts>
    <constant name="struts.devMode" value="true"/>
    <constant name="struts.convention.package.locators" value="web"/>
    <constant name="struts.convention.default.parent.package" value="beetroot"/>

    <package name="beetroot" extends="json-default">

        <action name="home" class="homeAction">
            <result>/jsp/home.jsp</result>
        </action>

        <action name="cars" class="baseCarsAction">
            <result name="input" type="json">
                <param name="root">autoResults</param>
                /jsp/home.jsp
            </result>
        </action>
    </package>
</struts>

It extends json-default because I need the json result type for an autocomplete function.

I don't know why it's not picking up the action mapping for the homeAction class. I know struts.xml is being read because if I remove the action mapping "cars" then the autocomplete is disabled (but this needs the annotations which I'm trying to remove in order to validate this).

I know that 'no result defined' is a simple error, usually caused by spelling/capitalization errors but this is definitely not the case here, it's simply seems to be ignoring the whole "home" action mapping.

When stepping through DefaultActionInvocation.createResult, there are no 'results' at all for it to try to match against.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
Ken Alton
  • 686
  • 1
  • 9
  • 21

1 Answers1

2

As it stands the cars action declaration isn't valid (nor does it make sense, IMO):

<action name="cars" class="baseCarsAction">
  <result name="input" type="json">
    <param name="root">autoResults</param>
    <param name="location">/jsp/home.jsp</param>
  </result>
</action>

That said: if it's a JSON result, a JSP isn't helpful, and it'll be ignored (or downright rejected, I'm not sure if it's an error or not). A single result will be either JSON, or HTML.

Turn logging up to DEBUG level to catch startup errors to narrow the range of possible causes.

If baseAction is configured in your Spring config file (which is unnecessary if you're using Spring annotations for injection) the configuration for the home action is valid.

I'd be wary of deploying the convention plugin if you're not actually using it: it changes how actions are mapped; it may have an impact on the surrounding application and cause problems. Stick with one or the other, avoid both–it makes it harder to reason about the source of application behavior.

Unrelated, but I recommend putting JSP pages under /WEB-INF to disallow direct client access.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • Yes, I removed the convention constants from struts.xml and now works as expected - perhaps more importantly - works in a way that I understand - my experience with Annotations is limited to basic Spring annotations for dependency injection. Dave, your knowledge is impressive and to assist patiently as you have is extremely noble. Thank you! – Ken Alton Jan 29 '13 at 16:06
  • @KenAlton Aw shucks; no problem. It's a lot to wrap your head around at first, but once you know the places-to-look-for-problems, things start to fall in to place much more quickly :) – Dave Newton Jan 29 '13 at 16:38
  • +1 although I strongly support the struts2-conventions-plugin, strange things can happen along with xml mappings, and the config-browser-plugin gets confused and will tell out right lies. Judging from the plugin, it isn't that easy to get the state of actions. Action handling isn't a particularly unified thing, I really wish it were much more unified because some interesting things are possible if you can accurately (and easily) determine certain handling... and it is a bit difficult to modify struts2 handling during run time. Sorry mostly OT but does point at why it doesn't cooperate. – Quaternion Jan 29 '13 at 20:36
  • @Quaternion I agree; adding the convention package can lead to counter-intuitive behavior. I'm not sure what the best way to make the browser plugin cooperate is, although it might be easier now that there's a plugin ordering mechanism (IIRC). I may poke around with this as part of a related side project; thanks for the nudge. – Dave Newton Jan 29 '13 at 20:38
  • @DaveNewton what would be really ideal, although I think it would be a nightmare. Would be to create a formal datamodel (ER diagram) for struts2 configuration, allow for an extension point to store struts2 configuration in a DB (then a plugin could support an by default an in memory option by default). Then struts2 would use this singular model for all transactions. Then on updating the model, new requests could be queued until old ones complete and then the new request be loaded. As it stands you have to mess around with immutable collections, it's just a pain. – Quaternion Jan 29 '13 at 20:46
  • I think struts2 internals could be hugely cleaned up and a config-browser plugin would only need to query internal state, it would be _very_ trivial. I needed to create a Unknown result handler to do something that could be readily fixed with such a system, any time anyone needs to go that route the config-browser plugin isn't going to be able to figure out what is going on. – Quaternion Jan 29 '13 at 20:51