I've worked around the problem inconsistent JSON results by removing the root parameter from the JSONResult annotations. It appears that at least I'm getting consistent results this way:
@Results( { @Result(name = "jsonPopsResult", type = JSONResult.class, value = "", params = {"noCache", "true"}), @Result(name = "jsonRefugesResult", type = JSONResult.class, value = "", params = {"noCache", "true"})}) The params attribute was previously params = {"root", "jsonResult", "noCache", "true"} Fortunately, the jsonResult property on the action is the only non-base-class property, so I'm still returning only what I need. FYI, as was suggested, I tried configuring the action via xml instead of annotations, but for some reason couldn't get the action's results to be recognized: <package name="wizard" extends="myapp" namespace="/wizard"> <action name="mapQuery" class="gov.doi.myapp.actions.wizard.MapQueryAction"> <result name="jsonPopsResult" type="json"> <param name="root">jsonResult</param> </result> <result name="jsonRefugesResult" type="json"> <param name="root">jsonResult</param> </result> </action> </package> I got "No result defined for action gov.doi.myapp.actions.wizard.MapQueryAction and result success". Probably some stupid error on my part, but I don't have time to work on it further right now. If I ever ascertain that the problem goes away with xml config, I'll let the list know. > he must be passing in JSONResult in one of the params to Action I am not passing in JSONResult to the action. The parameters passed (since I suspect you'll ask :-) are filter=false layerId=0 layerName=Section 7 Range nelat=43.689721907017194 nelon=-116.00601196289062 swlat=43.51469675271005 swlon=-116.41937255859374 zoomlevel=11 > can we see web.xml struts.xml and struts-default.xml > and struts-config.xml > please display ALL xml files for your project For what it is worth, the XML files appear below, edited to remove/change irrelevant and security sensitive areas There is no struts-config.xml. I'm using the struts-default.xml from the core jar. ------------------------------ struts.xml (version used when configuring json plugin via annotations): <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <include file="struts-plugin.xml"/> <package name="myapp" extends="struts-default" namespace="/"> <interceptors> <interceptor-stack name="myappStack"> <interceptor-ref name="defaultStack"> <param name="validation.validateAnnotatedMethodOnly">true</param> <param name="validation.excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="myappStack"/> <global-results> <result name="session-expired" type="redirect">/sessionExpired.jsp</result> </global-results> </package> <package name="wizard" extends="myapp" namespace="/wizard"/> <package name="wizardpdf" extends="myapp" namespace="/wizard/pdf"/> <package name="info" extends="myapp" namespace="/info"/> <package name="crud" extends="myapp" namespace="/crud"> <action name="*/*" method="{2}" class="gov.doi.myapp.actions.crud.{1}Action"> <result type="redirect">/crud/{1}/view.action</result> <result name="view">/crud/{1}/view.jsp</result> <result name="input">/crud/{1}/edit.jsp</result> <result name="list">/crud/{1}/list.jsp</result> <result name="search">/crud/{1}/search.jsp</result> <result name="searchResults">/crud/{1}/searchResults.jsp</result> <result name="resourceSelect">/crud/{1}/resourceSelect.jsp</result> <result name="activitySelect">/crud/{1}/activitySelect.jsp</result> <interceptor-ref name="paramsPrepareParamsStack"/> </action> </package> </struts> ------------------------------ struts.xml (version used when configuring json plugin via struts.xml): <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <include file="struts-plugin.xml"/> <package name="myapp" extends="json-default" namespace="/"> <interceptors> <interceptor-stack name="myappStack"> <interceptor-ref name="defaultStack"> <param name="validation.validateAnnotatedMethodOnly">true</param> <param name="validation.excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="myappStack"/> <global-results> <result name="session-expired" type="redirect">/sessionExpired.jsp</result> </global-results> </package> <package name="wizard" extends="myapp" namespace="/wizard"> <action name="mapQuery" class="gov.doi.myapp.actions.wizard.MapQueryAction"> <result name="jsonPopsResult" type="json"> <param name="root">jsonResult</param> </result> <result name="jsonRefugesResult" type="json"> <param name="root">jsonResult</param> </result> </action> </package> <package name="wizardpdf" extends="myapp" namespace="/wizard/pdf"/> <package name="info" extends="myapp" namespace="/info"/> <package name="crud" extends="myapp" namespace="/crud"> <action name="*/*" method="{2}" class="gov.doi.myapp.actions.crud.{1}Action"> <result type="redirect">/crud/{1}/view.action</result> <result name="view">/crud/{1}/view.jsp</result> <result name="input">/crud/{1}/edit.jsp</result> <result name="list">/crud/{1}/list.jsp</result> <result name="search">/crud/{1}/search.jsp</result> <result name="searchResults">/crud/{1}/searchResults.jsp</result> <result name="resourceSelect">/crud/{1}/resourceSelect.jsp</result> <result name="activitySelect">/crud/{1}/activitySelect.jsp</result> <interceptor-ref name="paramsPrepareParamsStack"/> </action> </package> </struts> ------------------------------ Here's the web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!-- ======================================--> <!-- listener --> <!-- ======================================--> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- ======================================--> <!-- filter: openEntityManager --> <!-- binds a JPA EntityManager to the thread --> <!-- for the entire processing of the request --> <!-- ======================================--> <filter> <filter-name>openEntityManager</filter-name> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openEntityManager</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- ======================================--> <!-- filter: transactionFilter --> <!-- Ensures proper commiting and rollback --> <!-- of Transaction --> <!-- ======================================--> <filter> <filter-name>transactionFilter</filter-name> <filter-class>gov.doi.tat.spring.TransactionFilter</filter-class> </filter> <filter-mapping> <filter-name>transactionFilter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <!-- ======================================--> <!-- filter: struts 2 --> <!-- ======================================--> <filter> <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>gov.doi.myapp.actions</param-value> </init-param> <init-param> <param-name>struts.devMode</param-name> <param-value>@struts.devMode@</param-value> </init-param> <init-param> <param-name>struts.enable.DynamicMethodInvocation</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>struts.enable.SlashesInActionNames</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> </web-app>