I know that there are many different architectures exist. In this question I consider 3-tiers architecture (presentation-services (busyness logic)-data access layer (DAOs). And I want to concentrate on how presentation tier works with services tier.
The problem I met is standard. I have stateless services layer, and I think it should be stateless for the sake of scalability and performance.
I also have stateful presentation layer. For example, when user fills some form and inputed values don't pass validation, it's good practice to show all fields with inputed values and to point to incorrect fields.
So, imagine that we have FooBean with methods setFoo (Foo f), getFoo () and doSave (). Bean has Session scope.
And we want to save (persist) new instance of Foo. What we do is call method setFoo () and then call method doSave (). If saving failed than user will see just filled form with all inputed values (getFoo () method is called).
That's nice, but now imagine that user clicks Create Foo link, fills all fields, tries to save but doesn't pass validation? He will see filled form again. And then he clicks on 'Create Foo' again (he wants to create 2 Foo objects simultaneously). He will see filled form with pointed errors. But it's bad, because he didn't fill this (second, new) form yet.
If we change FooBean scope to Request, than we won't be able to show filled form when it's necessary (after saving failed).
So, what is the way out? What is the correct solution? It can be JSF-specific or general.
You need something called "conversation". There are a number of ways for achieving this.:
MyFaces orchestra
JBoss seam
A conversation is either automatically or manually managed scope that is greater than a request, but is smaller than a session. Ideally it should store your beans as long as they are needed to be stored - i.e. in one conversation. So from your example, the first conversation will end at the point the use navigates away from the first page.
MyFaces orchestra (I can't tell for seam) can also differentiate between different browser windows/tabs.
Related
Should I have a bean for every form, datatable etc in JSF?
For example, I have a form for registration, which simply has 2 fields and a button which are:
nickname, password, submit
Should submitting this form go to a RegistirationFormBean or somewhere in UserBean or UserServiceBean?
What is the best practice?
Thank you.
To decide whether or not you should create a #ManagedBean exclusively for a component of the page (e.g. form, datatable), I believe you should think about the modularity of your design.
The 1st question you should ask yourself is: Will the component be re-used in many pages?. For example, on sensitive pages such as ChangePassword or DeleteAccount, usually, you will ask the user to enter the current password to validate his identity before performing any logic. In this case, you should definitely have an exclusive bean for the validating password component so that you can re-use the component again and again without having to re-code the validating function every time.
Secondly, I usually use #ManagedBean as a place to hold all the related functions that work toward the same goal. This grouping of functions can be pretty subjective. For example, I can have a page called CreateProduct.xhtml with a bean called CreateProductBean that has all the functions for creating a product. In this case, it's like 1 bean per view. Another way is to have a bean called ProductManager that has functions for everything related to the Product object (i.e. create, read, update, remove). In this case, it's like 1 bean for many views (e.g. CreateProduct.xhtml, RemoveProduct.xhtml). For ease of future maintenance and division of work, I usually use 1 bean per view. The 2nd approach 1 bean for many views is also good on certain situations but I suddenly cannot think of an example yet :P... I will update my answer when I got a good one ;).
Thirdly, I prefer to follow the 3-tier MVC model and separate back-end logic away from the front-end. For example, to persist a new account in the database, I will inject an #EJB or a #WebServiceRef to ask the back-end system to perform the necessary logic. It's definitely more maintenance friendly in the future :).
So, using your RegisterAccount example, I will have
1 bean called UserExistenceValidator to check if a nickname exists in the database. During registration, I can throw an error if the user chooses a nickname that is taken. I can also use this bean to check if a user exists in the AddFriend.xhtml page.
Another bean called RegistirationFormBean to capture a user's inputs and talk to the back-end to persist the new account.
Its actually a pretty interesting topic to tweak any JSF lover's brain, so I could not resist myself and I would like to go with detail explanation.
One of the very interesting and significant cause behind the invention of JSF was, wiring client side event to server side application code like any swing application and getting rid of handing of request and response object explicitly. Like any swing application, we can now simply bind any client side event (say, button click) with some server side code to handle that event, without worrying the facts and complexities of writing an web application.
As a result when designing any web apps, that uses JSF, the designer can focus on the user experience as easily as designing an event driven swing application. So as the consequence, you design the view pages and identify the events to do tasks and navigate between the views. Finally you write some server side codes to be executed in those events, to do the job you want. Those server side codes reside in your managed beans.
If we classify based on the type responsibility, there are several types of managed beans:
Model Managed-Bean
Backing Managed-Bean
Controller Managed-Bean
Support Managed-Bean
Utility Managed-Bean
You will find the details of each of the type in this article.
Your problem is, how to distribute the responsibilities of Controller Managed-Bean. There are several issues to consider, while you are distributing this kind of responsibilities:
The complexity of the task to do.
Re-usability of it.
Modularity in terms of responsibility (type of jobs to do).
Modularity in terms of business perspective.
Decoupling the responsibilities. etc.
You can design your system to with a single controller for all the views of your simple CURD operations of a model. But if you need to handle multiple complex transactions in your single create operation, then separating the operations to multiple controllers, would be a better design. Though your registration procedure is pretty much simple, you should use a separate controller to handle the task. Because it will not be a good idea, to put any task in the same managed bean, that is not simple and related enough to reside with the task "registration". I think this, concludes your query!
you should a data transfer object bean and a domain bean for ui submission and for persistence in db respectively.
using a controller class, process your ui jsf submission data and create a clean domain bean and use this to persist.
the best practice should always de-couple processes/entities if possible.
also your dto bean might have accessory and more data than your domain bean which u might require for several purposes.
In similar situations, I always have a UserManagedBean that handles user relative operations, such as login, registration, change password, etc...
To deal with these operations, I put an attribute in the UserManagedBean of type User (or whatever class name) which corresponds to the persisted data related to users (usually in DB table user).
In your case nickname and password are attributes of the User class. As for the submit it will invoke a method in the UserManagedBean to authenticate user:
<h:inputText value="#{userManagedBean.user.nickname}"/>
<h:inputSecret value="#{userManagedBean.user.password}"/>
<h:commandButton value="Login" action="#{userManagedBean.loginUser}"/>
Of course, the loginUser method will invoke a call to the service layer which will invoke DAO layer to check credentials against DB (or other storage).
If the login is successful, the user attribute in our managed bean (which should be session scoped) is initialized with returned object from DB.
We have built a Spring MVC web application that is heavily relying on the user to do things in a certain order, and while it prevents users from circumventing this (without trying very hard) in the usual case (by not offering options to “go to places” you’re not supposed to at the given moment), we’re having some problems when people open another instance of the application in a new tab or browser window.
Since the application stores the domain model in the user’s session, using the program in another window can potentially mess up the model’s data, we’ve already implemented a page-ID mechanism that validates the user using the program in the correct order and not using the browser navigation, but we’re still facing problems when things like resetting the program (this is a feature, redirecting the user to the home screen and clearing the domain model) happen in one window and the user then tries to do something relying on the domain model to be filled with valid data in another window (leading to a NullPointerException quite quickly).
Storing some user details (like id, name, email) in a session might be ok, but storing the user's state (or any data that changes often and/or significantly affects other things in your app) doesn't sound like a good idea.
Hopefully one of the following approaches will fit you:
Don't save state in the session - load it from the database whenever you need it (in your case, whenever the user tries to access one of the steps that should be done in order). If you use caching, this shouldn't have major performance consequences.
Don't save state in the database, only in the session - works for limited cases (for instance, ordering airline tickets) where you can postpone committing your domain object until the process has finished.
Use Ajax for multi-step processes and don't save state at all (except implicitly in the browser). This requires putting all the steps into one page and ajaxifying some of your code.
Regardless, if someone logs in and tries to go to step 3, they shouldn't get an exception thrown at them, but that's a different story.
If I were you, I'd let user to wander around other parts of the website - the parts that don't interfere with your wizard process. However, once they try to restart it - check if there's PageID in session, and remind them they have not finished what they started, and ask if they would like to cancel/restart or continue on from where they left it.
In case anyone ever reads this question again:
Instead of the HttpSession keeping exactly one copy of the domain model it now holds a collection and we transport a reference to a single one of the models through the requests/responses so we can get the right model to work on in our controllers and views.
I have been doing Java and Ruby (and used frameworks) for some while and I know MVC is a way to separate code. The thing is, I think I never really used it in the way it should.
The first question is: Business logic, what does it mean? Does Business logic mean the logic that is special for that application? Let say you are building a Satellite system. Is the business logic the code that is unique for that Satellite system and make it work?
What does "domain" mean? Like in domain logic or domain as a term.
"Keep your model smart, controllers thin and view dumb". This statement clearly indicates that the controllers which I load with too much code is the wrong way of writing it.
As an example. If you have a BankAccount class. Then should this class provide methods for behavior such as validating etc as well as getter/setter?
What should the controller be doing? Just redirecting input/events in the view to the model and maybe update view (which is the case in webframeworks).
For example in Java and JPA you have the entityManager that you use for finding entities, maybe do something on them etc. Should this entitymanager be used in the controller, or should you make another layer named e.g. "Service" which the controller uses. But again, does this server layer then belong to the Model in MVC? How would you do this in Rails?
I don't get the Model nor the Controller concept right I think.
Think of applications as being layered. When working on each layer, always think to yourself, "Is this layer dependent on the layer above it or can it work independently?" That is the basis to a good MVC application.
When thinking of layers in an MVC style application, there are a few.
In my mind the layers (from top to bottom) are the view, controllers, business logic, and data access.
The view could be JSP or even AJAX requests from jQuery. This is where the user interacts with your application. The view sends information to the business logic layer to do work.
Controllers should be written to collect data sent to it from the view, transform it in a way that the business logic can understand it, and then pass the information into the business logic layer. Controllers may also take information retured from the business logic layer, transform it, and send it back to the view. No real "business logic" should happen here. Think of it as a broker between the view and the business object layer. This is also a great spot for validating data submitted by the view.
Business logic is a layer you would find in the middle, typically between the controllers and data access layer. This could also be called a service layer. It should be written to not know anything about what is calling it. If written correctly, you could use this layer in a standalone application. Here is where a lot of the application smarts should take place. A lot of times, this layer is simply here to call the data access layer and return the results back to the controllers. But, a lot of other things could go on here like data manipulation, calculations, data security, validation, etc.
The data access layer should be written in such a way that it takes it's input, retrieves the appropriate data, transforms it into a useable form, and returns it. This layer should not know or care what is calling it and should be written in that way. Again, this layer should not know it is in a web application or a stand alone application. There are a lot of options here to make your life simpler in the form or ORM (Object Relational Mapping) frameworks. If your application is a step above trivial, you should think about using one.
In the traditional sense, the model could be the business logic layer and the data access layer as well as the domain objects that go along with them.
Using "BankAccount" as an example:
"BankAccount" sounds more like a domain object (representation of data in a database) than a class that has logic in it. Typically domain objects only have the fields they need (account number, balance, etc.) with getters and setters.
The user might log into their bank website. On login, the view sends the username to the controller (BankAccountController). The controller takes this information out of the request and sends it to the service layer (BankAccountService). The service layer would send this information to the data access layer which does a query for the BankAccounts that the user might have and return them to the service layer which returns them to the controller. The controller will manipulate this information in some way that the view layer can display them to the user. There would be a similar series of events when the user transfers money between accounts, for instance.
Hope this helps... let me know if you have any more questions or if something isn't clear.
Edit:
Besides the links posted by the other users, Wikipedia has a brief, but pretty good article on MVC.
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
In JSF 2.0, the most obvious use-case for the view scope is a single page with potentially multiple AJAX post-backs. Using CDI instead of JSF managed beans leaves us without the view scope so we're either left to implement our own, use a (possibly bug-ridden) third party implementation or use the conversation scope.
My question: Is the conversation scope a worthy substitute for the view scope in the typical AJAX situation? Like the view scope, does it allow multiple instances per session? What are the pitfalls?
I'm aware of one of the pitfalls, namely that the conversation scope isn't automatically deleted when the user navigates away from the page, but instead is deleted after a time-out. But I'm not sure what happens when the user navigates back to that page before the conversation has timed out.
UPDATE
The conversation scope does indeed support multiple instances per session. This book states as much and I was able to confirm this using code from ch. 2.
In any #ConversationScoped CDI beans, you must have the following field:
#Inject
private Conversation conversation;
Whenever you want to begin the conversation, you need to check if the bean is in transient state. Otherwise, IllegalStateException will be thrown. It would be something like this:
public void beginConversation() {
if (conversation.isTransient()) conversation.begin();
}
By doing this, your bean will be in the long-running state. Hence, if the user navigate aways from the page and navigates back later on, you can always check if his conversation has timed-out or not and bring him to the page where he left.
Besides, I have been using #ViewScoped ManagedBean together with CDI bean for a while. You can still use #Inject to inject a CDI bean into a MangedBean. I don't think you can do the other way around though. Anyway, I have no idea if this would cause anything bad to happen later. However, up until now, I have never met any issues. If you really want to use #ViewScoped, I think you can try :P.
UPDATE:
Is the conversation scope a worthy substitute for the view scope in the typical AJAX situation?
I don't think #ConversationScoped can ever fully replace #ViewScoped.
Like the view scope, does it allow multiple instances per session?
No, you cannot have multiple instances per session. As I mentioned, if you start a new Conversation while the old conversation is still in long-running state, you will get IllegalStateException.
What are the pitfalls?
Well, one of the main advantages of #ViewScoped over #RequestScoped is that you don't need to re-initiate data every time the user submits the form to the same View. However, with #ConversationScoped, this advantage is over-used. While this problem is not as serious as if you use #SessionScoped, you still need to hold the initiated data as long as the #ConversationScoped bean lives. The longer the conversation, the more data you may need to hold.
Anyone know of any other custom spring scopes than Servlet Context Scope and ThreadScope ?
If you've made some closed-source custom scope I'd really also be interested in hearing what it does and how it worked out for you. (I'd imagine someone would make a WindowScope in a desktop app ?)
I'm open to all use cases, I'm looking to expand my horizon here.
We implemented our own custom Spring scope. A lot of our code works at a relatively low level, close to the database, and we maintain a conceptual level on top of that with its own object model of data sources, links, attributes etc.
Anyway, a lot of beans require a so-called StorageDictionary (an encapsulation of this object graph) to do their work. When we make non-trivial changes to the object graph, the dictionary sometimes needs to be blown away and recreated. Consequently, we implemented a custom scope for objects that were dictionary scoped, and part of the invalidation of a given dictionary involves clearing this custom scope. This lets Spring handle a nice form of automatic caching for these objects. You get the same object back every time up until the dictionary is invalidated, at which point you get a new object.
This helps not only with consistency but also allows the objects themselves to cache references to entities within the dictionary, safe within the knowledge that the cache will be valid for as long as they themselves are retrievable by Spring. This in turn lets us build these as immutable objects (so long as they can be wired via constructor injection), which is a very good thing to do anyway wherever possible.
This technique won't work everywhere and does depend heavily on the characteristics of the software (e.g. if the dictionary was modified regularly this would be horribly inefficient, and if it was updated never this would be unnecessary and slightly less efficient than direct access). However, it has definitely helped us pass off this management of lifecycle to Spring in a way that is conceptually straightforward and in my opinion quite elegant.
In my company we've created two custom scopes, one that will use Thread or Request and another that will use either Thread or Session. The idea is that a single scope can be used for scoped beans without having to change configuration based on the execution environment (JUnit or Servlet container). This also really comes in handy for when you run items in Quartz and no longer have a Request or Session scope available.
Background:
I work on a single web app that runs 4 different web sites under the same servlet context. Each site has its own domain name, e.g. www.examplesite1.com, www.examplesite2.com, etc.
Problem:
Sites sometimes require their own customised instance of a bean from the app context (usually for customised display of messages or formatting of objects).
For example, say sites 1 and 2 both use the "standardDateFormatter" bean, site 3 uses the "usDateFormatter" bean and site 4 uses the "ukDateFormatter" bean.
Solution:
I'm planning on using a "site" scope.
We have a Site enum like this:
enum Site {
SITE1, SITE2, SITE3, SITE4;
}
Then we have a filter that stores one of these Site values in the request's thread using a ThreadLocal. This is the site scope's "conversation id".
Then in the app context there'd be a bean named "dateFormatter", with 'scope="site"'. Then, wherever we want to use a date formatter, the correct one for the user's current site will be used.
Added later:
Sample code here:
http://github.com/eliotsykes/spring-site-scope
Oracle Coherence has implemented a datagrid scope for Spring beans. To sum it up:
A Data Grid Bean is a proxy to a
java.io.Serializable Bean instance
that is stored in a non-expiring
Coherence Distributed Cache (called
near-datagridbeans).
Never used them myself but they seem cool.
Apache Orchestra provides SpringConversationScope.
In a Spring Batch application, we have implemented an item scope.
Background
We have lots of #Service components which compute something based on the current batch item. Many of them need the same workflow:
Determine relevant item parts.
Init stuff based on the item.
For each item part, compute something (using stuff).
We moved the workflow into a base class template method, so the subclasses implement only findItemParts(Item) (doing 1 and 2) and computeSomething(ItemPart) (doing 3). So they became stateful (stuff initialized in findItemParts is needed in computeSomething), and that state must be cleared before the next item.
Some of those services also involve injected Spring beans which are also derived from the current item and must be removed afterwards.
Design
We implemented an AbstractScopeRegisteringItemProcessor which registers the item and allows subclasses to register derived beans. At the end of its process method, it removes the item from its scope context, and the derived beans using DefaultSingletonBeanRegistry.destroySingleton.
How it worked out
It works, but has the following problems:
We did not manage to get the derived beans cleaned up without registration (just based on their #Scope). The concrete processor must create and register them.
AbstractScopeRegisteringItemProcessor would have been nicer using composition and dynamically implementing all interfaces of the underlying processor. But then the resulting #StepScope bean is a proxy for the declared return type (i.e. AbstractScopeRegisteringItemProcessor or ItemProcessor) without the required callback interfaces.
EDIT
With the aid of #Eliot Sykes's solution and shared code plus #Cheetah's BeanDefinition registration, I was able to get rid of the registration as singleton beans. Instead, ItemScopeContext (the storage used by both the processor and the Scope implementation; Java-configured via a static #Bean method) implements BeanDefinitionRegistryPostProcessor. It registers a FactoryBean whose getObject() returns the current item or throws an exception if there is none. Now, a #Component annotated with #Scope(scopeName = "Item", proxyMode = ScopedProxyMode.TARGET_CLASS) can simply inject the item and need not be registered for end-of-scope cleanup.
So in the end, it did work out well.
A spring locale scope based on the users locale wihtin a web application
See related wiki page
In my company, we have also implemented spring custom scope. We have a multi tenant system where every customer can customize settings. Instance based scope of ours, caches the beans which are customer specific. So each time user of a customer logs in, these settings are cached and reused again when other users of the same customers sign in.
I once used a kind of conversation scope to store some objects in the session scope, in order to keep them when re-entering the same page, but limited to a single page to avoid to leave useless objects in the session. The implementation just stored the page URL and cleaned the conversation scope on each page change.