Spring: Scoped fields - java

I wrote this idea on the Spring JIRA and even though I know this is not a key feature and has minor priority, I'd still expect some answer by now. I publicize the idea, because I want to know what you guys think about it, if it's cool and I should implement it myself, or is the need for this is a sign of bad architecture.
So the idea itself is - as the title suggests - is a field in a Spring Bean, which has a different scope then the bean itself. We already have something like this, in the shape of scoped proxies, however it works only for bean dependencies. I might want to store a list of Strings of session scope in a bean of singleton scope. I, then have to create a new bean, with scope of session for one field and some functions to use that field. It seems a waste of code and I'd find it bad, because I wouldn't be able to use that bean anywhere else, because it'd already have that data the first class put into it.
I could rephrase the mess above and say that I want to have named beans with arbitrary type (so not necessarily spring beans) and on top of the scope we configure it to have, that field would also be different for every instance of the parent class.
This could make a field instance broader than a prototype scoped bean, but also less broad then the actual scope we'd like to use it in. Kind of a middle ground.
Here is the JIRA issue I wrote: https://jira.spring.io/browse/SPR-16971

In my understanding, Scopes only work with Dependency Injection as it's the DI Container that decides if it should return a new instance or an already existing one. So everything that is #Autowired can be scoped.
I can't imagine how scoping a normal field would work. If I change it, should it change in all other objects that "use" it? I would have to be some kind of proxy object then and neve a primivive value. If on the other hand you have a proxy object, why not use the currently available autowire mechanism.

Related

Finalize beans of a certain user

I need a specific scope in my spring-managed (w/ spring-security) web application. But this scope must have a narrower scope than session and wider than request. Corresponding beans should be initialized and destructed on certain cases, within current session. But for sure only destructed for the user who requested such.
I successfully implement a custom-scope but it is not user-aware and when I try to finalize it, all created beans on that scope are finalized.
Is there any way to initialize beans with e.g logged user name?
In a nutshell, I need to initialize some of the variables on such beans on certain cases, that's why I want to destroy and re-initialize them.
Any suggestion will be well accepted,
Thanks all.
Edit: As #Stefan suggested to use webflow, even that'll probably solve our issues i think it doesn't seem an acceptable method because our bunch of pages are dependent to fields defined in spring beans. Now we have to bind them to viewscope/flowscope.
I still need a quicker way to handle this issue,
Thanks.
You might have a look at Spring Webflow. It works with JSF and has a 'flow scope' that is between request and session scope.

View scope bean injecting application scope and modify app scope data. Bad practice?

I have a view scoped bean and based on the user input, it might need to change the values of the application scope bean for the entire app to use the new values. It seems to be a bad practice to change values of application scope bean in real time. The application bean loads all the values of support tables, with the admin part of my app, I want the admin users to be able to add things to the support tables and then everyone should be able to use the new values.
The problem I'm seeing is that the view bean gets a new instance of the injected managed property each time the page has to go back to the managed bean, I also see a similar problem when injecting session scope into view scope and changing values.
Thanks.
There are two separate problems here.
Whether it is good practice to modify global application state via in-memory beans depends on the specifics of what you are doing, how much state there is, how its going to be persisted, whether the application is in a clustered environment, etc.
Stack Overflow is unsuited to doing a detailed architectural review.
The problem I'm seeing is that the view bean gets a new instance of the injected managed property each time the page has to go back to the managed bean, I also see a similar problem when injecting session scope into view scope and changing values.
This does not sound right at all. You might see new instances (proxied beans) if you're using CDI but you mention managed properties so I guess not. Application scoped beans are placed into the application map and remain there until the application is stopped.
So, there is something wrong with your application logic or you have omitted some relevant detail about your software stack or environment.

Beans: How to properly manage a property affected by another one

I have an Entity/JSF Managed Bean Ticket that represents a helpdesk
ticket.
It has a status property; when the status is set to closed I want to
change the value of the closingDate property to the current system time.
But I think that code should be contained in the bean, as each time the
ticket is closed the time should be recorded.
What would be the proper way to manage it? I have several ideas.
Make setter of creationTime private, and change its value when the
status setter is called. Fast and quick, but makes a setter change two
attributes. Also, forces me to use JPA field access (not much of a problem
as I am already using it, but still a limitation) and I am not clear of
what will happen when the bean is serialized.
Make the status property a bound property as described in JavaBeans,
and make the class a PropertyChangeListener to itself. Very formal, but
a little overcomplicated to my likening.
Make setters for both properties private, and add a non-bean method
close() that performs both actions. I would go this way but it can make
me it complicated to work with JSF.
Do nothing. Keep the bean as dumb as it can and move the logic to the
controller; cross my fingers hoping that nobody forgets to update both
attributes.
I favour 1) or 3), but I would like to know if there is a better approach.
I don't know if anyone can tell you the proper way to manage it, as arguments can be made for many different approaches just like you make them. To add to your list as a combination of 1) and 3), for example:
Have the setter of status update creationTime when it status is set to closed and leave both setters public. Has benefits from both as I'm not aware of any downside to this from a JPA perspective.
What I would advice against however is having a Entity/JSF Managed Bean. I would recommend having two, an Entity bean and a JSF Managed Bean. This way your Entity bean can be kept as dumb as it can be, while your JSF Managed Bean will have smart methods like close() or reopen() and comprised of a series of dumb calls to the Entity bean. Also, you can do things like persist() in #PreDestroy. Easy to develop, easy to maintain, easy to make decisions. Hopefully you'll find this helpful.

Spring, create a bean from deserializing

I've not used Spring too much, so I might be missing something obvious. Anyway, this is the question:
Say you have a Spring managed bean that is a networking client. After you call a method on it you get some object back, say it is a List
Now I want to process that List into something more useful for the rest of my application, say it is of a MyBusinessBean type.
How do I avoid doing a
new MyBusinessBean(List<String> info)
?? If I do this it becomes an object that is not part of the context.
I'm doing something like:
MyBusinessBean myBean = (MyBusinessBean) applicationContext.getBean("myBusinessBean", info);
However I keep reading everywhere that this is a signal of something not being done properly, since I am making my code context aware. What is the proper Spring way of doing this?
The second way is what you do in Spring. Calling "new" means you're breaking the model.
But don't assume that every call to "new" is eliminated by Spring. Every object need not be under Spring's control. Sometimes you just gotta call "new", usually in the scope of a single method. Create the object, use it, GC it - no Spring bean factory needed.
If you want to give an object in your app access to that List after serialization, simply pass the reference. You don't need the Spring bean factory in the situation you've described, because you've already got the serialized the object from the server.

Refreshing/replacing beans in the ApplicationContext. Possible or am I missing the point?

First off, I think I'm trying to use Spring incorrectly, but confirmation would be appreciated.
I am trying to reset a single bean in mid-application. My initial configuration works just fine.
My scenario
1 Insurance Claim bean (session
scope)
1 Claim details bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope)
1 Claimant details bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope)
1 Submit claim bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope).
My application is more complex than this, but for the sake of providing a clear example I wont describe the whole thing.
The first two controllers are used to set various properties of the claim, validate etc.
The third writes a claim to the database. THEN I want it to reset the bean. However I can't just say claim=new Claim() in SubmitClaimController.OnSubmit() as the ApplicationContext keeps its reference to the old Claim.
I could just create a method Claim.clear(), but that feels like the wrong approach. However, I can't see anything like ApplicationContext.destroyBean(beanname) or ApplicationContext.createBean().
I do not want to refresh the entire ApplicationContext as I will have other beans I want to keep alive throughout the session.
Thanks in advance.
I don't think the Claim object should be Spring-managed. It's really not injected; sounds like it should be bound from the request sent into the controller and passed to the service for processing. If you put a Claim into session scope, you need to invalidate the session when the transaction is done or if the session times out.
By the way, I see you mention three controllers, but no service. You should have a service layer, and controllers should not deal with DAOs or persistence.
You can change the scope of a bean. Default is singleton which is sometimes not appropriate in web contexts. You can change it to be session scoped by adding for example
the attribute scope="session"
and the child <aop:scoped-proxy proxy-target-class="false"/>
to the bean definition.
I am working with 3.0M4, btw, but I would expect it to be in earlier versions, as well, as it's a very important functionality. Have a look at:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ch03s05.html
Cheers!

Categories