I'm using java7 and seam jboss.
I have set up a conversation-required and no-conversation in my pages.xml to prevent bookmarks from accessing the secured pages. However the issue now is that the Restful services when accessed are always redirecting to the no-conversation-view-id because the when accessing Rest we don't start a conversation.
Is it possible for the Restful component to start a conversation?
I don't want to annotate every Rest method with #Begin.
Thanks,
A context defines a namespace, a set of context variables. These work much the same as session or request attributes in the servlet spec. You may bind any value you like to a context variable, but usually we bind Seam component instances to context variables.
So, within a context, a component instance is identified by the context variable name (this is usually, but not always, the same as the component name). You may programatically access a named component instance in a particular scope via the Contexts class, which provides access to several thread-bound instances of the Context interface:
User user = (User) Contexts.getSessionContext().get("user");
You may also set or change the value associated with a name:
Contexts.getSessionContext().set("user", user);
Usually, however, we obtain components from a context via injection, and put component instances into a context via outjection.
4.1.9. Context search priority
Sometimes, as above, component instances are obtained from a particular known scope. Other times, all stateful scopes are searched, in priority order. The order is as follows:
Event context
Page context
Conversation context
Session context
Business process context
Application context
You can perform a priority search by calling Contexts.lookupInStatefulContexts(). Whenever you access a component by name from a JSF page, a priority search occurs.
Surc:Google
Related
I know in a web application, for every request it gets, spring creates a new instance of the bean in ints container.
I want to know how does spring differentiate between the requests and create new instances of bean accordingly?
This work is done by Request context listener where it takes the decision of instantiating beans based on incoming http request and discarding them once their life cycle is over. Session , Request scope beans are only relevant if the application context web aware, if otherwise IllegalStateException will be thrown.
And also refer -
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-scopes-other
I noticed that there are different bean scopes like:
#RequestScoped
#ViewScoped
#FlowScoped
#SessionScoped
#ApplicationScoped
What is the purpose of each? How do I choose a proper scope for my bean?
Introduction
It represents the scope (the lifetime) of the bean. This is easier to understand if you are familiar with "under the covers" working of a basic servlet web application: How do servlets work? Instantiation, sessions, shared variables and multithreading.
#Request/View/Flow/Session/ApplicationScoped
A #RequestScoped bean lives as long as a single HTTP request-response cycle (note that an Ajax request counts as a single HTTP request too). A #ViewScoped bean lives as long as you're interacting with the same JSF view by postbacks which call action methods returning null/void without any navigation/redirect. A #FlowScoped bean lives as long as you're navigating through the specified collection of views registered in the flow configuration file. A #SessionScoped bean lives as long as the established HTTP session. An #ApplicationScoped bean lives as long as the web application runs. Note that the CDI #Model is basically a stereotype for #Named #RequestScoped, so same rules apply.
Which scope to choose depends solely on the data (the state) the bean holds and represents. Use #RequestScoped for simple and non-ajax forms/presentations. Use #ViewScoped for rich ajax-enabled dynamic views (ajaxbased validation, rendering, dialogs, etc). Use #FlowScoped for the "wizard" ("questionnaire") pattern of collecting input data spread over multiple pages. Use #SessionScoped for client specific data, such as the logged-in user and user preferences (language, etc). Use #ApplicationScoped for application wide data/constants, such as dropdown lists which are the same for everyone, or managed beans without any instance variables and having only methods.
Abusing an #ApplicationScoped bean for session/view/request scoped data would make it to be shared among all users, so anyone else can see each other's data which is just plain wrong. Abusing a #SessionScoped bean for view/request scoped data would make it to be shared among all tabs/windows in a single browser session, so the enduser may experience inconsitenties when interacting with every view after switching between tabs which is bad for user experience. Abusing a #RequestScoped bean for view scoped data would make view scoped data to be reinitialized to default on every single (ajax) postback, causing possibly non-working forms (see also points 4 and 5 here). Abusing a #ViewScoped bean for request, session or application scoped data, and abusing a #SessionScoped bean for application scoped data doesn't affect the client, but it unnecessarily occupies server memory and is plain inefficient.
Note that the scope should rather not be chosen based on performance implications, unless you really have a low memory footprint and want to go completely stateless; you'd need to use exclusively #RequestScoped beans and fiddle with request parameters to maintain the client's state. Also note that when you have a single JSF page with differently scoped data, then it's perfectly valid to put them in separate backing beans in a scope matching the data's scope. The beans can just access each other via #ManagedProperty in case of JSF managed beans or #Inject in case of CDI managed beans.
See also:
Difference between View and Request scope in managed beans
Advantages of using JSF Faces Flow instead of the normal navigation system
Communication in JSF2 - Managed bean scopes
#CustomScoped/NoneScoped/Dependent
It's not mentioned in your question, but (legacy) JSF also supports #CustomScoped and #NoneScoped, which are rarely used in real world. The #CustomScoped must refer a custom Map<K, Bean> implementation in some broader scope which has overridden Map#put() and/or Map#get() in order to have more fine grained control over bean creation and/or destroy.
The JSF #NoneScoped and CDI #Dependent basically lives as long as a single EL-evaluation on the bean. Imagine a login form with two input fields referring a bean property and a command button referring a bean action, thus with in total three EL expressions, then effectively three instances will be created. One with the username set, one with the password set and one on which the action is invoked. You normally want to use this scope only on beans which should live as long as the bean where it's being injected. So if a #NoneScoped or #Dependent is injected in a #SessionScoped, then it will live as long as the #SessionScoped bean.
See also:
Expire specific managed bean instance after time interval
what is none scope bean and when to use it?
What is the default Managed Bean Scope in a JSF 2 application?
Flash scope
As last, JSF also supports the flash scope. It is backed by a short living cookie which is associated with a data entry in the session scope. Before the redirect, a cookie will be set on the HTTP response with a value which is uniquely associated with the data entry in the session scope. After the redirect, the presence of the flash scope cookie will be checked and the data entry associated with the cookie will be removed from the session scope and be put in the request scope of the redirected request. Finally the cookie will be removed from the HTTP response. This way the redirected request has access to request scoped data which was been prepared in the initial request.
This is actually not available as a managed bean scope, i.e. there's no such thing as #FlashScoped. The flash scope is only available as a map via ExternalContext#getFlash() in managed beans and #{flash} in EL.
See also:
How to show faces message in the redirected page
Pass an object between #ViewScoped beans without using GET params
CDI missing #ViewScoped and #FlashScoped
Since JSF 2.3 all the bean scopes defined in package javax.faces.bean package have been deprecated to align the scopes with CDI. Moreover they're only applicable if your bean is using #ManagedBean annotation. If you are using JSF versions below 2.3 refer to the legacy answer at the end.
From JSF 2.3 here are scopes that can be used on JSF Backing Beans:
1. #javax.enterprise.context.ApplicationScoped: The application scope persists for the entire duration of the web application. That scope is shared among all requests and all sessions. This is useful when you have data for whole application.
2. #javax.enterprise.context.SessionScoped: The session scope persists from the time that a session is established until session termination. The session context is shared between all requests that occur in the same HTTP session. This is useful when you wont to save data for a specific client for a particular session.
3. #javax.enterprise.context.ConversationScoped: The conversation scope persists as log as the bean lives. The scope provides 2 methods: Conversation.begin() and Conversation.end(). These methods should called explicitly, either to start or end the life of a bean.
4. #javax.enterprise.context.RequestScoped: The request scope is short-lived. It starts when an HTTP request is submitted and ends after the response is sent back to the client. If you place a managed bean into request scope, a new instance is created with each request. It is worth considering request scope if you are concerned about the cost of session scope storage.
5. #javax.faces.flow.FlowScoped: The Flow scope persists as long as the Flow lives. A flow may be defined as a contained set of pages (or views) that define a unit of work. Flow scoped been is active as long as user navigates with in the Flow.
6. #javax.faces.view.ViewScoped: A bean in view scope persists while the same JSF page is redisplayed. As soon as the user navigates to a different page, the bean goes out of scope.
The following legacy answer applies JSF version before 2.3
As of JSF 2.x there are 4 Bean Scopes:
#SessionScoped
#RequestScoped
#ApplicationScoped
#ViewScoped
Session Scope: The session scope persists from the time that a session is established until session termination. A session terminates
if the web application invokes the invalidate method on the
HttpSession object, or if it times out.
RequestScope: The request scope is short-lived. It starts when an HTTP request is submitted and ends after the response is sent back
to the client. If you place a managed bean into request scope, a new
instance is created with each request. It is worth considering request
scope if you are concerned about the cost of session scope storage.
ApplicationScope: The application scope persists for the entire duration of the web application. That scope is shared among all
requests and all sessions. You place managed beans into the
application scope if a single bean should be shared among all
instances of a web application. The bean is constructed when it is
first requested by any user of the application, and it stays alive
until the web application is removed from the application server.
ViewScope: View scope was added in JSF 2.0. A bean in view scope persists while the same JSF page is redisplayed. (The JSF
specification uses the term view for a JSF page.) As soon as the user
navigates to a different page, the bean goes out of scope.
Choose the scope you based on your requirement.
Source: Core Java Server Faces 3rd Edition by David Geary & Cay Horstmann [Page no. 51 - 54]
I have a Tomcat 6 instance running on my local machine.
I have made the following changes in its configuration:
In /conf/context.xml – changed the tag as follows
<Context crossContext="true">
In /conf/server.xml – changed the tag as follows
<Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true"
connectionTimeout="20000"
redirectPort="8443" />
Suppose I have a WAR file named SampleProject.war deployed here which extract to folder SampleProject.
In some servlet in this WAR, say SampleServlet, I write two blocks of code as follows :
ServletContext context1 = session.getServletContext();
and
ServletContext context2 = session.getServletContext().getContext("/SampleProject");
What is the difference between context1 and context2? I thought that both refer to the application context. But if I set some attribute in context1 and access in context2, I don't get the value in context2.
Any help would be appreciated.
I feel your question was slightly misunderstood and that you already had the basic understanding of the API i.e. once a web-app sets its crossContext="true" it could use getContext() to get access to a context that corresponds to some other web-app deployed on the server.
getServletContext().getContext() equals NULL unless <Context crossContext="true">
From what I've understood, your question actually is that in /SameWebApp why
ServletContext context1 = session.getServletContext();
context1.setAttribute("contextAttribute", new Object());
ServletContext context2 = session.getServletContext().getContext("/SameWebApp");
System.out.println(context1.equals(context2)); // prints false, or
System.out.println(context2.getAttribute("contextAttribute")); // prints null (at least they could have been clones)
In just one word, the answer is "Security". Imagine if you couldn't guarantee that an "adminEmail" context attribute has not been tampered with by an evil web-app having its crossContext=true. Your app could potentially help compromise itself as soon as that "Forgot Password" request comes! :)
A Dive into Tomcat internals
Tomcat 7 provides a class ApplicationContext implements ServletContext that returns from getContext("/context-root") as
if (context.getCrossContext()) {
// If crossContext is enabled, can always return the context
return child.getServletContext();
} else if (child == context) {
// Can still return the current context
return context.getServletContext();
} else {
// Nothing to return
return (null);
}
Here context belongs to current web-app and child represents the other web-app. But, hold on, what makes Tomcat call it a child?
These two actually aren't ApplicationContext but instances of StandardContext a class that implements Context but instead of servlet specific things holds Tomcat specific config settings for a web-app like crossContext, hostname, mimeMappings etc. StandardContext.getParent() gives you the Container and hence it has been referred to as a child above.
Anyways, we're interested in the case when child == context is true i.e. getContext() was called on the "/SameWebApp". The call is being delegated to StandardContext.getServletContext() which has been implemented to return a different instance of ApplicationContext.
This is why the attributes you set in context1 are not found in context2.
But wait, there's some more to it. Why does StandardContext.getServletContext() return like
return (context.getFacade());
A Tomcat instance is basically executing two types of Java code:
container provided, and
user deployed
The container code is "Trusted" and may need to run with elevated privileges sometimes. The user code, on the other hand, is not trusted and needs to be restricted from compromising Tomcat internals.
One of the things that Tomcat does to achieve this is always wrap an ApplicationContextFacade around the ApplicationContext (and hence the StandardContext as well). So just to recap, what appears to be a simple ServletContext implementation is actually a StandardContext mapped to an ApplicationContext which is then wrapped within an ApplicationContextFacade.
For further information on how the ApplicationContextFacade works using Reflection in tandem with Globals.IS_SECURITY_ENABLED and SecurityUtil.isPackageProtectionEnabled() settings please take a look at Why do Servlets access Tomcat ApplicationContext through a Facade on SO.
References:
Tomcat 7 Source Code (Download Link)
Absolutely those two context objects are different from another..
Context1 object gives current web application servlet context obj.
( ServletContext context1 = session.getServletContext();)
and
context2 object gives the servletcontext obj of specified web application
(ServletContext context2 = session.getServletContext().getContext("/SampleProject");)
you are setting object in one context and trying to retrieve using another context, so it is not possible to get attribute from another web application context by putting it in current application context. But you can get attribute resides in another web application context by using second method.
Think OO & java EE platform standards + security.
The first call returns the definitive servlet context for the current app, with all operations supported.
The second call returns a copy of the servlet context that could be for any app. As stated (rather vaguely!) in the javadoc, it's purpose is to allow you to obtain a RequestDispatcher, so you can dispatch to pages of other apps. It's other major but implicit requirement is to do this securely and to respect the Java EE specs, which do not allow sharing of session state or servlet context between apps. Imagine the terrible damage "rogue App B" could do to "good App A" if it could just change (or read) Servlet Context data by brute force. That's why it's a copy.
Hence, setting attributes on the copy, does not result in changes to the original. You could argue that the copy should throw some "Operation Not Supported Exception". Alternatively, you could argue that getRequestDispatcher should be refactored either to another class, or to allow an App Context URL to be passed in. ... But, unfortunately, neither of these things are true. B^)
I have a servlet which handles http get requests that I'd like to be able to share an object which is also used by a webservice im developing. They are both on the same tomcat server within the same web-app container. Im not sure best how to do it any ideas ?
You can share things across the webapp by storing them as attributes in the ServletContext (using setAttribute / getAttribute). You could create the object in an impelementation of ServletContextListener, store it in the ServletContext, and then retrieve it and use it from your web service and servlet.
I will expand on my comment here.
In the simplest case ServletContext.setAttribute/getAttribute would be fine. But some people rightly raised the questions about thread safety.
For this a better approach would be to store a shared POJO in a ServletContext during webapp initialization and get it wherever you need with ServletContext.getAttribute.
For this you need to implement ServletContextListener interface and declare it in your web.xml file.
<listener>
<listener-class>your.package.ServletContextListenerImpl</listener-class>
</listener>
This listener is called once when your webapp is loaded by the servlet container, and when it is about to be unloaded by the servlet container. In both cases it passes ServletContextEvent that has a handle to ServletContext. It is at that point that you want to set/removeAttribute that points to your shared object.
Because of this you may be certain that ServletContext.getAttribute will return a valid object when called from the Servlet.service or one of the do... methods.
As for attribute name, I would go with your Shared class classname. I would also add a static access method to your shared class to get it from the ServletContext, like this:
public class Shared
{
...
public static Shared fromServletContext ( final ServletContext context )
{
return (Shared) context.getAttribute( Shared.class.getName( ) );
}
}
The simplest option is create a Singleton - a class which allows only one instance in memory. Since you get it by calling a static method on the class itself it should be available to both the servlet and the WS
If my alternative understanding of the question is correct, the data which comes from request should be stored, and then retreived by the web-service. If this is supposed to run in a multi-user environment, you might consider using an in-memory database (HSQLDB) to temporarily store the data. Then you will be able to retrieve it with your web-service, based on some criteria I cannot foretell.
If this is application-specific data (accessible by all users (sessions)), then use ServletContext#set/getAttribute(). If this is user (session)-specific data, then use HttpSession#set/getAttribute().
Let the servlet class set the object in the desired scope (application or session) by a specific attribute key and let the webservice get the object from the desired scope by the same attribute key.
I think you rather need the HttpSession.
The singleton story makes no sense here.
I have a Java EE application consisting of 1 web module and 1 EJB module. Inside my EJB module I have a stateful session bean containing my business logic.
What I would like is:
When a user logs in to my web application and creates a new session in the web tier I want that user to be assigned an instance of my session bean.
At the moment a session is being created in the web tier as expected but I am unsure about how to map the session in the web tier to a new EJB session each time. Currently I am invoking my EJB from my Servlet meaning that only 1 instance of the bean is being created. I am trying to get a 1-1 mapping between web sessions and sessions in my EJB layer.
I know this could be achived easily using application clients but any advice / design patterns on how I could achive this in the web tier would be greatly appreciated.
Stateful Sessions are not always a good choice, sometimes using persistence to a DB is easier.
In the servlet, as process a request from a user, obtain the "handle" to your SFSB. Put that "handle" into your HttpSession. Now when the next request for that user arrives you have the handle ready.
With EJB 3.0 do it like this.
Declare the bean reference with #EJB at class scope, this sets up the reference you'll use later
#EJB
(name=“CounterBean", beanInterface=Counter.class)
public class MyStarterServlet …
When you process the request: access the EJB using JNDI and the declared bean name, note that this code is in your doGet() and/or doPost() method, the "counter" variable must be local (on the stack), as the servlet object is shared between potentually many requests a the same time.
Context ctx = new InitialContext();
Counter counter = (Counter)
ctx.lookup(“java:comp/env/CounterBean”);
counter.increment();
Store the interface in the HttpSession object to retrieve as needed
session.setAttribute(“counter”, counter);