Set data into ActionResponse Portlet GateIn - java

I am working on portlet for GateIn 3.6. Currently i have created a page that list the records in table. When user click on any row then it takes to description page.
Right now when user click on row it loads the details page but values are not available. What i am doing details are here..
#RenderMode(name = "view")
public void display(RenderRequest request, RenderResponse response) throws PortletException, IOException, NamingException {
RecordsDAO recordsDAO = new RecordsDAOImpl();
// Records listing available on listing page
request.setAttribute("recordsList", recordsDAO.getAllRecords());
// tried to load record detail page when user click one row
if(actionJsp == null || actionJsp.equals("")){
getPortletContext().getRequestDispatcher("/jsp/ListRecords.jsp").
include(request, response);
} else {
getPortletContext().getRequestDispatcher("/jsp/DetailsBoxRecord.jsp").
include(request, response);
}
actionJsp = "";
}
and the process action is
#ProcessAction(name = "details")
public void details(ActionRequest request, ActionResponse response) throws PortletException, IOException {
RecordsDAO recordsDAO = new RecordsDAOImpl();
int id = Integer.parseInt(request.getParameter("id"));
RecordsForm recordsForm = recordsDAO.getRecord(id);
// way 1 set request attribute
request.setAttribute("details", recordsForm);
// way 2 set response attribute -- display error that cannot set Form type values
response.setRenderParameter("details", recordsForm);
actionJsp = "values";
}
Option1:
I have tried to set RecordsForm type values in request.setAttribute, its done but the values in request are not available in jsp page.
Option2:
Using response.setRenderParameter I am not able to set RecordsForm type values in response.setRenderParameter to access these values in jsp page.
Can anyone please guide me which one is correct way in my case and how these values will be available in jsp page so i can load detail page.

This line of code
response.setRenderParameter("details", recordsForm);
will only pass the recordsForm object to the doView method as parameter. Your JSP is likely trying to use attributes on the RenderRequest. This means in your doView you will need to do something like the following
RecordsForm recordsForm = request.getParameter("details");
request.setAttribute("details", recordsForm);
There is also the option to use the portlet container runtime option javax.portlet.actionScopedRequestAttributes. You set this in your portlet.xml and it should take attributes you set in an action method and provide them as attributes in your render method, eliminating the need to move your objects from the parameters map to the attributes map yourself.
Unrelated note: It looks like you're using actionJsp as an object variable in your portlet. That's not recommended because portlets should be coded to be thread safe. Object variables are shared between users and threads, so saving user specific state data in them will cause errors when you get multiple users.

After adding actionScopedRequestAttributes in portlet.xml i am able to set the values in request and these values are available in jsp pages.
<container-runtime-option>
<name>javax.portlet.actionScopedRequestAttributes</name>
<value>true</value>
</container-runtime-option>
and process action is some thing like that
#ProcessAction(name = "details")
public void details(ActionRequest request, ActionResponse response) throws PortletException, IOException {
RecordsDAO recordsDAO = new RecordsDAOImpl();
int id = Integer.parseInt(request.getParameter("id"));
RecordsForm recordsForm = recordsDAO.getRecord(id);
request.setAttribute("details", recordsForm);
}

Related

Getting more data during a Post request using Spring / Thymeleaf

I'm not really sure how to ask the question, but I'm going to try here.
I've got a list of actions that could happen to a subject. The user of my system needs to approve these actions and does so by selecting (checkboxes) these actions and then clicking the Approve button. Some of these action might require extra data, so a new page is presented to the user. The user enters that new data. Then the backend sends the whole package off to the endpoint for modification on the database. Once completed, it will reload the page they were just on.
So this is how I have it setup:
Approve button jumps to the following method:
#PostMapping("ApproveActions")
public RedirectView approveActions(ModelandView mav, #ModelAttribute("pendingActions") PendingActionsForm pendingActions) {
boolean needsDetails = false;
ActionForm actionForm = new ActionForm();
// parse through each of the actions
pendingActions.forEach(action -> {
// verify if the action has been selected by the user.
if (action.isSelected()) {
// if needsDetails hasn't been set to true,
if (!needsDetails) {
// check to see if it is one of the special actions that needs more info
needsDetails = ActionTypes.NeedsDetails(action.typeId());
}
// build the data for the endpoint
actionForm.addActionData(action);
}
});
if (needsDetails) {
// load the new page
rv.setUrl("/extraActionDetails");
return rv; // This is not right, but it does get me to the new page.
// get data
// return to this point with that new data
actionForm.setExtraDetails(???);
}
actionService.ApproveActions(actionForm);
RedirectView rv = new RedirectView();
rv.setUrl("/subjects/" + pendingActions.getSubjectId() + "#actions-pending");
return rv;
}
The problem I'm having is I don't know how to do that part with // load the new page get data and return to this point with that new data. I've got the extra-details.jsp page built out. And it's controller can be called. Does this question make sense? Are there any tutorials out there that address this situation?

Session existing even after invalidating it

I have basic login-logout session management problem.
When i click login button, this function below gets triggered.After LDAP authentication, it moves to index.html where I display their name.
function validate()
{
var pageTitle=$(document).attr('title');
var un=document.getElementById('username').value;
var pwd=document.getElementById('pass').value;
$.ajax({
'url':'/analytics_1/validate',
'data':'userName='+un+'&password='+pwd,
'type':'GET',
'success':function(response)
{
if(response==1)
{
$.ajax({
'url':'/analytics_1/LogButton',
'type':'POST',
'data':'userName='+un+'&buttonId=VIKALPLoginButton&pageTitle='+pageTitle,
'success':function()
{
window.open("index.html","_self");
}
});
}
else
{
alert("Invalid Credentials");
}
}
});
}
I create the Session in LogButton.java after checking if it's new
if(session.isNew())
{
System.out.println("session is not set, lets create the name");
associate=req.getParameter("userName");
session.setAttribute("Associate",associate);
}
else
{
System.out.println("session is already set, lets get the name");
associate=(String)session.getAttribute("Associate");
}
I get their name from the session I created after successful login
And I do some actions and logout,
$('#logout').on('click',function()
{
var pageTitle=$(document).attr('title');
$.ajax({
'url':'/analytics_1/LogButton',
'data':'buttonId=VIKALPLogoutButton&pageTitle='+pageTitle,
'type':'POST',
'success':function()
{
window.open('Login.html',"_self");
},
'error':function(err)
{
alert("haha:"+err.response);
}
});
});
In LogButton.java, I check if button is VIKALPLogoutButton, if true, i proceed to invalidate the session and remove Attribute
if(button.equals("VIKALPLogoutButton"))
{
System.out.println("deleting the session cuz of logout");
session.removeAttribute("Associate");
session.invalidate();
//System.out.println("what happens to the session? " +session.isNew());
}
All these happen as per required. Now comes the security use case : What should happen if I go to index.html without logging in?
So I started checking if session is set or not when index.html loads,
$(document).ready(function () {
$.ajax({
'url':'/analytics_1/GetAssocId',
'type':'POST',
'success':function(response)
{
if(response!="null")
{}
else
{
window.open("Login.html","_self");
}
$('#name').text(response);
}
});
.....
.....
}
GetAssocId.java:
public void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException,IOException
{
HttpSession session=req.getSession();
PrintWriter out=res.getWriter();
out.print(session.getAttribute("Associate"));
}
This also works fine, i.e it redirects me to Login.html if the session isn't created.
Now the thing is, I cannot Login, even after providing valid credentials, somehow the "Associate" attribute is set to null,
Below is the System.out.println output that I get in cmd
Above white line: Login,Logout action (notice the session invalidate output that I've given)
Below white line: Go directly to index.html, it redirects to Login.html, and you Login with your valid credentials,
Now this is my problem, It invalidates the session, yet still it says session is already existing . Even more confusing is, session is existing, but the value is null.
How do I overcome this problem? Please help
P.S:Other than the snippets I've provided for LogButton.java are not significant for this problem
HttpSession session=req.getSession();
If you look at the docs of getSession method
Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a new session.
If create is false and the request has no valid HttpSession, this method returns null.
You are calling req.getSession() method which gives you a new session. Probably to get the existing session you need to use
HttpSession session=req.getSession(false);
As you already invalidate the session, this gives you session as null .
Your other question
Now this is my problem, It invalidates the session, yet still it says session is already existing . Even more confusing is, session is existing, but the value is null.
It's because you created a new session, there are no attributes in it and that is the reason you getting null

Tapestry5 : URL Re-writing : Pass parameters to transformPageRenderLink method

I am upgrading tapestry from 5.2.4 to 5.3.8 and am stuck at re-implementing the URL re-writing part.
In my application a user account can have multiple data stores. User can have same page of different stores active at the same time. Hence I need to put the storeId in page links and event links URLs. So What is done is as follows.
I register MyLinkTransformerClass in AppModule as follows.
#Contribute(PageRenderLinkTransformer.class)
#Primary
public static void provideURLRewriting( OrderedConfiguration<PageRenderLinkTransformer> configuration){
configuration.addInstance(
"Faces", MyLinkTransformer.class);
}
Following is the MyLinkTransformer class which implements PageRenderLinkTransformer
public PageRenderRequestParameters decodePageRenderRequest(
Request request) {
// for incoming requests - remove the store id from URL and
// save into Request as an attribute
String path = request.getPath();
if (path.equals("/")) {
// Redirect to accounts page
return new PageRenderRequestParameters("account", new EmptyEventContext(), false);
}
else {
String start = path.split("/")[1];
if (!ignoredRewriteSet.contains(start) && !start.startsWith("account")) {
String storePath = path.substring(1).substring(path.indexOf("/"));
int idx = storePath.indexOf("/");
if (idx < 0) idx = storePath.length();
String storeId = storePath.substring(0, idx).trim();
RequestHelper.setStoreId(request, storeId);
EventContext urlEventContext = new URLEventContext(contextValueEncoder, new String[]{storeId});
EventContext arrayEventContext = new ArrayEventContext(typeCoercer, "foo");
return new PageRenderRequestParameters(storePath.substring(idx), arrayEventContext, false);
//return new PageRenderRequestParameters(storePath.substring(idx), new EmptyEventContext(), false);
}
}
return null;
}
public Link transformPageRenderLink(
Link defaultLink,
PageRenderRequestParameters parameters) {
// for outgoing requests- This is where I want to access the store Id
// which is stored in Request class of Tapestry as an attribute and
// add it to the URL
return null;
}
So, the idea is to remove storeId from URL in decodePageRenderRequest method and save it in the Request class of Tapestry as an attribute. And while creating outgoing URLs of page link and event link, I want to access the storeId which was saved in Request and inject it to the URL which will be rendered in method transformPageRenderLink.
But I don't know how to pass parameters to transformPageRenderLink method or access Request instance there.
I am following http://blog.tapestry5.de/index.php/2010/09/06/new-url-rewriting-api/ example.
I am new to URL Rewriting, any help with this will be appreciated.
You will probably be interested in the ModeComponentEventLinkEncoder here. It removes a "mode" from the URL and puts it onto the Environment before passing it on to the normal tapestry URL processing.
It's a two way process so the "mode" is included in any links generated on the page.
Note: This is applied as a decorator here

Wicket trigger request after another request

I try my best to describe my situation.
My wicket site contains list wicket component, where every list element has another list. Each element in lowest level list has ajax wicket link to download some file. All this works fine. I used to this AjaxBehaviour. Method startDownload of this behaviour is invoked within link onClick method.
public void startDownload(AjaxRequestTarget target) {
target.appendJavaScript("window.location.href='" + getCallbackUrl() +"'");
}
Method onRequest of this behaviour is:
#Override
public void onRequest() {
IRequestHandler fileTarget = new IRequestHandler() {
#Override
public void respond(IRequestCycle requestCycle) {
if (null != file) {
try {
FileInputStream inputStream = new FileInputStream(file);
WebResponse resp = (WebResponse) requestCycle.getResponse();
resp.setAttachmentHeader(fileName);
String contentType = FileUtils.getFileType(fileName);
if (contentType != null) {
resp.setContentType(contentType);
}
resp.setHeader("Pragma", "anytextexeptno-cache");
resp.setHeader("Cache-Control", "max-age=0");
Streams.copy(inputStream, requestCycle.getResponse().getOutputStream());
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
Now i need to reload model and refresh some components in the page after download file action. I tried to add entire page to the AjaxRequestTarget in method onclick, after code invoked startDownload method. Reload page works fine but window with file to download doesn`t show.
I think that i have to do reload page in other, separate request (maybe i'm mistaken? ), because in this request i call 'window.location.href=....', but i don`t know how i can to enforce second request to reload page.
Does have someone some ideas what I do wrong ? And how can I resolve my problem ?
Seems you need something like this:
https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow
It seems that my implementation is simmilar to this from cwiki.apache.org website. In onRequest method i used getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler), and despite of this doesn`t work.
Is possible that reason of this is component, which cause request is added to target (because i add to target entire page and component - ajaxLink in this example, is child of this page)

Strategy when retrieving user name from session

I have a technical problem and I am not sure about the correct way to solve:
In a web page I am developing, I have to store the current user name from session (the person who is logged in) to "stamp" an action. (For instance, "The user created this file on "). My algorithm retrieves the user name from session but it obviously changes for each user. Therefore, the is always been the one of the user logged in, and not the creator name.
Any hint anyone?
Thanks!
So logically these are the steps you want?
User1 logs in
User1's name gets stored in Http session
User1 creates File42
System stores in database that User1 created File42 on Timestamp257
User1 logs out
User 2 logs in
User2's name gets stored in Http session
User2 views information about File42
System reads from database that User1 created File42 on Timestamp257
System displays information to User2
I think you might be missing the part where the system stores stuff (e.g. in a database).
EDIT: If you don't need persistence you could store shared data in the ServletContext. Note this is not a serious solution but could be used for a quick prototype or demo. Don't even think about doing this in production, it's got issues.
In your servlet do:
private static Map<String, FileData> fileAccess;
private class FileData {
String userName;
Date timeStamp = new Date();;
String fileName;
FileData(String userName, String fileName) {
this.userName = userName;
this.fileName= fileName;
}
}
public void init(ServletConfig config) {
String attributeKey = "fileAccess";
fileAccess = config.getServletContext().getAttribute(attributeKey);
if (fileAccess == null) {
fileAccess = new HashMap<String, FileData>();
config.getServletContext().setAttribute(attributeKey, fileAccess);
}
}
// in this example a POST means a user accesses a file
public void doPost(HttpServletRequest req, HttpServletResponse resp) {
// get the user name from the current session
String userName = req.getSession().getAttribute("userName");
// get the file name from the request (posted from the file access form)
String fileName = req.getParameter("fileName");
// check if we have the necessary data
if (userName == null || fileName == null) {
resp.getWriter().write("Invalid file access request");
resp.getWriter().flush();
return;
}
// create and fill file data wrapper
FileData fileData = new FileData(userName, fileName);
// store the file data in the shared fileAccess map.
// synchronized to block simultaneous acccess from different threads
synchronized (fileAccess) {
// note: any previously stored FileData object gets replaced
fileAccess.put(fileName, fileData);
}
// display the result to the user
display(fileData, resp);
}
// in this example a GET means a user views a file
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
// get the file name parameter from the request (sent as part of the view-file request)
String fileName = req.getParameter("fileName");
// check if we have the necessary data
if (fileName == null) {
resp.getWriter().write("Invalid view file request.");
resp.getWriter().flush();
return;
}
// get the file data from the shared fileAccess map.
// synchronized to block simultaneous acccess from different threads
synchronized (fileAccess) {
FileData fileData = fileAccess.get(fileName);
// display the result to the user
display(fileData, resp);
}
}
private void display(FileData fileData, HttpServletResponse resp) {
resp.getWriter().write("File accessed:");
resp.getWriter().write("User: " + fileData.userName);
resp.getWriter().write("File: " + fileData.fileName);
resp.getWriter().write("Timestamp: " + fileData.timeStamp);
resp.getWriter().flush();
}

Categories