问题
I am trying to pass an Object
from Servlet
's doPost()
to JSF's Managed bean
's action method. But I am unable to do that.
I have tried to set the value from Servlet
as:
request.getSession().setAttribute(key, "JYM");
And tried to retrieve it form Managed bean
as:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(key)
It is returning null
.
Also this is also returning null
from Managed bean
:
((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession().getAttribute(key);
Also from Managed bean
this is returning null
:
((HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false)).getAttribute(key)
I am passing the key as:
'${pageContext.request.contextPath}/uploadservlet;jsessionid=${pageContext.session.id}?key=<h:outputText value="#{uploadBean.key}" />'
uploadBean
is the name of the Managed bean
and the key
is generated as:
key = UUID.randomUUID().toString();
The key
remains unchanged in both of the Servlet and in managed bean. I have printed is to check.
How can I pass the Object
from Servlet
to Action
? Any pointer would be very helpful.
Update
The Managed bean
is in session scope.
Update
By using ServletContext
I am able to pass the value:
Here is what I did: In Servlet:
String key = request.getParameter("key");
if (getServletContext().getAttribute(key) == null) {
List<FileItem> fileFields = new ArrayList<FileItem>();
fileFields.add(fileField);
getServletContext().setAttribute(key, fileFields);
} else {
List<FileItem> fileFields = (List<FileItem>)getServletContext().getAttribute(key);
fileFields.add(fileField);
}
And from session scoped bean:
ServletContext servletContext = ((ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext());
List<FileItem> fileFields = (List<FileItem>)servletContext.getAttribute(key);
servletContext.setAttribute(key, null);
Now the fileFields
is not null anymore. What I understand is the ServletContext
behave like Application Scoped variable.
Update
HttpSessionListener
's implementation:
This is the class I have written:
public class UploadListener implements HttpSessionListener {
private HttpSession session = null;
public void sessionCreated(HttpSessionEvent event) {
session = event.getSession();
session.setMaxInactiveInterval(10);
}
public void sessionDestroyed(HttpSessionEvent event) {
session = event.getSession();
Set<String> keys = (Set<String>) session.getAttribute("key");
Map<String, Object> data = (Map<String, Object>) session.getServletContext().getAttribute("key");
data.keySet().removeAll(keys);
}
}
I am setting the value in the ServletContext
as:
String key = request.getParameter("key");
List<FileItem> fileFields = (List<FileItem>)getServletContext().getAttribute(key);
if (fileFields == null) {
fileFields = new ArrayList<FileItem>();
getServletContext().setAttribute(key, fileFields);
}
fileFields.add(fileField);
And this is the way I am calling the Servlet: '${pageContext.request.contextPath}/uploadservlet?key=<h:outputText value="#{uploadBean.key}" />'
.
回答1:
This construct will fail if the servletcontainer doesn't support identifying the HTTP session by jsessionid
URL fragment. This is by default supported, but it's possible to turn off this by servletcontainer specific configuration. So far it unfortunately looks like that your Weblogic server is configured as such.
Your best bet is then to exchange the data in the application scope. The randomness of UUID
is strong enough to not cause clashes. You should only need to make sure that the session-associated data is cleaned up when the session is destroyed. Otherwise the memory will leak away. For this, you can use a HttpSessionListener. Provided that you store the key in both the application scope (referencing the shared data) and in the session scope (referencing a set of all keys used so far), then the sessionDestroyed()
implementation can look like this:
public void sessionDestroyed(HttpSessionEvent event) {
Set<String> keys = (Set<String>) event.getSession().getAttribute("keys");
Map<String, Object> data = (Map<String, Object>) event.getSession().getServletContext().getAttribute("data");
data.keySet().removeAll(keys);
}
Update as per your update, a bit more elegant way to get/set them is:
String key = request.getParameter("key");
List<FileItem> fileFields = (List<FileItem>) getServletContext().getAttribute(key);
if (fileFields == null) {
fileFields = new ArrayList<FileItem>();
getServletContext().setAttribute(key, fileFields);
}
fileFields.add(fileField);
and
List<FileItem> fileFields = (List<FileItem>) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().remove(key);
// ...
来源:https://stackoverflow.com/questions/14275732/passing-value-from-servlet-to-jsf-action-method-in-weblogic