This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes Struts and the fly likes Struts2-json plugin not serializing action class to json Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Frameworks » Struts
Bookmark "Struts2-json plugin not serializing action class to json" Watch "Struts2-json plugin not serializing action class to json" New topic
Author

Struts2-json plugin not serializing action class to json

David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Hello, Im having problems getting struts2-json-plugin 2.1.8.1 to
work with struts-jquery-plugin.

Im trying to get struts-jquery grid to load json data that struts2-json plugin forms from a List/object property in that action class.
my action class has to load a "success" result. The success result loads a jsp page that has the struts-jquery grid. that grid should get
its json data from the action class that called the result. Instead, my grid is showing up with no data in it (no json data was loaded).
Im not sure if im just configuring this wrong, or what.


I have the struts2-json-plugin installed and added to my classpath. Same for the struts2-jquery-plugin.

Heres my struts.xml

**********************************************************************************
<struts>

<constant name="struts.devMode" value="true"/>
<constant name="struts.objectFactory" value="guice"/>

<package name="org.webhop.ywdc" namespace="/" extends="struts-default,json-default">

<result-types>
<result-type name="json" class="com.googlecode.jsonplugin.JSONResult">

</result-type>
</result-types>
<action name="login" class="org.webhop.ywdc.LoginAction">

<result type="json">
<param name="root">gridModel</param>
</result>
<result name="success" type="dispatcher">/pages/uiTags/Success.jsp</result>
<result name="error" type="redirect">/pages/uiTags/Login.jsp</result>
<interceptor-ref name="cookie">
<param name="cookiesName">JSESSIONID</param>
</interceptor-ref>
</action>
<action name="logout" class="org.webhop.ywdc.LogoutAction" >

<result name="success" type="redirect">/pages/uiTags/Login.jsp</result>
</action>
</package>



</struts>
***************************************************************************

Under package I have it extend struts-default and json-default. I do this because I need both i believe.
under result types i put <result-type name="json" class="com.googlecode.jsonplugin.JSONResult">, which lets struts know what to do with a json result in your action config.

Under action I have 3 different result types, one for success, one for error, and one for json.
The examples I saw online were simplified ones where they didnt have the result mapped to a certain page.
I find this very confusing, because if your json data has to be read from a certain jsp page (like my "success" result type), then how will struts know which page to load after
the action complets/json serialized?

<result type="json">
<param name="root">gridModel</param>
</result>

As far as I can tell, this result type="json" should cause the json plugin to, for this action class, find any paramter with the name gridModel, and json-ize it.

Heres my action class

*****************************************************************************
public class LoginAction extends ActionSupport {

public String JSESSIONID;
public int id;
private String userId;
private String password;
public Members member;
public List<Customer> gridModel;

public String execute()
{
Cookie cookie = new Cookie("ywdcsid", password);
cookie.setMaxAge(3600);
HttpServletResponse response = ServletActionContext.getResponse();
response.addCookie(cookie);

HttpServletRequest request = ServletActionContext.getRequest();
Cookie[] ckey = request.getCookies();
for(Cookie c: ckey)
{
System.out.println(c.getName() + "/cookie_name + " + c.getValue() + "/cookie_value");
}
Map requestParameters = ActionContext.getContext().getParameters();//getParameters();
String[] testString = (String[])requestParameters.get("password");
String passwordString = testString[0];
String[] usernameArray = (String[])requestParameters.get("userId");
String usernameString = usernameArray[0];

Injector injector = Guice.createInjector(new GuiceModule());
HibernateConnection connection = injector.getInstance(HibernateConnection.class);
AuthenticationServices currentService = injector.getInstance(AuthenticationServices.class);
currentService.setConnection(connection);
currentService.setInjector(injector);
member = currentService.getMemberByUsernamePassword(usernameString, passwordString);
userId = member.getUsername();
password = member.getPassword();

CustomerFactory customerFactory = new CustomerFactory();
gridModel = customerFactory.getCustomers();

if(member == null)
{
return ERROR;
}
else
{
id = member.getId();
Map session = ActionContext.getContext().getSession();
session.put(usernameString, member);
return SUCCESS;
}
}

public String logout() throws Exception
{
Map session = ActionContext.getContext().getSession();
session.remove("logged-in");
return SUCCESS;
}
public List<Customer> getGridModel()
{
return gridModel;
}
public void setGridModel(List<Customer> gridModel)
{
this.gridModel = gridModel;
}
public String getPassword()
{
return password;
}

public void setPassword(String password)
{
this.password = password;
}

public String getUserId()
{
return userId;
}

public void setUserId(String userId)
{
this.userId = userId;
}
public String getJSESSIONID() {
return JSESSIONID;
}

public void setJSESSIONID(String jsessionid) {
JSESSIONID = jsessionid;
}

}

**********************************************************************************

From reading online, all i need to do is have my list property i want json-ized and have a public accessor for it (get, set), which i do.
My action class has a success return which will thru the struts.xml file, open up Success.jsp, which will then load and when the
grid for success.jsp is loaded, it should find that json data and load it to the grid.


My "Success.jsp" page contains a grid from the new struts-jquery-plugin.

***************************************************************************************

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sj" uri="/struts-jquery-tags"%>
<%@ taglib prefix="sjg" uri="/struts-jquery-grid-tags"%>

<%@ page language="java" contentType="text/html" import="java.util.*"%>
<jsp:include page="/pages/uiTags/CheckLogin.jsp" />

<html>
<head>
<sj:head jqueryui="true" jquerytheme="redmond" />
<title>Welcome, you have logged in!</title>
</head>
<body>

<s:url id="remoteurl" action="login"/>

<sjg:grid
id="gridtable"
caption="Customer Examples"
dataType="json"
href="%{remoteurl}"
pager="false"
gridModel="gridModel"
>
<sjg:gridColumn name="id" key="true" index="id" title="ID" formatter="integer" sortable="false"/>

</sjg:grid>

Welcome, you have logged in.

Session Time: <%=new Date(session.getLastAccessedTime())%>






<h2>Password:<s:property value="password"/></h2>

<h2>userId:<s:property value="userId"/></h2>


<a href="<%= request.getContextPath() %>/logout.action">Logout


ID: <s:property value="id"/>
session id: <s:property value="JSESSIONID"/>
</body>
</html>

******************************************************************************************

Here my struts-jquery grid is set up to read the json data from the action class (at least i think so).
My grid shows up, but with no data loaded.

Im not even sure if the struts2-json plugin is actually working. None of the examples were set up like this, where the packages extension
needed to be struts-default as well as json-default.
Im confused about the
<result type="json">
<param name="root">gridModel</param>
</result>
that i mapped in the action class. I read online someone saying that if your action returned a "SUCCESS" then you dont need it to map to json data.
Well, thats not the case. I need my action to open up "success", and also have that page read the json data from the action class that is supposed to have
had a property (gridModel) json-ized.

Can someone explain how to do both of these together? Also, how to see the json data that the plugin json-ized from the action property collection (list<customer>),
just to make sure that Im getting something.

Please help me, you will be my super hero.



Sincerely,

thebravedave

ps: im sure that my action class's List<Customer> (the data that is supposed to be json-ized in the end) is loaded with Customer objects. So, json plugin shouldnt have a problem with a null value.
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

Please UseCodeTags when posting code or configuration. Unformatted code and configuration is unnecessarily difficult to read. You can edit your post by using the button.
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

Under package I have it extend struts-default and json-default. I do this because I need both i believe.

I thought json-default already extended struts-default, but I don't believe the double-extension should cause an issue.
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

The examples I saw online were simplified ones where they didnt have the result mapped to a certain page.
I find this very confusing, because if your json data has to be read from a certain jsp page (like my "success" result type), then how will struts know which page to load after
the action complets/json serialized?

I'm not sure what this means: a JSON result only returns JSON data--there's no page mapping; it's just returning data for use by an Ajax request.
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Thanks for the reply,
You said:
*I'm not sure what this means: a JSON result only returns JSON data--there's no page mapping; it's just returning data for use by an Ajax request.*

So I guess that the struts-jquery-grid makes the ajax request to the action class that has my List that has been set up to be json-ized, and is supposed
to access that json data and load it into the grid.
Sorry for my ignorance, but i wasnt able to find the info i needed online

Am I setting up my json result for action correctly? I have 2 other results encoded in my struts.xml file, one is the jsp page that the grid is located in, and
the other is the error result.
how can i tell if the json plugin is creating the json data?
I used <code><param name="root"> gridModel</param></code> to specify the action attribute that the json plugin should turn into json data
in struts.xml under result-types, i specified the json result type (result-type name="json" class="com.googlecode.jsonplugin.JSONResult").
I also set my grid up to look for this action class and the gridmodel for the grid is named "gridModel".

So, its cool having the json result type in with the other result types for your action class?
Im not sure where the breakdown is, but dont know how to check to make sure the json data is formed properly,
or to findout if the grid is recieving the json data.
Please help if you have any ideas.

sincerely,

thebravedave




David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

David Pew wrote:how can i tell if the json plugin is creating the json data?

Look at the response?
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24

The struts2-json plugin is automatically forming json from my gridModel list property of my action class
and sends that back to the jsp page.
I think the struts-jquery-grid makes the call for the json when the page is loaded.
How would one access this json data from the response?

thanks again.

thebravedave
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

Firebug?
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Im programming in eclipse, and debugging thru the server.
When i do this eclipse/tomcat calls up a small "browser" window inside eclipse that doesnt
allow me the options available in firebug.
Do I have to prepare and export my project every time I want to look at one of these types of responses?
Thanks again for all your help.

sincerely,

thebravedave
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

It's still running on a webserver you can access from a non-embedded browser. IIRC if the log level is DEBUG for the JSON plugin it'll dump it to the log anyway.
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24

Hello. thanks again for all your help with this greenhorn.
Well, im using firefox now to test the program and firebug as you suggested.

Under the firebug Net tab option, under all, there are 2 calls to the action class.
The first was a POST which is an authentication thing that my program uses
to check that the person is in the database. This worked from before I even
started trying to use the grid.
Right ater that is a GET login.action log.
Under Response tab of the GET login.action information that firebug displays,
is a struts problem report.
Here is the report
<code>

<html>
<head>
<title>Struts Problem Report</title>
<style>
pre {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<h2>Struts Problem Report</h2>
<p>
Struts has detected an unhandled exception:
</p>


<div id="exception-info">
<table>
<tr>
<td><strong>Messages</strong>:</td>
<td>
</td>
</tr>
<tr>
<td><strong>File</strong>:</td>
<td>org/webhop/ywdc/LoginAction.java</td>
</tr>
<tr>
<td><strong>Line number</strong>:</td>
<td>46</td>
</tr>

</table>
</div>


<div id="stacktraces">
<hr />
<h3>Stacktraces</h3>
<div class="stacktrace" style="padding-left: 0em">
<strong>java.lang.NullPointerException</strong>
<div>
<pre>
org.webhop.ywdc.LoginAction.execute(LoginAction.java:46)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:441)
com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:280)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:243)
org.apache.struts2.interceptor.CookieInterceptor.intercept(CookieInterceptor.java:218)
com.google.inject.struts2.GuiceObjectFactory$ProvidedInterceptor.intercept(GuiceObjectFactory.java:224)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:488)
org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:67)
com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:122)
com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:110)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Unknown Source)
</pre>
</div>
</div>
</div>

<div class="footer">
<hr />
<p>
You are seeing this page because development mode is enabled. Development mode, or devMode, enables extra
debugging behaviors and reports to assist developers. To disable this mode, set:
<pre>
struts.devMode=false
</pre>
in your <code>WEB-INF/classes/struts.properties</code> file.
</p>
</div>
</body>
</html>

</code>



Its saying that the problem is at login.action line 46. This line is right after I get the request parameters from the login (username and password).
This line is me extracting the value from the request, and declaring a string with the request password. (see earlier coderanch posting for my loginaction class)

In firebox's console tab, there a whole bunch of struts logs, but at the very end
it shows the same error that was showed in the net tab. Right below the error
posting is a red tagged json error that shows:
a red circle and JSON.parse
</head>


So Im guessing that the struts2-json plugin is going to my action class
and trying to create a json mapping from it. Somehow it gets hung
up on this local string i created and assigned the password request variable to.

In my struts.xml file, when i was configuring all of the json, I put <code> <param name="root">gridModel</param> </code>
which should tell it to serialize the gridModel list into json data, but its geting stuck on this local String which assigned the password obtained from the request.

Any ideas?

sincerely,

thebravedave
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Also, when the json data is returned in the post, it should be in the response where this error message is, am I correct?

thebravedave
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

David Newton wrote:Please UseCodeTags when posting code or configuration. Unformatted code and configuration is unnecessarily difficult to read. You can edit your post by using the button.
I'm actually serious about that; I not going to spend much time trying to read unformatted code or config.
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

David Pew wrote:Also, when the json data is returned in the post, it should be in the response where this error message is, am I correct?

Not if there's an NPE before it ever gets to the point of rendering a result--there's been an exception: a break in the normal flow of execution.
As far as I can tell, this result type="json" should cause the json plugin to, for this action class, find any paramter with the name gridModel, and json-ize it.

Any (action) property, not parameter.

Right now it looks like you don't understand how S2 and/or HTTP works, although it's difficult to read the configuration. There are a number of issues with the following:1) You have two results named "success". "success" is the default result name. For all intents and purposes, the behavior will be undefined. The action returning the JSON data can be in the action *class*, but cannot be the same *method* in the action. Every request needs to be handled by an action (or action alias). This is configured to handle two completely different requests with the same action and action method--this is not possible.

Also, when you define *any* action-specific interceptors, you must define *all* of them: this action is configured to use *only* the "cookie" interceptor, which is almost certainly not what you want.

It also appears as though you're redirecting directly to a JSP--this would not be considered good design in an MVC app: all requests should be handled by actions, even if it's one defined via convention (and the convention plugin) or via XML an action defined without specifying a class.

If you post any more code or configuration, please UseCodeTags.
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Hello, thanks again for getting back to me.
I was pretty confused about the struts2-json-plugin.
So now Ive created a new action class that specifically is set to return only the json data I need. Ive also fixed a few of the issues you mentioned that didnt
specifically pertain to the json struts problem im having,
but on to my fix of the problem that still doesnt work.



then in my Success.jsp page



Now my success.jsp page should be accessing the json action name for the class JsonAction, which should the serialize the gridModel property.
When I run the program in firebug and look in the Net Tab and find the error related
to my grid trying to get the json data. The error is as such:



I know it looks like im just not mapping it correctly, but my struts.xml file is correctly configured, i believe



This should map to my JsonAction class, which is in the same folder as the LoginAction class.
I replaced json action name with the action name for LoginAction (which is "login"), and
it knew right away which class i was talking about, it just wasnt the correct class.

I followed the instructions in the apache struts2-json plugin page https://cwiki.apache.org/WW/json-plugin.html
I seem to be setting my application up correctly, but it cant find my action class JsonAction.
Can I get a little help here?
I really do appreciate all of your help.

Sincerely,

thebravedave

David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
ps: in the link that the grid in my success.jsp page gets its json data from, for the action class, I have the action listed as "json.action"
I tried a bunch of different permutations on this, but they all give the same error result listed above.
ty.

thebravedave
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Hi, just a heads up,
I wasnt sure if mabey having my package extend struts-default and json-default, if this might give errors,
so i created a new package in struts.xml with the same namespace, and only had this one extend json-default, but
I get the same error.
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

Start by using the config-browser plugin to see what S2 thinks your configuration is; I don't have access to a machine I can test anything on right now.
David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24
Once again, I must thank you for your patience in helping me. I REALLY appreciate it.

I ran the config-browser and it returned the config information. I
took 4 screen shots. 1st one is the intial page that the config info showed
2nd is the "/" namespace which the login, logout, and jsonaction actions share,
3rd is the jsonaction config info and i cropped the 4th image to the 3rd.
4th is the login action config info, just for a reference, because this action class works.


[Thumbnail for 2.jpg]

[Thumbnail for 1.jpg]

[Thumbnail for 3.jpg]

David Brave
Greenhorn

Joined: May 20, 2010
Posts: 24

hello. So I was messing around with my struts.xml file, and before when i had the json action and the login action in the same package,
i had changed my login.actions return string to be "Authenticated" instead of what i was using before SUCCESS.
I was wondering if it would still work it i put it back as SUCCESS returning in the LoginAction class.
Now my jsonaction class is returning the json data.
This is confusing to me. here is my struts.xml file



All I did was, in my LoginAction class, change my return to "SUCCESS" instead of a string i made up called AUTHENTICATED.
Then all i did was change this in struts.xml and now its working in firebug.
The grid is still not loading the data, but at least im getting my json data back.
Any idea why this would occure?

Sincerely,

thebravedave

ps: thanks again so much.
David Newton
Author
Rancher

Joined: Sep 29, 2008
Posts: 12617

Yeah, you'd have to return the same string as your result is named :)

I'm not familiar with the jQuery plugin--the first thing I'd check is what specific format (not just "JSON", but in an array, does it want header columns, blah blah blah) the grid control expects, then make sure whatever you're serializing to JSON is ending up being output in that format.
anoopkumar kumar
Greenhorn

Joined: Oct 13, 2011
Posts: 1
Did you got it correct i am also facing the same isssue.
 
GeeCON Prague 2014
 
subject: Struts2-json plugin not serializing action class to json