I have the following code in a listener method:
FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("time", new Date());
When a button is clicked the following code is executed
System.out.println(FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("time"));
One could except that "time" is null when the listener was not executed while processing the current request, but: it seems like the "time" object survives the request processing. So when "time" has been set sometimes in the past it stays there... can anybody explain this? Thanks.
Found the answer here:
http://wiki.icefaces.org/display/ICE/Compatibility
Scopes
By default, ICEfaces 1.x operated under what was referred to as extended request scope. In a nutshell, extended request scope refers to the behaviour that a new request is only associated with a change in view. This means that Ajax requests that occur within an existing view are not treated by ICEfaces as new requests. A request is not considered a new request unless it results in a new view so request-scoped beans would not be recreated until a new view was created. This behaviour was configurable to allow for the more standard definition of request scope but was considered necessary at the time because the existing standard scopes (request, session, application, none) were not granular enough.
Related
How do I change HTTP method in javax,servlet.RequestDispatcher?
I have some old service APIs that support GET and POST, The new version supports DELETE method for removing a record which used to happen through POST earlier.
We are decommissioning old version APIs by setting RequestDispatcher.forward() for old end points (stop gap arrangement until clients change). everything was cool except this POST to DELETE mapping.
Any solution there for this problem without adding POST end point for delete operation in new API?>
Although I agree using the next layer after your servlets would be a better choice, this is interesting. It use to be common to wrap an incoming request to add request based functionality (IE: auth state, etc). The HttpServletRequestWrapper was used to accomplish this. You could do the following if you just need to change the method:
class PostDeleteAdapter extends HttpServletRequestWrapper {
public String getMethod(){ return "POST"; }
}
You may also change other aspects of the incoming request if you need to further adapt the request. This may play well with your servlet containers RequestDispatcher, however it's dependent upon the container entirely.
I think you can't do it using servlet API. You can do what you want creating a new request, processing it's response and sending it back through the original response (in the servlet).
Some http clientes might help you. See Apache HTTP client:
http://hc.apache.org/httpclient-3.x/methods/delete.html)
I am working on a Java Portlet (extending GenericPortlet), using JBoss 7.02 and LifeRay Portal 6.1.0 GA1. This is one of the bundles that can be downloaded from LifeRay's release archive.
During deployment, when the init() method is called, getRequestDispatcher() returns null. Below is the exact error message:
09:22:15,972 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/my-portlet-name]] (MSC service thread 1-15) Error during mapping: java.lang.NullPointerException
Below is a snippet from my init() method:
PortletConfig config = getPortletConfig();
PortletContext context = getPortletContext();
PortletRequestDispatcher normalView = context.getRequestDispatcher("/portlet.jsp");
As a temporary workaround, I have moved all getRequestDispatcher() calls to doView() where it executes without problem. I do not understand why getRequestDispatcher() can locate portlet.jsp when called during doView, but not when its called during init()
Am I missing a preceding call of some other method that would resolve this? Is this a known issue?
Thanks for any help.
Getting the request dispatcher in the doView is the only place I've seen it done. I would imagine that it returns null during init because there is no actual request to dispatch.
Typically the init method is used for time-expensive operations that you don't want to incur for each request. This might be something like reading data from a file, or creating a reusable SQL connection.
You should also keep in mind that you should keep any portlet state thread safe. Don't create class or object variables that can only be used for one request at a time. The portlet methods are not inhererently thread safe, so you need to make sure that whatever variables a request is interacting with won't be manipulated by another request that is executing concurrently.
I'm not familiar with Portlets, but the answer should be the same as for Servlets.
The init() method is called exactly once, when your application is initially deployed. There is no active request (no one is asking for anything) or response (no one is going to read what the output is). Therefore, it is very reasonable forgetRequestDispatcher() to return null. In doView(), when you're handling a request and response, it makes sense to ask another resource to generate part (or all) of the response.
To address your question directly, getRequestDispatcher() has no problem locating portlet.jsp from init(); it's the request that's missing. (Where do you expect to see the result of portlet.jsp, anyway?)
If you do want to print some output during initialization, you can try logging it to a file, if your application is set up for that. Or, you can display data on System.out, if you know where the container's console is. (I use this second option quite often with servlets.)
I'm developing a single page jQuery & Backbone.js web app. The backend is a JBoss 6 application server.
Until now we had the following structure:
There is only one servlet (front controller). Every request from the JavaScript client goes through here.
In the servlet - at the first request of a certain JS client - I make a look p to a stateful session bean. For the next requests of this client, I store the result of the look up in an HTTP session container. So every JS client has exactly one stateful session bean. This connection is kept by a session cookie.
Now I have an additional requirement:
When the user has two browser tabs (in one browser), they should have two isolated instances of the web app in every browser tab. Because of that I have a problem with session cookies because this session cookie is for all browser tabs.
I have to change the structure so that:
The servlet has to generate a new session ID for the first request of a certain JS client. This session ID is communicated to the client.
With every POST to the backend the JS client has to send this session ID.
My question is:
Until now I saved the result of the look up in an HTTP Session object and I hadn't to think about generating a session ID. But now I have to store this somewhere else, where?
Has anybody experience with this kind of setting and can help me?
Update:
Thank you BalusC for this very interesting approach.
When I understood you well, this means:
All individual JS clients of the tabs of one browser share one HTTP session object. And in this HTTP session object, every tab has its own entry point. That sounds really good. So I still can use the whole HTTP session infrastructure and don't have to reinvent the wheel.
Autogenerate an unique value on the initial GET request which you store and pass around on every subsequent postback as a hidden input value. Use this unique value as identifier of the session attribute representing the view-scoped data.
During the 1st request on a brand new session, do:
Map<String, ViewData> viewScope = new HashMap<String, ViewData>();
session.setAttribute("viewScope", viewScope);
(the ViewData represents the view-specific data you'd like to track across postbacks on the same view)
During every GET request, do:
String viewDataId = UUID.randomUUID().toString();
viewScope.put(viewDataId, new ViewData());
request.setAttribute("viewDataId", viewDataId);
During generating the HTML, do:
<input type="hidden" name="viewDataId" value="${viewDataId}" />
During every POST request, do:
ViewData viewData = viewScope.get(request.getParameter("viewDataId"));
// Get/set view-specific data in there.
Make sure that jQuery also passes this hidden input around (which shouldn't be a big problem if you already properly use $(form).serialize() or e.g. AjaxForm plugin to ajaxify the forms).
If you're familiar with Java EE's MVC framework JSF, then it may be useful to know that its #ViewScoped annotation works roughly the same as described above. See also a.o. How to choose the right bean scope?
You can use session tracking with URL rewriting. See here:
Session shared in between tabs
I have a #ConversationScoped bean, with a start method, like so:
#PostConstruct
public void start() {
if (conversation.isTransient()) {
conversation.begin();
log.debug("conversation.getId(): " + conversation.getId());
}
}
My problem is that every time the page is refreshed a new conversation is started, a new conversation is also started every time I have an AJAX call to a method in the bean (which is my main problem).
What I really want to happen is for the sam conversation to hang around until I manually call conversation.end(). What am I missing here?
Slightly off-topic, but hopefully valuable:
I'm not 100% sure that #PostConstruct is the right place to start a conversation. I'd rather use a faces-event like this:
<f:metadata>
<f:event type="javax.faces.event.PreRenderViewEvent"
listener="#{myBean.init}" />
</f:metadata>
and start the conversation if you are sure that you are not in a JSF-postback request.
public void init() {
if (!FacesContext.getCurrentInstance().isPostback() && conversation.isTransient()) {
conversation.begin();
}
}
If you use Seam 3, it's even easier:
<f:metadata>
<s:viewAction action="#{myBean.init}" if="#{conversation.transient}" />
</f:metadata>
Did you checked that the (AJAX) calls include the conversation ID parameter (cid)?
If that's missing, a new conversation is expected to start for each call.
The concept of the JSR-299 builtin Conversation is a bit broken. At least for JSF apps. Using the #PreRenderViewEvent would basically drop all the benefits of this approach as it would make every #ConversationScoped bean longRunning.
You might try to use Apache MyFaces CODI #ConversationScoped instead. CODI is a CDI Extension library which is known to work well with Apache OpenWebBeans and also with Weld.
It additionally also provides #ViewScoped, #ViewAccessScoped (kind of an auto-conversation) and #WindowScoped contexts.
More at: https://cwiki.apache.org/confluence/display/EXTCDI/Index
It's all in the docs:
The conversation scope is active:
during all standard lifecycle phases of any JSF faces or non-faces request.
The conversation context provides access to state associated with a particular conversation. Every JSF request has an associated conversation. This association is managed automatically by the container according to the following rules:
Any JSF request has exactly one associated conversation.
The conversation associated with a JSF request is determined at the beginning of the restore view phase and does not change during the request.
Any conversation is in one of two states: transient or long-running.
By default, a conversation is transient
A transient conversation may be marked long-running by calling Conversation.begin()
A long-running conversation may be marked transient by calling Conversation.end()
All long-running conversations have a string-valued unique identifier, which may be set by the application when the conversation is marked long-running, or generated by the container.
If the conversation associated with the current JSF request is in the transient state at the end of a JSF request, it is destroyed, and the conversation context is also destroyed.
If the conversation associated with the current JSF request is in the long-running state at the end of a JSF request, it is not destroyed. Instead, it may be propagated to other requests according to the following rules:
The long-running conversation context associated with a request that renders a JSF view is automatically propagated to any faces request (JSF form submission) that originates from that rendered page.
The long-running conversation context associated with a request that results in a JSF redirect (a redirect resulting from a navigation rule or JSF NavigationHandler) is automatically propagated to the resulting non-faces request, and to any other subsequent request to the same URL. This is accomplished via use of a GET request parameter named cid containing the unique identifier of the conversation.
The long-running conversation associated with a request may be propagated to any non-faces request via use of a GET request parameter named cid containing the unique identifier of the conversation. In this case, the application must manage this request parameter.
When no conversation is propagated to a JSF request, the request is associated with a new transient conversation. All long-running conversations are scoped to a particular HTTP servlet session and may not cross session boundaries. In the following cases, a propagated long-running conversation cannot be restored and reassociated with the request:
When the HTTP servlet session is invalidated, all long-running conversation contexts created during the current session are destroyed, after the servlet service() method completes.
The container is permitted to arbitrarily destroy any long-running conversation that is associated with no current JSF request, in order to conserve resources.
Author:
Gavin King, Pete Muir
IMHO CDI conversations are broken by design and struberg pointed out a promising alternative. In my App I've the same problem and currently I'm refactoring it to CDI + CODI 1 and it just feels right. #ConversationScoped solves all those problems. While refactoring my App I could solve a lot of nasty cases with #ViewAccessScoped. Thank you struberg for pointing us to it!
Oddly enough, if you add an event listener to your Facelet, even if it calls an empty method, the form action of the generated source will have the 'cid' parameter and therefore, the AJAX call will not create a new conversation. Without the event listener, the 'cid' is missing the in the form action.
<f:metadata>
<f:event listener="#{myBean.dummy}" type="preRenderView" />
</f:metadata>
MyBean.java
public void dummy() {}
i want a mechanism in my web app as described below:
user will enter mydomain.com/CompanyName , depending upon the CompanyNameit will show its logo and its customized page, and i will take that parsed parameter in session again upon each request i will compare the parsed CompanyName and one stored in session , and if they matched then application will show the requested page with user's data.else it will be redirected to login page.
and the main thing is i want this thing in JSF arch.
i tried taking a servlet that will resolve all request and it will parse and then will dispatch the request to prefered servlet,but problem is it goes in loop as again it resolves to the same controller servlet,
You can do this via a phase listener. You can define a global one in faces-config.xml (or using annotations, if JSF 2.0 is used)
<lifecycle>
<phase-listener>com.yourcompany.CompanyPhaseListener</phase-listener>
</lifecycle>
There you have access to the FacesContext, from which you can obtain the current request URI. Parse it and store the appropriate attributes in the request, which you can later read on your pages.
The phase listener is executed on the specified phase(s), and perhaps you should choose RENDER_RESPONSE
For affecting the way your URLs appear in the browser, check PrettyFaces.
i tried taking a servlet that will resolve all request and it will parse and then will dispatch the request to prefered servlet,but problem is it goes in loop as again it resolves to the same controller servlet,
Use a Filter instead. It by default doesn't listen on forwarded requests, so you won't get an infinite loop on forwarding.