I'm wondering why there is no single notice about the importance of immutability property when storing serializable objects in the HTTP session? I tried to check the JSF and Servlet API specifications but couldn't find anything related.
I've seen a specific problem in the case of JSF based clustered application where #SessionScoped managed bean is mutable i.e. user-modified parameter is stored as a field of this managed bean.
Trouble begins when the node "owning" the session (thanks to stickiness requirement in servlet API specs) dies and different node starts to take over serving the session, the latest state is lost. In fact, only the initial state is replicated. I believe this is because managed beans are placed in session (and replicated to backup nodes) only when they are created for the first time, at least this is confirmed by my tests performed on Websphere.
While one can debate whether this is a good design or not, JSF and even Servlet API still allows it to happen.
I also found some note in Oracle docs:
As a general rule, all session attributes should be treated as immutable objects if possible. This ensures that developers are consciously aware when they change attributes. With mutable objects, modifying attributes often requires two steps: modifying the state of the attribute object, and then manually updating the session with the modified attribute object by calling javax.servlet.http.HttpSession.setAttribute(). This means that your application should always call setAttribute() if the attribute value has been changed, otherwise, the modified attribute value will not replicate to the backup server.
Apart from manually updating the attribute as described above, is there any clean solution, preferably in an idiomatic JSF way?
In WebSphere Liberty, there is a property called
writeContents = "GET_AND_SET_ATTRIBUTES"
for the mutable session objects. For details, please see:
https://github.com/OpenLiberty/open-liberty/issues/2802
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.liberty.autogen.nd.doc/ae/rwlp_config_httpSessionCache.html
Same property apply for database persistence.
Related
Going through an abstract in a book, I came across this:
On the server side, the state can be stored as a shallow copy or as a
deep copy. In a shallow copy, the state is not serialized in the
session. By default, JSF Mojarra uses shallow copy.
I seriously couldn't understand this.
Since in the above case, we will have-
javax.faces.STATE_SAVING_METHOD set to server,
and an input hidden field javax.faces.ViewState with a value somewhat like this "2870966362946771868:-8449289062699033744".
Obviously, the server must have maintained internally an state corresponding to the above hidden field.
But going by the abstract, if the state is not serialized in the session, then where it is?
Furthermore, I have noticed one thing that if my Managed bean(ViewScoped) is not implementing marker interface Serializable with STATE_SAVING_METHOD set to server, then in Mojarra, the NotSerializablEexception doesn't occur, while in MyFaces it does.
But going by the abstract, if the state is not serialized in the session, then where it is?
It exist of references to instances already in the HTTP session which in turn is not necessarily serialized.
The key context param for this is javax.faces.SERIALIZE_SERVER_STATE which defaults in MyFaces to true and in Mojarra to false. When set to true, you will sooner see NotSerializableException on artifacts which are mistakenly not Serializable. Otherwise, you're dependent on server configuration. For example, Tomcat by defaults serializes the entire HTTP session including all its attribtues during a server restart. Some servers, particularly those running in cluster, can even be configured to serialize entire HTTP sessions during runtime. In such cases you would also see NotSerializableException during restart or failover.
Mojarra has plans to make javax.faces.SERIALIZE_SERVER_STATE setting default to true as per 2.3, particularly because this setting would proactively prevent unforeseen developer mistakes such as assigning non-serializable instances of JSF artifacts such as UIComponent or even FacesContext as properties of a non-requestscoped bean. It would otherwise result in problems as Stuck thread at UIComponent.popComponentFromEL, Java Threads at 100% CPU utilization using richfaces UIDataAdaptorBase and its internal HashMap and java.lang.IllegalStateException at com.sun.faces.context.FacesContextImpl.assertNotReleased.
On the other hand, in older MyFaces versions, this setting broke EJBs injected in serializable managed beans due to the wrong classloader being used to resolve EJB proxies during deserialization. This was fixed in MyFaces 2.0.15 and 2.1.9 as per MyFaces issue 3581. See also #EJB in #ViewScoped #ManagedBean causes java.io.NotSerializableException.
If I'm informed correctly, every request for/from a XPage is processed in a new thread in the JVM on the Domino server.
Hence, all objects stored in the applicationScope which might be modified concurrently by different users should be thread-safe. However, all the articles about thread safety I have read so far never say anything about the necessity of using thread-safe objects in the sessionScope.
A user could, for example, run the same XPage (which modifies a sessionScope object) in two different browser tabs at the same time.
In my opinion, that sessionScope object has to be thread-safe too, or did I get something wrong?
In general, whenever there is more than one thread trying to access the same object and at least one of them tries to modify the state of the object it needs to be threadsafe.
So in this case if two browser tabs try to access same xpage or different xpages but trying to access the same session scope object and at least one of them trying to modify that object, we need to ensure it is threadsafe.
As #Tiny commented regarding the view scoped beans, "According to the JSF specification, AJAX requests made from the same view are queued on the client side. Therefore, the possibility of concurrent access in a view scoped bean is zero. A view scoped bean is not shared across different tabs / windows of the same browser".
Refer to Section 13.3.2 of jsf 2.0 specification.
According to the documentation,
Global: Component is shared among all users.
Session: Separate instances of the component are provided to each user.
Is that means, for global component, there is only one instance for the whole nucleus system..
If this is true, how does it valid for components like ‘/atg/dynamo/transaction/TransactionManager’ and most of the droplets..?
Because those components are used by several users at a single moment
Edited:
I understood the ‘TransactionManager’ behavior. According to the definition there should be single transaction manager, and he should keep transaction objects per each transaction.
But my question is still valid for droplets like, foreach, switch, etc (most of them are globally scoped)
If there is only one instance of corresponding class for the whole nucleus system, isn't it having bad effects on performance?
Historically there were three different types of scope available in ATG. This has now increased to 5, with the addition of Window (generally only used in the CSC application so try not to use it) and Prototype (added to support the use of Endeca Cartridge Handlers).
As you highlight from the documentation, global component is instantiated once and is shared by all users, while a session component is created once for a given session and is shared by all requests of that session. Similarly a request scoped component is freshly instantiated for each request that uses it.
From a performance point of view, resolving the path to an existing component (for example a globally scoped component like ForEach) takes a little time, but instantiating a new object (in other words a request scoped component) is comparatively more expensive.
So in the case of a ForEach droplet it gets instantiated once but in the service method it actually extracts the parameters from the request:
String elementName = pRequest.getParameter(ELEMENT_NAME);
This means that your globally scoped component is thread safe in that it only takes in parameter from the current request. So in general, if a component can be shared by multiple users, without worrying about synchronisation, it should be globally scoped versus session or request scoped. (The rule of thumb should be that if your droplet is request scoped, you are likely doing it wrong).
If you are aware of Design Patterns, $scope=global is the equivalent of making an ATG component a singleton.
ATG Commerce has 4 different scopes of components
Global: This is the default scope of the component, if scope isn’t defined.
These components will be initialized once and will be there as a
global object. It’s a best practice to have all the Droplets, Tools,
Manager and other Configuration components as global
Session: The scope and the values maintained will be unique for every
session. The session scope components generally used are ShoppingCart
(Order), Profile, SearchFormHandler etc..
Request:The scope and the values maintained will be unique for every request. The request scope components generally used are FormHandlers to process individual requests.
Window: The scope and the values maintained will be unique till
the browser window is closed. The Window scope components
generally used in CSC application for ShoppingCart component etc..
It’s good to use components with any scope based on business
requirement but having it declared as Global and using it will be a
benificial for improving the performance of the application.
It’s a thumb rule have the business logic in Global scope components and refer it from lower scoped components if required.
This will reduce the threads waiting to be Garbage collected.
I have a drop down menu from which user selects an item(in my case project he is working on), most of the data displayed by a webpage depends on that selection. So I have couple of view scoped beans that call EJB beans which do database queries that depend on the selected project.
I want to cache most of that data in order to reduce Database queries, but when user changes project it has to notify other beans that change has happened and new data needs to be fetched.
So I had an idea:
projectChangeManager (session scoped managed bean), saves which project is selected, notifies it's subscribers when project changes. Has #PreDestory method implemented where I cleanup observers.
project observers (view scoped managed beans), gets data from EJB based on project selection, has onProjectChange() method which fetches new data from EJB. Has #PreDestory method implemented where projectChangeManager.detach(this) is called to unsubscribe from projectChangeManager.
Is this reasonable approach in JSF? Or is it better not to implement observer pattern but just when user changes project I fetch all cached data and save it in session bean and then in ViewScoped bean I just access that data from SessionScoped bean? Or is there a better way?
To me this looks like overengineering. Initially, I would probably just let every managed bean call the repository/EJB whenever it needs data. Then rely on caching in the persistence layer (JPA/Hibernate/whatever you use).
If this turns out to be a performance problem, you can consider some hand-rolled caching solution.
Even in that case I still don't quite see the advantage of your observer approach. Your second approach (cache in session bean, access from ViewScoped bean) looks simpler and should work just as well.
Finally, if you decide to use caching, consider how to avoid a stale cache. If you cache per session, changes in one session will not be visible in another session. Incidentally, I think this is another reason to leave caching to the persistence layer.
I'm developing a java EE web app using JSF with a shopping cart style process, so I want to collect user input over a number of pages and then do something with it.
I was thinking to use an EJB 3 stateful session bean for this, but my research leads me to believe that a SFSB is not tied to a client's http session, so I would have to manually keep track of it via an httpSession, some side questions here . . .
1) Why is it called a session bean, as far as I can see it has nothing to do with a session, I could achieve the same by storing a pojo in a session.
2) What's the point of being able to inject it, if all I'm gonna be injecting' is a new instance of this SFSB then I might as well use a pojo?
So back to the main issue I see written all over that JSF is a presentation technology, so it should not be used for logic, but it seems the perfect option for collecting user input.
I can set a JSF session scoped bean as a managed property of all of my request beans which means it's injected into them, but unlike a SFSB the JSF managed session scoped bean is tied to the http session and so the same instance is always injected as long as the http session hasn't been invalidated.
So I have multiple tiers
1st tier) JSF managed request scoped beans that deal with presentation, 1 per page.
2nd tier) A JSF managed session scoped bean that has values set in it by the request beans.
3rd tier) A stateless session EJB who executes logic on the data in the JSF session scoped bean.
Why is this so bad?
Alternative option is to use a SFSB but then I have to inject it in my initial request bean and then store it in the http session and grab it back in each subsequent request bean - just seems messy.
Or I could just store everything in the session but this isn't ideal since it involves the use of literal keys and casting . etc .. etc which is error prone. . . and messy!
Any thoughts appreciated I feel like I'm fighting this technology rather than working with it.
Thanks
Why is it called a session bean, as far as I can see it has nothing to do with a session, I could achieve the same by storing a pojo in a session.
From the old J2EE 1.3 tutorial:
What Is a Session Bean?
A session bean represents a single
client inside the J2EE server. To
access an application that is deployed
on the server, the client invokes the
session bean's methods. The session
bean performs work for its client,
shielding the client from complexity
by executing business tasks inside the
server.
As its name suggests, a session bean
is similar to an interactive session.
A session bean is not shared--it may
have just one client, in the same way
that an interactive session may have
just one user. Like an interactive
session, a session bean is not
persistent. (That is, its data is not
saved to a database.) When the client
terminates, its session bean appears
to terminate and is no longer
associated with the client.
So it has to do with a "session". But session not necessarily means "HTTP session"
What's the point of being able to inject it, if all I'm gonna be injecting' is a new instance of this SFSB then I might as well use a pojo?
Well, first of all, you don't inject a SFSB in stateless component (injection in another SFSB would be ok), you have to do a lookup. Secondly, choosing between HTTP session and SFSB really depends on your application and your needs. From a pure theoretical point of view, the HTTP session should be used for presentation logic state (e.g. where you are in your multi page form) while the SFSB should be used for business logic state. This is nicely explained in the "old" HttpSession v.s. Stateful session beans thread on TSS which also has a nice example where SFSB would make sense:
You may want to use a stateful session
bean to track the state of a
particular transaction. i.e some one
buying a railway ticket.
The web Session tracks the state of
where the user is in the html page
flow. However, if the user then gained
access to the system through a
different channel e.g a wap phone, or
through a call centre you would still
want to know the state of the ticket
buying transaction.
But SFSB are not simple and if you don't have needs justifying their use, my practical advice would be to stick with the HTTP session (especially if all this is new to you). Just in case, see:
Stateless and Stateful Enterprise Java Beans
Stateful EJBs in web application?
So back to the main issue I see written all over that JSF is a presentation technology, so it should not be used for logic, but it seems the perfect option for collecting user input.
That's not business logic, that's presentation logic.
So I have multiple tiers (...)
No. You have probably a client tier, a presentation tier, a business tier, a data tier. What you're describing looks more like layers (not even sure). See:
Can anybody explain these words: Presentation Tier, Business Tier, Integration Tier in java EE with example?
Spring, Hibernate, Java EE in the 3 Tier architecture
Why is this so bad?
I don't know, I don't know what you're talking about :) But you should probably just gather the multi page form information into a SessionScoped bean and call a Stateless Session Bean (SLSB) at the end of the process.
1) Why is it called a session bean, as far as I can see it has nothing to do with a session, I could achieve the same by storing a pojo in a session.
Correction: an EJB session has nothing to do with a HTTP session. In EJB, roughly said, the client is the servlet container and the server is the EJB container (both running in a web/application server). In HTTP, the client is the webbrowser and the server is the web/application server.
Does it make more sense now?
2) What's the point of being able to inject it, if all I'm gonna be injecting' is a new instance of this SFSB then I might as well use a pojo?
Use EJB for transactional business tasks. Use a session scoped managed bean to store HTTP session specific data. Neither of both are POJO's by the way. Just Javabeans.
Why shouldn't I use a JSF SessionScoped bean for logic?
If you aren't taking benefit of transactional business tasks and the abstraction EJB provides around it, then just doing it in a simple JSF managed bean is indeed not a bad alternative. That's also the normal approach in basic JSF applications. The actions are however usually to be taken place in a request scoped managed bean wherein the session scoped one is been injected as a #ManagedProperty.
But since you're already using EJB, I'd question if there wasn't a specific reason for using EJB. If that's the business requirement from upper hand, then I'd just stick to it. At least, your session-confusion should now be cleared up.
Just in case you're not aware of this, and as a small contribution to the answers you have, you could indeed anotate a SFSB with #SessionScoped, and CDI will handle the life cycle of the EJB... This would tie an EJB to the Http Session that CDI manages. Just letting you know, because in your question you say:
but my research leads me to believe that a SFSB is not tied to a client's http session, so I would have to manually keep track of it via an httpSession, some side questions here . . .
Also, you could do what you suggest, but it depends on your requirements, until CDI beans get declarative transaction support or extended persistence contexts etc, you'll find yourself writing a lot of boilerplate code that would make your bean less clean. Of course you can also use frameworks like Seam (now moving to DeltaSpike) to enhance certain capabilities of your beans through their extensions.
So I'd say yes, at first glance you may feel it's not necessary to use a stateful EJB, but certain use cases may be better solve through them. If a user adds a product to his cart, and another user adds this same product later, but there is only one unit in stock, who gets it? the one who does the checkout faster? or the one who added it first? What if you want to access your entity manager to persist a kart in case the user decides to randomly close his browser or what if you have transactions that spawn multiple pages and you want every step to be synchronized to the db? (To keep a transaction open for so long is not advisable but maybe there could be a scenario where this is needed?) You could use SLSB but sometimes it's better and cleaner to use a SFSB..