Why shouldn't I use a JSF SessionScoped bean f

2019-02-10 20:40发布

问题:

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

回答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.

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.



回答2:

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.



回答3:

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..