I have a scenario where I need to call a Java method which sets some request properties and the same has to be reflected in the jsp page.
<script type="text/javascript">
setInterval(function() {
ajaxAction($('#refresh'), 'moveETHAction_fetchExecutorData');
return false;
//callNextMethod(document.getElementById('moveForm'), 'moveETHAction_',
// 'fetchExecutorData');
}, 60 * 1000);
function ajaxAction(form, url) {
/* the time and hour are added to the request for create an unique URL for IE.
* The call to the server is realised only if the url is different...
*/
params = Form.serialize(form) + '&ms=' + new Date().getTime();
currentFocused = document.activeElement.id;
lastActionCalled = url;
formUsed = form;
var myAjax = new Ajax.Request(url, {
method : 'post',
parameters : params,
onComplete : showResponse
});
}
function showResponse(originalRequest) {
xml = originalRequest.responseXML;
}
</script>
as you see, I want to hit action class and the respective method.
However I don't have to replace anything in view part except fetching some request attributes which will be set in Java action class.
the total view part is in one form ('sendOrder') and i included one more form('refresh' within the main form. sorry, i don't know how to achieve my requirement. I just gave this try.
Please let me know how can I resolve this? It's not mandatory to use AJax, all i need to do is hit the java method and display the same page with updated request properties.
I am not sure how many fields you want to get from the Action and you can very well use Jquery along with Struts2-Json Plugin to do the work for you.
S2 Json plugin will help you to send back response in JSON format and you can use Jquery JSon feature to parse those fields and fill the values as per your way.
This is what you have to do
var myFormValues='id='+uuid;
$.getJSON('myAction',myFormValues,function(data) {
$.each(data.myObject,function(key, value){
alert(key);
alert(value);
});
});
here key is the name of the field and value is the value it hold with respect to that fiel
In above you are calling a action namely myAction which will return the JSON back based on the value sent by you myFormValues.
This is a mock for your action
public class MyAction extends ActionSupport{
private String id;
//getter and setter
private String vallue1;
private String vallue2;
private String vallue3;
//there getter ans setters
public String execute() throw Exception{
//Fill you values based on the condition
return SUCCESS;
}
}
<package name="JSON" extends="json-default">
<action name="myAction" class="MyAction">
<result type="json"></result>
</action>
Hope this will give you some idea
Related
Short Question: How do I get the action passed in the AnchorTag's action when I am customising it?
Long Question:
I am doing a migration from Struts 1 to Struts 2 where we are using some custom tags. One of the customisations is in the org.apache.struts.taglib.html.LinkTag. This has been customised to add additional parameters. Please see below a sample tag in a particular jsp.
<shared:link page="/getItems.do?itemType=ItemA&callingPage=Summary">
This link gets added with some additional parameters by the customisation resulting in the below modified link.
/main/getItems.do?itemType=ItemA&callingPage=Summary&custAcctId=1041&customerName=name_mask
The customisation is done like below by overiding the calculateURL method
public class MetaLinkTag extends LinkTag {
/**
* Return the complete URL to which this hyperlink will direct the user.
*
* #exception JspException if an exception is thrown calculating the value
*/
protected String calculateURL() throws JspException {
// Identify the parameters we will add to the completed URL
Map params = RequestUtils.computeParameters
(pageContext, paramId, paramName, paramProperty, paramScope,
name, property, scope, transaction);
params.put("custAcctId","1041");
params.put("custAcctName","name_mask");
String url = RequestUtils.computeURL(pageContext, forward, href,
page, params, anchor, false);
return url;
}
}
I have identified that the org.apache.struts2.views.jsp.ui.AnchorTag in struts 2 will have to be customised to do the equivalent in Struts2. So I replaced the jsp as follows
<shared:link action="/getItems.do?itemType=ItemA&callingPage=Summary">
but I am not able to get the parameter list for adding the new parameters. Struts 1 does RequestUtils.computeParameters to get the parameters and then appends additional stuff to it.
How do I get the original list of parameters of the AnchorTag for Struts 2
P.S: If I get the parameters list, I am planning to override the setAction with the new customised parameters list. Hopefully that goes good. Sample code below
public class MetaLinkTag extends AnchorTag {
#Override
public void setAction(String action) {
//String existingAction = GetExistingAction()
//super.setAction(existingAction +"&custAcctId=1041&customerName=name_mask");
}
Spent 30+ mins in thinking/writing this question and I found the answer when I came to the end of it. It was straight forward.
public class MetaLinkTag extends AnchorTag {
#Override
public void setAction(String action) {
super.setAction(action +"&custAcctId=1041&customerName=name_mask");
}
}
I don't want to waste this effort in writing this question. Putting it out here in case it is useful for someone.
I'm trying to pass data from DAO with flexbile search query trough to the zul page using de the widgetModel. But when I print the widgetModel.orders it says...
(index):93 Uncaught ReferenceError: LazyList is not defined
at window.onload ((index):93)
zul page
window.onload = function () {
const myChart = new Chart(
document.getElementById('myChart'),
config
);
const test = [[${widgetModel.orders}]];
console.log(test);
};
controller class
public class customGraphController extends DefaultWidgetController {
private static final long serialVersionUID = 7954736389190109887L;
#WireVariable
private transient customGraphService customGraphService;
#Override
public void preInitialize(Component comp) {
super.preInitialize(comp);
WidgetModel model = getWidgetInstanceManager().getModel();
model.put("orders", customGraphService.getAllOrders());
}
}
service class
public class customGraphService {
#Autowired
private OrdersDataDao ordersDataDao;
public List<OrderModel> getAllOrders() {
return ordersDataDao.getAllOrders();
}
}
dao class
public class OrdersDataDao {
#Resource
private FlexibleSearchService flexibleSearchService;
public List<OrderModel> getAllOrders() {
final String stringQuery = "select {o.pk} from {order as o}";
final FlexibleSearchQuery query = new FlexibleSearchQuery(stringQuery);
final SearchResult<OrderModel> result = flexibleSearchService.search(query);
if (null != result.getResult()) {
return result.getResult();
} else {
return null;
}
}
}
Does someone knows a solution?
window.onLoad is always too early to manipulate ZK widgets. The onLoad callback will trigger once the initial document has been loaded, but that document itself will load ZK libaries, initialize the client engine, etc.
If you need to do something "after libraries have been loaded", you can use zk.afterload. This hook is good if you need to modify a framework function before the widgets actually use it.
However, this is still before widget instantiation by the client engine, so if your goal is to access a widget, it is still too early.
If you want to do something to a widget after that widget has been added to the page an initialized, what you actually need is a client-side onBind listener.
You can set that listener in zul or in java, but the simplest way to do that is like this: https://zkfiddle.org/sample/1v9phuk/1-Another-new-ZK-fiddle
Lastly, if you are going to use ZK's client-side API to access / modify content at client-side, I'd recommend looking into the ZK client-side selectors. Way easier than trying to manually lookup elements by ID, and way more robust in the long run.
document.getElementById('myChart') will only work if you have a dom element with the actual ID "myChart", which is not how ZK works (not with default UUID generator anyway).
Instead, you can select a widget by it's ZK ID.
Assuming you have <charts id="myChart" /> in your zul, you can get the ZK widget directly as argument to the onBind listener, or you can get it with the ZK selector:
zk.$("$myChart"), and from there you can get the DOM node: zk.$("$myChart").$n()
Make sure you know what is client-side (JavaScript), and what is Server side.
(Lastly)^2, keep in mind that in a ZK architecture, the server is the source of the state, and the client only update the state by sending client commands back to the server.
If you use JS to modify the client-side state, you can create desynchronization between the server-side state and the client-side state, so proceed with caution.
I found a solution, I used GSON to stringify the list and than pass it to the zul page :-)
private Object convertAllOrderModelsToJSON() {
//get all the models
List list = customGraphService.getAllOrdersModels();
//convert models to JSON
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(list);
return json;
}
The get method will prepare the model and send to the "add person" jsp
It will also set the "mode" attribute to be "add" (so add and edit can share same jsp)
When the processSubmit result hasErrors ,mode attribute is gone
How to maintain mode attribute between calls?
#RequestMapping(value="/people/def/add" , method = RequestMethod.GET)
public String personAdd(#ModelAttribute("person") Person person,Model map) {
map.addAttribute("mode", "add");
//DO SOME LOGIC
return "personAdd";
}
#RequestMapping(value="/people/def/add" , method = RequestMethod.POST)
public String processSubmit(#ModelAttribute("person") Person person,BindingResult result) {
personValidator.validate(person, result);
if (result.hasErrors()) {
//MODE ATTRIBUTE IS LOST
return "personAdd";
Request attributes live only for the life of request. So, if you want "mode" back in Post, you may have to submit it back as part of POST, may be by using hidden form control in your web form.
You have to add "#RequestParam("mode") String mode" to your "processSubmit" method to retrieve the value of mode from HTTP POST parameters
class SampleAction extends ActionSupport {
private Map<String,String> circleIdNameMap;
public String preprocess(){
--logic for populating value of MAP
}
--getters and setters
}
Now my problem is on page load I call preprocess function and populate the value of Map. After page submit another method is called and during that after some DB interaction it redirects to JSP, but this time the value of Map is empty. I am using this Map for drop-down tag in Struts2.
My preprocess is associated in the link like:
href="/gma/preprocessConfigureTspThreshold?operatorId=5102&sessionId=12332"`
So only first time when the link is clicked preprocess is called, after that when I redirect to my JSP so its not called then, so second time the value of Map is empty.
Shall I put the map in a session so that it is retained? Or can do something else?
I read that don't use preprocess function, use Preparable interface. But as per docs:
The prepare method will always be called by the Struts 2 framework's prepare interceptor
whenever any method is called for the Action class.
So, it will be called for every method. I want preprocess to be called only when page loads.
The prepare method of the Preparable action class is called on every action execution, that's right. That might be the reason why you prepare the map for a drop-down in the preprocess method.
public class SampleAction extends ActionSupport {
private Map<String,String> circleIdNameMap;
private String circleId;
//getters and setters here
protected boolean reload = false;
private void preprocess(){
// Get the Map by calling a stateless Session bean
circleIdNameMap = remoteInterface.getMap();
}
public String action1(){
preprocess();
Map session = ActionContext.getContext().getSession();
session.put("circleIdNameMap ", circleIdNameMap );
return SUCCESS;
}
public String action2(){
Map session = ActionContext.getContext().getSession();
circleIdNameMap = (Map<String,String>)session.get("circleIdNameMap");
if (circleIdNameMap == null){
if (reload) {
preprocess();
Map session = ActionContext.getContext().getSession();
session.put("circleIdNameMap ", circleIdNameMap );
} else {
addActionError("circleIdNameMap is null");
return ERROR;
}
}
return SUCCESS;
}
...//other actions
}
the JSP for drop-down
<s:select name="circleId" list="circleIdNameMap" listKey="key" listValue="value"/>
The meaning of this code is: you should not return result SUCCESS or INPUT if fields in JSP aren't initialized.
I've a problem sending data from jQuery to struts2 action class.
I have seen the question: JSON Jquery to Struts2 action but I don't understand the solution quite well.
Here is my problem:
The json array is like this:
[{"id":"1","code":"111","name":"ddd"},
{"id":"2","code":"222","name":"sss"},
{"id":"3","code":"333","name":"eee"}]
I want to send the json data to the struts2 action class.
The jQuery code is like this:
var data = JSON.stringify(dataObj);
$.ajax({
url: "Update",
type: "post",
data: data,
dataType: 'json',
contentType:"application/json;charset=utf-8",
success : function(){
alert("You made it!");
}
});
However, in Chrome's Development Tool, I have seen the data submitted to the server side. But on the server side, I don't know how receive the json data.
Action:
public class Update extends ActionSupport{
private String data;
public String getData(){
return data;
}
public void setData(String data){
this.data= data;
}
public String execute(){
System.out.println(data);
return SUCCESS;
}
}
In this way, data is null.
I've also tried to use a List to receive JSON data. Changing "data" type from String to List<Node>, it failed again. Probably because I don't quite understand the OGNL model which Struts2 is using.
Please Help Me. Thank you very much!
{"id":"1","code":"111","name":"ddd"}
Step 1 : Create a bean/pojo to accumulate/encapsulate the above fields
class MyBean{
String id,code,name;
//getters & setters
}
Step 2 : Change your action code to receive a List of MyBeans
public class Update extends ActionSupport{
private List<MyBean> data;
//other code, getters & setters
}
Step 3: Configure your action to de-serialize JSON data and fill the action fields (using json-plugin)
<action name="Update" class="Update">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="json">
<param name="enableSMD">true</param>
</interceptor-ref>
</action>
Step 4 : Make necessary changes in the ajax request body being sent to match the action-params/fields
var data = JSON.stringify(dataObj);
$.ajax({
url: "Update",
type: "post",
data: "data:"+data,
dataType: 'json',
contentType:"application/json;charset=utf-8",
success : function(){
alert("You made it!");
}
});
The above code is untested.
Hey The problem is you are directly posting array of objects. So Struts2 don't know whicch method to call. Change your json data like below. Then it will work.
{"data":[{"id":"1","code":"111","name":"ddd"},
"id":"2","code":"222","name":"sss"},
{"id":"3","code":"333","name":"eee"}]}
Then inside the setter read with object
public void setData(List < Report > data) {
System.out.println("Setter Call Flow");
this.data = data;
}
Where Report is a java class contains id,code,name as it's members with setters and getters.