Result is null with JSON and Struts2 - java

I have created a simple form in Extjs4.1.
I am sending the request to Struts2 framework, and using the Strtus2JSON plugin, i have to recieve the response. But unfortunately, the response is null.
Action class
public String execute()throws Exception{
Employee emp = new Employee();
emp.setAddress(getAddress());
emp.setDepartment(getDepartment());
emp.setName(getName());
emp.setSalary(getSalary());
AddEmployeeService empService = new AddEmployeeService();
boolean flag = empService.addEmployee(emp);
resultJSONobj = new JSONObject();
if(flag == true)
resultJSONobj.put("success","Inserted Successfully");
else
resultJSONobj.put("failure","An error occured");
System.out.println(resultJSONobj);
return SUCCESS;
}
struts.xml
<struts>
<package name="default" extends="struts-default, json-default">
<action name="AddEmp" class = "actions.AddEmpAction">
<result name = "success" type="json">
<param name ="root">resultJSONobj</param>
</result>
</action>
</package>
</struts>
Can anybody tell why iam getting the response as null ?

Do you have a Getter for resultJSONobj like this?:
public JSONObject getResultJSONobj(){
return this.resultJSONobj;
}
Add a namespace to your package, like this:
<package name="default" namespace="/" extends="struts-default, json-default">
And see if something has changed...
EDIT
As described in the guide,
'transient' fields are not serialized
fields without getter method are not serialized
Try like this:
Use a Map instead of your JSONObject. Not every class is accepted, and I'm not sure your JSONObject is serializable (do you implement serializable? do you declare a serialVersionUID? etc)
private Map resultJSONobj = new HashMap(); //instantiated at class level
// accessors
public Map getResultJSONobj() {
return resultJSONobj;
}
public void setResultJSONobj(Map resultJSONobj) {
this.resultJSONobj = resultJSONobj;
}
//...
public String execute()throws Exception{
Employee emp = new Employee();
emp.setAddress(getAddress());
emp.setDepartment(getDepartment());
emp.setName(getName());
emp.setSalary(getSalary());
AddEmployeeService empService = new AddEmployeeService();
boolean flag = empService.addEmployee(emp);
if(flag == true)
resultJSONobj.put("success","Inserted Successfully");
else
resultJSONobj.put("failure","An error occured");
System.out.println(resultJSONobj);
return SUCCESS;
}
And change struts config like this:
<struts>
<package name="default" extends="struts-default, json-default">
<action name="AddEmp" class = "actions.AddEmpAction">
<result name="success" type="json" />
</action>
</package>
</struts>
Success is not necessary, but leave it for a clearer code, you can always remove it later.
Now, you should see this as result (if you doesn't have any other getter):
{
"resultJSONobj": {
"success":"Inserted Successfully"
}
}
or
{
"resultJSONobj": {
"failure":"An error occured"
}
}

in your configuration file struts.xml, please use
<param name="includeProperties">resultJSONobj.*</param>
Instead of
<param name="includeProperties">resultJSONobj</param>
I was facing the same issue before in my project, after I made the above change it works.

There are few things missing in your struts.xml file. After result is success, where are you going?
Create json object instance outside your execute method and inside action class.
Struts2JSON plugin serializes all action variables inside an action class. It might be that since you have only declared JSONobject in action class and actually creating it inside execute, JSON might be getting it {}.
Put
private JSONObject resultJSONobj = new JSONObject();
inside action class and outside execute and see, it might work.
For more information you can go here
http://struts.apache.org/2.2.3/docs/json-plugin.html

Related

SessionMap is null after implementing SessionAware interface in Struts 2

I am implementing SessionAware in my action class. But, the sessionMap is always null. The setSession method doesn't seem to be called.
Here is the code. In the execute method, the sessionMap is always null.
What am I doing wrong?
Action class:
public class HelloWorldAction extends ActionSupport implements SessionAware
{
private static final long serialVersionUID = 544659976107736338L;
private Map<String, Object> sessionMap;
private String name;
public String execute() throws Exception {
if(sessionMap != null) {
sessionMap.put("TestID", "Test");
}
return "success";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void setSession(Map<String, Object> arg0) {
this.sessionMap = arg0;
}
}
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-default.xml"/>
<package name="my-projects" namespace="/" extends="struts-default">
<action name="hello"
class="com.my.projects.actions.HelloWorldAction"
method="execute">
<result name="success">/jsp/HelloWorld.jsp</result>
</action>
You can try this to get Session Map
Map session = ActionContext.getContext().getSession();
and remove below line
<include file="struts-default.xml"/>
The struts-default.xml is the name of the default configuration file used by the Struts in it's core library. You should not use this name to your custom configurations.
A base configuration file named struts-default.xml is included in the struts2-core.jar file. This file is automatically included into struts.xml file to provide the standard configuration settings without having to copy them.
To exclude the struts-default.xml or to provide your own version, see the struts.configuration.files setting in struts.properties.
Remove this line from the configuration:
<include file="struts-default.xml"/>
This file can override the default settings such as the interceptor stack and your application won't work in the default mode.
By default it's configured to populate the session to the actions that implement SessionAware.

REST API plugin - use body instead of query string for parameters

I'm using this as a reference to create a REST only configuration on Struts2:
https://cwiki.apache.org/confluence/display/WW/REST+Plugin
I have one model, Receipt with a few test fields: title, body.
Currently to create a receipt, I send a request in this way:
POST /receipt/?body=new_body&title=new_title
and it creates me a receipt with the new body and title passed in.
This doesn't work:
POST /receipt/
{
"body": "new_body",
"title": "new title"
}
Here's some code:
struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="jackson" class="org.apache.struts2.rest.handler.JacksonLibHandler"/>
<constant name="struts.rest.handlerOverride.json" value="jackson"/>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.rest.content.restrictToGET" value="false"/>
<constant name="struts.rest.defaultExtension" value="json"/>
<constant name="struts.rest.handlerOverride.EXTENSION" value="json"/>
<constant name="struts.i18n.encoding" value="UTF-8"/>
<constant name="struts.action.extension" value="xhtml,,xml,json,action"/>
<constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.PrefixBasedActionMapper" />
<constant name="struts.mapper.prefixMapping" value="/receipt:rest,:struts"/>
<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="receipto"/>
<constant name="struts.convention.package.locators" value="controllers,actions"/>
</struts>
ReceiptController.java:
public class ReceiptController implements ModelDriven<Object> {
private ReceiptManager receiptManager = new ReceiptManager();
private String id;
private Receipt model = new Receipt();
private Collection list;
public Object getModel()
{
return (list==null ? model : list);
}
public HttpHeaders create()
{
receiptManager.save(model);
return new DefaultHttpHeaders("create");
}
public HttpHeaders show()
{
model = receiptManager.find(id);
return new DefaultHttpHeaders("show");
}
public HttpHeaders update()
{
receiptManager.save(model);
return new DefaultHttpHeaders("update");
}
public HttpHeaders destroy()
{
model = receiptManager.destroy(id);
return new DefaultHttpHeaders("destroy");
}
public HttpHeaders index()
{
list = receiptManager.list();
return new DefaultHttpHeaders("index").disableCaching();
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
}
Is it supposed to work as I want it to, or is it just how the plugin works?
I guess that postman is sending JSON in the body of the request and sets the content type application/json. Struts can parse the request if you add json interceptor to the stack.
<interceptor-stack name="myStack">
<interceptor-ref name="json"/>
<interceptor-ref name="myInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
The description for "json" interceptor in the JSON Plugin:
If the interceptor is used, the action will be populated from the JSON content in the request, these are the rules of the interceptor:
The "content-type" must be "application/json"
The JSON content must be well formed, see json.org for grammar.
Action must have a public "setter" method for fields that must be populated.
Supported types for population are: Primitives (int,long...String), Date, List, Map, Primitive Arrays, Other class (more on this later), and Array of Other class.
Any object in JSON, that is to be populated inside a list, or a map, will be of type Map (mapping from properties to values), any whole number will be of type Long, any decimal number will be of type Double, and any array of type List.
Resources:
Kickstart FAQ
Getting Started
FAQs
Other Resources

Passing a key value in query string from one page to another in a project using Struts 2

I am trying to pass a key value in query string from one page to another in a project using the Struts 2 framework.
URL Mapping:
<struts>
<package name="default" namespace="/" extends="struts-default">
<!-- Line -->
<action name="line" class="com.example.a.b.action.LineAction">
<result name="success">/line.jsp</result>
</action>
</package>
</struts>
URL For HTML Anchor Link:
http://localhost/line?key=value
When it goes to LineAction I want to get the query string key value part but could find anything online for it.
If I understand you correctly. In your action class create Getters and Setters for key. You will get a value in your action class.
May be You try this way..
try{
URL url = new URL("http://www.google.com?gender=male&name=jagga");
System.out.println(url.getQuery());
}catch(MalformedURLException e)
{
e.printStackTrace();
}
You build your URL of that Action
You can get parameters from the action context like
Map<String, Object> parameters = ActionContext.getContext().getParameters();
But a better way is to implement ParameterAware
private Map<String, String[]> parameters;
public void setParameters(Map<String, String[]> parameters){
this.parameters = parameters;
}

Checking a session value in Struts 2 web application [duplicate]

This question already has answers here:
Is there a way to redirect to another Action class without using on struts.xml
(2 answers)
Closed 6 years ago.
I am creating a web application using Struts 2. I have a login page in it. As the user click the login button after entering the username and password, the credentials are checked and if the credentials are found correct, then a session is created and its attributes are set and control is redirected to WELCOME JSP.
Now before the welcome.jsp is opened, I want to check, if the session attributes are set. How to do it in Struts 2?
Can anyone clear me the concept of interceptors. I read that we create interceptors to perform any function before or after an action is called. Can I create an interceptor that checks if the session is set, every time before WELCOME JSP is called.
you can use <s:if> tag to test presence of your attribute in Session.I am assuming that you are setting value in your action class and here is how you can do that in jsp page
<s:if test="%{#session.logged_in ==true}">
I am assuming that here i am setting a flag indicating if user is logged in or not on similar way you can test as per your requirements
For Interceptors, They are set of utility classes being provided by Struts2 out of the box to make your life easy.Interceptors are just java classes with certain functionality which is being provide by the framework, some of them are
fileUpload
i18n
params
token etc
These Interceptors are called based on the interceptor stack being configured in your application and they will be called at 2 places
when you send request to your action
when request processing done and view rendered.
in first case they will be called before your action execute or custom method defined by you is called, Interceptors are responsible to provide required data to your action class, some of the work done by interceptors before your action called are
File uploading
Handling i18n
Passing form values to respected fields in your action class
validation of your data
there are certain set of interceptors being provided by struts2 , you can have look at struts-defaultxml.
You can create any number of interceptors and configure them to be executed as per your requirements,a ll you need to extends AbstractInterceptor an provide your custom logic inside intercept(ActionInvocation invocation) method
I suggest you to follow below mentioned links to get more overview
building-your-own-interceptor
Struts2 Interceptors
writing-interceptors
#rickgaurav for your 1st question. make a login action like this
<action name="login_action" class="loginAction class">
<result name="success" type="chain">welcomeAction</result>
<result name="input">/index.jsp</result>
<result name="error">/index.jsp</result>
</action>
wher index.jsp is your login page
and in login interceptor first make a session map in which your session attribute will be store
Map<String, Object> sessionAttributes = invocation
.getInvocationContext().getSession();
after that check using this condition
if (sessionAttributes == null
|| sessionAttributes.get("userName") == null
|| sessionAttributes.get("userName").equals("")) {
return "login";
}else{
if (!((String) sessionAttributes.get("userName")).equals(null)){
return invocation.invoke();
}else{
return "login";
}
for your 2nd question assume you are calling a welcomeAction to go to the welcome.jsp page
so you can add action like this
<action name="welcomeAction" class="class">
<interceptor-ref name="logininterceptor"></interceptor-ref>
<result name="login" type="chain">loginaction</result>
<result name="success" >/welcome.jsp</result>
</action>
hope so this will work for you
In Struts.xml write this:
<interceptors>
<interceptor name="loginInterceptor"
class="com.mtdc.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="loginStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
2.Now After aAction which you want to check session put this: <interceptor-ref name="loginStack"></interceptor-ref>
3.Our LoginACtion in struts.xml: `
<action name="login_action" class="com.action.LoginAction">
<result name="success">/welcome.jsp</result>
<result name="input">/login.jsp</result>
<result name="error">/login.jsp</result>
</action>
`
4.Now define LOgin interceptor for that make com,interceptor.LoginInterceptor :
`
public String intercept(ActionInvocation invocation) throws Exception {
Map<String, Object> sessionAttributes = invocation
.getInvocationContext().getSession();
if (sessionAttributes == null
|| sessionAttributes.get("userName") == null
|| sessionAttributes.get("userName").equals("")) {
return "login";
} else {
if (!((String) sessionAttributes.get("userName")).equals(null)
|| !((String) sessionAttributes.get("userName")).equals("")) {
return invocation.invoke();
} else {
return "login";
}
}
}
`
[5]. Now make Login Action class where you assign session:
`
public String execute() {
String result = LOGIN;
UserLogin userlogin;
try {
userlogin = userlogindao.authenticateUser(signin_username, signin_password);
if (userlogin != null && userlogin.getUsername() != null) {
session.put("userID", userlogin.getUserId());
session.put("userName", userlogin.getUsername());
result = SUCCESS;
} else {
result = LOGIN;
}
} catch (Exception e) {
result = LOGIN;
e.printStackTrace();
}
return result;
}
`
[6]. Now final step on your login page on click call action LoginAction.
Yes you can use interceptor.
Make a Action class Which will store UserId / Username of user (after user is authenticated) in session like this.
session.put("userID", userlogin.getUserId());
after that make a Interceptor class which impl. interceptor
public class LoginInterceptor implements **Interceptor** {
public String intercept(ActionInvocation invocation) throws Exception {
get the session attribute using
sessionAttributes.get("userId");
and check it is not null if it is null then return login to forward user to the login page
or else return invocation.invoke(); to continue the action.
and in struts.xml file configure interceptor inside package
<interceptors>
<interceptor name="loginInterceptor" class=".....LoginInterceptor"></interceptor>
<interceptor-stack name="loginStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
and for action you can write
<action name="anything" class="anyclass" method="default">
<interceptor-ref name="loginStack"></interceptor-ref>
<result name="login">/index.jsp</result>
<result name="success" type="redirect">success.jsp</result>
</action>

The form does not submit the selected value of the <s:select>

I have the following dropdown list which correctly shows the options but when I select an item and submit the form it runs into the following error :
'select', field 'list', name 'name': The requested list key 'listnames' could not be
resolved as a collection/array/map/enumeration/iterator type. Example: people or
people.{name} - [unknown location]
My JSP form
<s:form method="POST" action="addNames">
<s:select name="name"
label="Names"
list="listnames"
/>
</s:form>
My Action
#Action
public class Myaction implements ModelDriven{
private MyClass myclass = new MyClass();
private List listnames = new ArrayList();
#Override
public MyClass getModel() {
return this.myclass;
}
public List getListnames() {
return listnames;
}
public void setListnames(List listnames) {
this.listnames = listnames;
}
public MyClass getMyClass() {
return myclass;
}
public void setMyClass(MyClass myclass) {
this.myClass = myclass;
}
}
My Class
public class MyClass {
private String name;
..... getter and setters go here ....
}
struts
<package name="MyUsers" extends="default" namespace="/MyUsers">
<action name="*" method="{1}" class="com.myproject.controller.Myaction">
<result name="uAdd" type="tiles" >uAdd</result>
<result name="uView" type="tiles" >uView</result>
</action>
</package>
STEP 1 :make sure that getter and setter for listnames are done properly
STEP 2 :make sure that you have done the declaration and initialization for listnames List properly
UPDATE 2
Sample Example
struts.xml
<action name="getText" class="commonpackage.ReportsCommonClass" method="getText">
<result name="success">index.jsp</result>
</action>
<action name="myaction" class="commonpackage.ReportsCommonClass" method="myaction">
<result name="success">index2.jsp</result>
</action>
index.jsp
<s:form id="conform" action="myaction" method="post">
<label>NAME</label>
<s:select id="name1" name="name1" list="mylist" headerKey="0" headerValue="--SELECT--"/>
<s:submit value="Click" />
</s:form>
In commonpackage.ReportsCommonClass class
ArrayList mylist=new ArrayList();
public ArrayList getMylist() {
return mylist;
}
public void setMylist(ArrayList mylist) {
this.mylist = mylist;
}
public String getText()
{
mylist.add("NAME 1");
mylist.add("NAME 2");
mylist.add("NAME 3");
mylist.add("NAME 4");
mylist.add("NAME 5");
return SUCCESS;
}
String name1;
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public String myaction()
{
System.out.println("NAMEEEEEEEEEEEEEEEEEEEEE:"+name1);
return SUCCESS;
}
change your select tag like this
<s:form method="POST" action="addNames">
<s:select name="myclass.name"
label="Names"
list="listnames"
/>
</s:form>
Edit:
Problem:
I guess you are hitting jsp directly hence there is no any action execution. If there is no any action execution then there is no any list in request.
Solution.
Hit URL in way that action class get executed and list should initialize or populated before rendering the jsp or view.
Create a method like populateView in action class and execute this method rather than directly execution JSP.
Hope you understand what I want to say.
Provide getter setter for name in your action class.
As your select tag name is name <s:select name="name"> when you submit your form it will search for the property name in your action class.
This may be the problem in your case

Categories