Question

Ok I know scope questions come up all the time but I'm interested in a slightly different approach to the solution. The @ViewScope is a fantastic bridge between the @RequestScope and the @SessionScope.

However there is still a common use case (at least for me) where I really don't want to use @SessionScope but I need the data over a couple of views. A really simple case is when I have multiple datatables chained together each one depending on previous selections.

It's perfectly possible to use <f:paramView> and pass a single or even a couple of pieces of data as params in the address and then retrieve everything from the database again. I am more interested in finding a way of creating a 'snapshot' of the beans state / variables, creating the new @ViewScope and then 'restoring' the 'snapshot state' to the new bean.

Does such a thing exist? Ideas? Opinions?

Was it helpful?

Solution

I don't know if this is the 'accepted solution' but I've implemented an idea that works for me. (Feedback appreciated!)

So I have created a @SessionScoped class with a couple of static maps:

private static Map<String, Object> objectVariableMap;

// Getters, setters and methods etc. are omitted for simplicity

The idea being that I have specified a map that accepts a String as the key and an Object as the value. I've specifically not set the type of object to allow me to store any type of object in there. The caveat is that you need to be sure of the type of object when retrieving it so you can cast it back into its original type.

Now comes the time to set the data from the first @ViewScoped. I generate a random UUID (or what ever you want) as the Map key and then set the value to the object I'm working with (ie. this, or indeed any other objects you might want to pass to the next view). Save the key, value into the map and set the URL param to the key.

I'm never keen on passing data like user id's etc. in URL params (even when its encrypted). This idea has the added benefit of offering disposable URL values that have a specifiable life span.

On the receiving end (ie. The new @ViewScoped bean, or any other scope for that matter) you read in the URL param (the map key) using <f:paramView> and then use a preRenderView event to retrieve and set the Object where working with.

At this point you can choose to remove the key pair from the Map and invalidate the ability to retrieve that object or you can keep keep the key pair for a longer duration by simply updating the object if there are any changes.

UPDATE: Conceptually this has been really successful (for me at least). I've created a handfull of useful methods and classes surrounding the concept to make it more universal. If anybody wants more specific instructions or I might even create a small library if anybody wants.

OTHER TIPS

You can use the CDI "Conversation Scope" for this. This is narrower than the session scope but wider than the view scope.

If the pages between which you pass parameters are a unit, you can also make them a flow in JSF 2.2 and use the flow scope.

Projects like CODI offer various other scopes that can be used between pages.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top