Recently we faced the issue of flowscope values not being set across the flow, but later after the investigation found that all the flowscope variables should be serialized ( my mistake i did not read the line from the spring webflow documentation - the line "any objects stored in flow scope need to be Serializable"
I feel this is kind of session information, in general we don't serialize session variable. Just curious why this serialization required for this spring webflow ?
By forcing flow scoped objects to be Serializable, it provides the flexibility to safely store them anywhere - a database, on disk, etc - and then re-store them when returning to whatever flow state you were in. While your particular server/environment might be a single machine, with every HttpSession (the default "backing" for spring web flow state) persisted in memory, others might have clustered/distributed web/app servers.
Related
Is it a bad idea to implement my own session state provider that conditionally switches based on key between the redis session provider and the inproc session provider?
I am working in a very large legacy asp.net application that currently uses the inproc session provider. We are migrating to Redis as a session state provider so that it persists deploys, however the application is chock full of session abuses (e.g. way too large objects, non-serializable object, I saw a thread in there for some reason?).
We plan to slowly correct these abuses but until they are all corrected we cannot really move to redis. I am hoping we can slowly start migrate serializable-safe keys into redis while the abuses remain in memory until we address them.
Does anyone have any advice on this? Or perhaps alternative suggestions for migrating to out of process from in process?
Thanks!
In ASP.NET Web Form and MVC, using Redis for Session State is just a couple of line of modification in Web.config. Then add SerializableAttribute to classes. There is no side effects of applying it to a class.
Based on my experience when migrating to Azure few years ago, Session State is not worth migrating slowly.
Caching is different story. It requires code changes, so we end up implementing two classes - MemoryCacheManager and RedisCacheManager, and register at run-time in IoC container. Then inject ICacheManager to dependent classes.
Source for the session state: https://github.com/Microsoft/referencesource/blob/master/System.Web/State/
Docs: https://learn.microsoft.com/en-us/dotnet/api/system.web.sessionstate?view=netframework-4.7.2
I'd start by checking out the reference source so you can search the codebase. One interface jumps out as potentially interesting.. IPartialSessionState (When implemented in a type, returns a list of zero or more session keys that indicate to a session-state provider which session-state items have to be retrieved.) Source is here
https://learn.microsoft.com/en-us/dotnet/api/system.web.sessionstate.ipartialsessionstate?view=netframework-4.7.2
I stumbled on https://www.wiktorzychla.com/2007/06/wrapped-inprocsessionstatestore.html
via ASPNET : Switch between Session State Providers ?.
This technique could theoretically be used with the Redis provider as well. You'd have to either maintain a list of keys suitable for storing in Redis or do some kind of try to serialize/catch/cache result of which types can be serialized and adaptively fall back to the InProc behavior. You should be able to use HttpContext.Current.Items to flow information between events in the request processing pipeline.
The SessionStateModule (the module responsible for retrieving session, locking, saving, unlocking, etc.) seems to treat InProc as special in a few places. Search its code for InProc. Essentially you're trying to plug in a magical provider that is Custom and yet still has all of the InProc semantics applied by the one and only SessionStateModule. You won't be able to/probably won't want to modify that module, but you may be able to hook up another one adjacent to it that hooks into related events in the request pipeline and does whatever needs to be done that is either In-Proc or Custom-specific. You'll probably run into internal/private methods for which you'd need to use reflection. Not sure how the licensing works on the reference source (MS-PL I think), but another option would be to copy & paste the code from SessionStateModule into your own, make adjustments as needed, unregister the original and register your replacement.
I think you're going to be stuck dealing with a lot of reflection code to get this to work.
Controllers are created per request in Asp.net MVC, this is a fact.
My question is:
what is the best practice for for creating common objects (Logger, Localizer, Configurator) that are used in the web application, possible methods from my knowledge are:
Create the object per request then dispose it at the end of the request.
Create the object at the beginning of user session then dispose it at the end of the session.
Create only one object for the entire application and dispose it at application shutdown.
It depends entirely on the scope within these components are used and their dependencies, to elaborate:
Logger
A logger is usually alive throughout the entire lifespan of the application and can be used all over the application (scope), the logger doesn't care for the request or the controller (dependencies). Best Lifetime Scope: Application.
LogSource / LogContext
Unlike logger, LogSource / LogContext are contextual object that are to be used withing a given context (scope), these object are aware of their context (controller / request) (dependencies). Best Lifetime Scope: Controller / Request.
Localizer
Localizer is a bit less clear-cut as the other components. For one it is use application wide (Controllers, Views etc.) (scope). But as for its dependencies the matter is implementation specific, your localizer may need a CultureInfo object for construction or it may not. In a case when it is not required then there are no dependencies for that component and an Application scope will fit.
On the other hand if a culture is required then it is a dependency for that component. Now it's logical to then scope it to a user session but this is where the idea of performance and dependency specifics comes to play. If you scope the localizer to a user session then each user will have x amount of time the server to read the localization file before it's served its response. Additionally the dependency is not the user session but the user's culture, whilst the possible user sessions are infinite, the possible supported locals are all but infinite. Keeping that in mind you can then create a localization pool that contains every supported local (and possibly a fallback local for the ones that aren't supported),scoped to the application, which can serve localizers scoped to user sessions.
To sum up - You can apply the scope-dependencies logic to any component but as we've seed with the localizer it's always best to understand the component and the implication of scoping that component to a specific scope.
It really depends on 2 things:
The implementation of those common objects - for example thread safety. For example if your logger has a singleton life-cycle and it has some static property (for example level or a name) then by modifying it in one request it will affect others (and this most probably is unwanted behavior).
The purpose(usage) of those objects - lets assume that you have a LoggerManager or a Configurator or some kind of Factory object that should be initialized only once on application start and then it is used to create(retrieve) other objects (for example an IoC container)then it is certainly makes sense to make it singleton (sometimes it is absolutely required).
From my experience most of the objects have either transient or per-request life cycle. Regarding the singletons (one object for the entire application) - usually it is very clear when to use them. I think a god example is a LoggerManager that is used to create Logger instances based on some static configuration or a Configurator (as you called it) that is initialized on application start and parses some configuration files. My rules of thumb for singletons are:
they have to be thread-safe
they don't change often
they either hold some shared data that is applicable to all threads/requests/users and etc
they are heavy objects - if they are light weight you can create a new object each time (transient life-cycle) and most probably you won't notice any difference in performance.
Regarding the session - for me it is more of a cache, so most of the time it holds some user related data
I'm reading the Spring Web Flow chapter in the book Pro Spring MVC. Unfortunately there's no explicit information, where the state during a flow execution is persisted. I assume it is saved in the JVM Heap and associated with the session.
Now HTTP is a stateless protocol (REST...) and I'd like to use Spring Web Flow without saving state on the server (besides the one and only state that a session might be authenticated).
One strategy is to send all parameters of the entire flow with every HTTP request of the flow (hidden input) and thus accumulating all necessary parameters until the flow has finished.
The overhead of re-validating parameters can be avoided with signatures over already validated parameters.
Do you know, whether it might be possible to use Spring Web Flow in this way? Has anybody already done this?
Update: Why?
Persisting state is not only a violation of the principles of HTTP as a stateless protocol but has practical problems too:
If the user browses with multiple browser tabs then this can lead to inconsistent state, race conditions or data loss.
Storing state on the server makes load balancing over several servers more complicate.
Testing and debugging becomes more complicate, because requests can not be tested or analyzed in isolation but only in the context of previous requests.
Cookies must be enabled to correlate servers sessions to requests.
The server needs to synchronize access to the server-side state.
The url of a request that also depends on server state does not contain all information necessary to bookmark the state inside a flow or to make sense of it in a bug report.
I've not yet looked at the details of Web Flow but I'm confident that one could have the same programming experience and still keep all information in the request parameters.
Update: I've now learned that my requested style of flow handling has a name: Continuations. The term continuation is more common in functional programming but it's apparently not uncommon to adapt the idea to HTTP interactions.
You might be interested in checking my bean flow FSM project (restflow):
https://github.com/alfonso-presa/restflow
Although it doesn't use Spring WebFlow, I think it may help answering the spirit of the question, as it allows the implementation of a stateless server orchestrated flow. I started this project because I wanted to make almost the same as you with spring WebFlow but I found it was not possible as state is stored in session (and also REST/json serialization is not built in).
It's main purpose is making an state-machine (just like WebFlow does) but with it's state stored in a bean, which you can persist in a distributed store, or easily sign or encrypt and send back to the client as continuation for next requests.
I hope you find it useful.
edit: I created a showcase project here: https://github.com/alfonso-presa/restflow-spring-web-sample
I'm doing unit testing on a class library that uses NHibernate for persistence. NHibernate is using a Sqlite in-memory database for testing purposes. Under normal circumstances, it's easy to get StructureMap to kick out a session for me.
However, because I'm using the in-memory database to improve testing speed, I need to have a single session available for the duration of a test (because it blows the database away when I create a new one). And there is another wrinkle. The case that is currently burning me is testing a custom NHibernate-based ASP.NET membership provider. These are created apparently once per AppDomain, so I shouldn't inject the session into it, for obvious reasons.
Is there a way in structuremap to tell it to get rid of an instance of a particular type while still maintaining the bits that tell it how to instantiate that type? Really, if I could get away with it, I would just make it act like the HttpScoped object lifetime, but apparently I can only do that within the context of an Http request. Is there a straightforward way to manually control the lifetime of an object coming out of structuremap?
I apologize for the length of this and the possibility that it is a dumb question. I'm solo on this project, so I don't really have anyone to bounce ideas off of.
You could wrap the session in your own ISession implementation which delegates to a real session which lifetime you control. Then register your own ISession as instance.
I ended up making two constructors for my provider along with a private variable of type Func. By default, its value was set to my standard code for creating a session using StructureMap's ObjectFactory.
The overloaded constructor accepted as a parameter an object of type Func. That way, I can inject a strategy for creating an instance of that type if needed, but otherwise don't have to go through any extended effort. In the case of my test, I created the session in the NUnit setup method and destroyed it in the Teardown. I don't love this idea, but I don't currently hate it enough to rip it out....yet.
This got rid of the error I was experiencing in regard to the tables. However, it appears that NHibernate for some reason cannot write to an in-memory sqlite database under the conditions I created. I'm now working on testing to see if I can write to one in the file system. It isn't ideal, but it will be a good long while (I hope), before the performance of writing to disk really starts hurting.
I've read through this article trying to understand why you want a session bean in between the client and entity bean. Is it because by letting the client access entity bean directly you would let the client know exactly all about the database?
So by having middleman (the session bean) you would only let the client know part of the database by implementing the business logic in some certain way. So only part of the database which is relevant to the client is only visible. Possibly also increase the security.
Is the above statement true?
Avoiding tight coupling between the client & the business objects, increasing manageability.
Reducing fine-grained method invocations, leads to minimize method invocation calls over the network, providing coarse-grained access to clients.
Can have centralized security & transaction constraints.
Greater flexibility & ability to cope with changes.
Exposing only required & providing simpler interface to the clients, hiding the underlying complexity and inner details, interdependencies between business components.
The article you cite is COMPLETELY out of date. Check the date, it's from 2002.
There is no such thing anymore as an entity bean in EJB (they are currently retained for backwards compatibility, but are on the verge of being purged completely). Entity beans where awkward things; a model object (e.g. Person) that lives completely in the container and where access to every property of it (e.g. getName, getAge) required a remote container call.
In this time and age, we have JPA entities that are POJOs and contain only data. Don't confuse a JPA entity with this ancient EJB entity bean. They sound similar but are completely different things. JPA entities can be safely send to a (remote) client. If you are really concerned that the names used in your entity reveal your DB structure, you could use XML mapping files instead of annotations and use completely different names.
That said, session beans can still perfectly be used to implement the Facade pattern if that's needed. This pattern is indeed used to give clients a simplified and often restricted view of your system. It's just that the idea of using session beans as a Facade for entity beans is completely outdated.
It is to simplify the work of the client. The Facade presents a simple interface and hides the complexity of the model from the client. It also makes it possible for the model to change without affecting the client, as long as the facade does not change its interface.
It decouples application logic with the business logic.
So the actual data structures and implementation can change without breaking existing code utilizing the APIs.
Of course it hides the data structure from "unknown" applications if you expose your beans to external networks