It is needed to define Spring scope which will provide a proxy to the beans and reload/recreate target beans when say an event occurs. The behavior is similar to session beans, except there is no http session.
Does Spring provide a way for such bean proxing and scope manipulation?
UPDATED
Say that it is need to change externalUrl which is used to send http requests. So the application has to switch to new bean with new http connection pool created.
When bean autowired directly it is imposible to recreate it, especially when it is used in many places. So I search some way to inject a proxy instead of it and recreate target instace without altering caller code.
It is possible. I can't tell you exactly how to do it, but if you're able to, something like Spring Cloud Config would be exactly what you want. If you can't adopt that, I would start digging into the source code. The class you'd want to start with is the RefreshScope - from there, you should be able to figure out how it works and how it re-creates beans. I'm sorry that I can't provide more direction.
Related
I am trying to figure out how can I dynamically update/reload externalized configuration in a Spring Boot application without restarting the whole application.
Most of the advice involves reloading ApplicationContext after changing the externalized configuration, but that is equivalent to restarting the entire application, so this is not really all that useful.
Reading through SpringBoot reference documentation, I found a chapter 23.7 Typesafe Configuration Properties.
If I understand it correctly, this allows to define simple POJO classes that will hold your application (externalized) configuration values as attributes.
In theory at least, this scheme could be used to bind beans only once to the required configuration POJO and upon configuration change just update the values in the POJO. Components could easily pick up the changes next time they access getters on the POJO...
However, I have yet not managed to figure out how to enable this type of behavior. Is there some glaringly obvious way to dynamically update components annotated with #ConfigurationProperties when relevant configuration has changed?
It sounds like you're looking for #RefreshScope which is provided by Spring Cloud. From the Spring Cloud documentation:
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
Coming from plain old DI of Spring I can't figure out how to choose scopes properly while writing with CDI.
In Spring all my services have singleton scope by default, which I suppose maps to application scope in CDI (or even #Singleton). I know for e.g. logged in user information I need to use Session scope and for e.g. form params I need request scope.
Say I have a bean that hides external service API calls. It is completely stateless. Should I put it as #Singleton or simply application scoped? Or let it be created on every request (possibly bad option).
Is this correct to inject everything everywhere? In Spring I create my data objects by new. Should I do the same in CDI or simply #Inject them?
Are you only using CDI? or a Java EE 6 container? If you have a stateless class that is used for service calls, then I would recommend using #Stateless, which is from the EJB spec (so you would need a Java EE 6 container) It isn't a singleton, but it doesn't get created on each request either. I believe it is more closely bound to the session, but since it is stateless, instances can be pooled and shared. If you are only dealing with CDI, I believe Singleton matches more directly to Spring's singleton, but I would recommend using ApplicationScoped because it provides a proxy which makes serialization of beans that use it easier.
#Service
#Scope("prototype")
public class CustomerService
{
......
}
Just add #Scope("prototype") annotation to your component.
Is there a reason you would need the bean to remember it's state? If you are using something like a web client, that is a better place to store state in say, session scoped managed beans (assuming jsf), or whatever equivalent for your case. On the back end server side your EJB's would be better kept as #stateless to keep overhead to a minimum and help with the 'keep it simple s..." paradigm. And in case this works, just declare #Stateless on your bean. Unless there is a reason to use a singleton, again it is better to use a stateless bean if you want to go with a Java EE container for your services.
Stateless beans are not really being recreated with every request. That is the purpose of the pool. The app server keeps a ready supply of stateless beans on hand, and if it gets busy, it will make more, and if it quiets down, it will empty some out.
Correct me if anything is wrong.
As I understand, all Spring functionality, namely DI works when beans are got thru
Spring Context, ie getBean() method.
Otherwise, none can work, even if my method is marked #Transactional and I will
create the owning class with a new operator, no transaction management will be provided.
I use Tomcat 6 as a servlet container.
So, my question is: how to make Servlet methods managed by Spring framework.
The issue here is that I use a framework, and its servlets extend the functionality of
basic java Servlets, so they have more methods. Still, web.xml is present in an app as usual.
The thing is that I do not control the servlets creation flow, I can only override a few methods
of each servlet, the flow is basically written down in some xml file, but I control this process
using a graphical gui.
So, basically, I only add some code to a few methods of each Servlet.
How to make those methods managed by Spring framework? The basic thing I need to do is
making these methods transactional (#Transactional).
comment to Bozho:
#Bozho Let's see. In these servlets' methods I work with framework capabilities, let's say special variables that are got and saved in the current session. And what is needed, is looping through those framework-based collections while saving some values in a database. What you suggest is introducing a new very complex object, so that it could be passed to a service layer. (Service layer will not know anything about framework, its classes and objects kept in current Session! First, we "wrap" framework based collections to such a object, so copy everything into it. Then, again, the Service layer method should either save changes in a database or, worse case, return a new complex object so that Servlet framework method could update framework variables depending on the result of Service layer method execution. It is a workaround but do you think it is a good idea?
You can also define your servlets directly in the Spring application context. You'll need a "proxy" servlet registered in web.xml and delegating to the servlet instance which is configured as bean in the applicationContext.xml. Proxy servlet is configured with the name of the target servlet bean, it discovers this bean via WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(...) and delegates all the processing to the target servlet. In this case an instance of your servlet is completely managed by Spring.
I'd suggest restructuring your code - making servlet methods transactional is not a good thing to do. Put the transactional logic in a separate, service class, and either
obtain these spring-managed classes by WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(..) or
in your servlet init() method obtain the ApplicationContext with the above method and call appCtx.getAutowireCapableBeanFactory().autowireBean(this). This way you can inject the transactional classes in your servlet as if it was spring-managed.
Now, you can do all this, but it is definitely not a beautiful way to go. I'd suggest using Spring MVC or any other MVC framework (which support spring integration of its components)
If this is all not possible, as a last resort I think you can use #Configurable (on your servlets) with a <context:load-time-weaver/>.
You should take a look how Spring proxy filters:
http://grepcode.com/file/repository.springsource.com/org.springframework/org.springframework.web/3.0.2/org/springframework/web/filter/DelegatingFilterProxy.java
In theory you could easily make the same sort of proxy for servlets and DispatcherServlet is sort of a proxy.
I've got a project using Jetspeed portal and Springframework 2.5.6 where I need a Jetspeed level service to be unique for each user logged in. This would be best done using Spring AOP and scope="session". The problem is, that these are behind the scenes beans that need to be running as soon as the session in initiated. It appears that Spring's AOP chooses a lazy load design and does not create or init the actual implementation until a method on the bean is called.
Is there a way to force Spring AOP to create the new bean as soon as the session object is created?
An excellent question. The easiest option that springs to mind (if you'll pardon the expression) is to wire your session-scoped bean into the controller that is invoked when the first request of the session comes in (and to do this, the controller would have to either be a session-scoped bean itself, or your bean would need to use aop:scoped-proxy).
If different controllers could be invoked at the start of the session, then you could wire the bean into a session-scoped interceptor instead, and configure your url mapping to pass the requests through the interceptor, ensuring that the bean is initialized right at the start of the session.
I can't really think of a more elegant way to do this. You could potentially create a custom HttpSessionListener which calls getBean("my-session-scoped-bean") on the app context when sessionCreated() is called, but that's a bit clunky.
I have a bean, say manager, which is used all over my application for remoting. The bean is using httpclient which in turn can be configured with or without proxy. But this configuration can be only one. What i want in my application is: when the application started, the user is asked does she want to use a proxy or not? And depending on the user's answer the bean is properly configured and only then started. Some sort of dynamic configuration during runtime.
Is it possible or maybe I should achieve this some other way?
Thank you.
Why can't you call setProxy() on httpclient configuration depending on user's input?
Alternatively you can configure httpclient as bean in Spring context (either directly or create a simple wrapper) two times - one with proxy and one without. Then manager can choose which one to use depending on user's input (both can be injected into manager).