I am trying to create multi-tab (JavaScript tabs) interface for Spring/facelets application and I have s.c. window manager that holds array of windows (tabs). Each window (tab) contains Spring bean (session scope) which receive (as injections) other spring beans, e.g. for business services, DAO beans and so on. I am using Primefaces p:tabView for facelets part.
When user creates new tab, the new Spring bean (as part of the window/tab) should be created and added to the window manager bean (WindowManager.addWindow(...) has method that is colled from the p:commandButton and that creates window/tab and its session been). The question is - how to create this bean and initialize it (with injected beans)? One solution maybe is to call ctx.getBean("beanName"), but I am afraid to use this because it has name and this name seems to be unique.
Maybe programmatical creation of Spring beans is not good design (they should be created automatically but the web server/Spring context when they process the web requests), but it seems to be necessary in my case.
You must define that bean with scope "prototype", this setting causes that Spring context create a new fresh instance in every call to context.getBean("beanName");
To configure that, you can use:
#scope("prototype")
or
<bean id="beanName" class="com.foo.myBean" scope="prototype"/>
Depending on whether you are using java or xml configuration. Take a look to the Spring documentation for more details:
http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html
Related
If the Spring context cannot find a bean referred to from my xml I want to be able to provide some custom logic (ie look in another Spring Context or create the bean programmatically) before a BeanNotFoundException (whatever the expection is) is thrown.
You can use the BeanFactoryPostProcessor to define your beans dynamically (click on the link for an explanation).
Alternatively if you want to act on your bean in a lazy manner (instead of at app startup), which I strongly recommend not to do since you will have bugs related to the state of you beans config that is not visible at compile time: Anyway, you can surely add to your ApplicationContext a custom singleton : instead of calling getBean() from spring, if nothing was found, your class will be called to respond which bean corresponds to a bean name, and you will indirectly have the opportunity to handle BeanNotFoundException
See a post about the second (not recommended) solution here : How to add Properties to an Application Context
I'm new to Spring and a little confused about how it works. I get that I can use the application context to instantiate beans and have them populated. However, is the idea that I should be able to just write Bean b = new Bean() and then have Spring to somehow automagically populate that Bean?
I'm experimenting with Spring in a web application, and as far as I can see I need to inject the ApplicationContext into, say, the servlets to be able to instantiate other beans (services, daos etc.) from there. It's a bit cumbersome, but probably works.
However, is Spring meant to be able to hook into any object instantiation which happens on classes defined as beans in applicationContext.xml?
Spring is an Inversion of Control container. A bean is an object whose life cycle is managed by Spring. If you want Spring to populate an object, it needs to go through Spring, ie. it needs to be bean.
is Spring meant to be able to hook into any object instantiation
which happens on classes defined as beans in applicationContext.xml?
Spring doesn't hook into anything. You configure your beans and the relationships between them with Spring and Spring handles creating the instances and linking them up.
For domain objects, Spring provides a solution via the #Configurable annotation: http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/#aop-atconfigurable
It requires compile- or load-time-weaving and, thus, introduces some additional complexity but having the convenience of using the standard new Bean() syntax plus Spring's autowiring is worth it in my opinion.
Alternatively, you could define your domain objects as beans with prototype scope and use some factory to create them using the Spring ApplicationContext.getBean() method. With a scope of prototype a new instance will be returned every time and since you go through the ApplicationContext, Spring will do all the dependency injection magic as usual.
As for services and other beans with singleton scope, you would typically NOT retrieve them by first injecting the ApplicationContext and using it but instead you would inject them via either a constructor, setter or annotation-based strategy. The documentation covers that in detail: http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-collaborators
I am wondering if the following is possible. For testing purposes, I wish for different mock classes to be declared in the application context for different tests. These are acceptance tests, using the Jersey REST client. Is there a way to dynamically declare a bean at runtime? Does Spring have an API to allow changes to the application context after the context has been loaded?
The common way to have different beans in the application context is using profiles. You can read about profiles in the following spring source posts:
http://blog.springsource.org/2011/02/14/spring-3-1-m1-introducing-profile
http://blog.springsource.org/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles/
About your first question, you can declare beans at runtime via BeanDefinitionRegistry.registerBeanDefinition() method, for example:
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(SomeClass.class);
builder.addPropertyReference("propertyName", "someBean"); // add dependency to other bean
builder.addPropertyValue("propertyName", someValue); // set property value
DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getBeanFactory();
factory.registerBeanDefinition("beanName", builder.getBeanDefinition());
Is possible also to register a singleton bean instance (already configured) with
context.getBeanFactory().registerSingleton(beanName, singletonObject)
Finally, Spring don't provides a clear way to change a bean after refreshing the context, but the most common approachs are:
close and refresh again (obiously)
Use a proxy and swap the targetSource at runtime: see Replace spring bean in one context with mock version from another context (for an example).
How does Spring know when to call 'destory' method on a session/request scoped bean (in other words, how does it detect that the concerned bean is going out of scope)?
I read somewhere that it uses request/session listeners to be notified of these events. But these listners need to be defined in web.xml, and there's no mention of defining such listeners in Spring literature. So how does this work?
The org.springframework.web.servlet.DispatcherServlet does it. It uses own code, e.g. the org.springframework.web.context.request.RequestAttributes#registerDestructionCallback callback list functionality to register all these scoped beans.
and there's no mention of defining such listeners in Spring literature
Oh, there is:
To support the scoping of beans at the request, session, and global session levels (web-scoped beans), some minor initial configuration is required before you define your beans.[...]
If you use a Servlet 2.4+ web container, [...] you need to add the following javax.servlet.ServletRequestListener to the declarations in your web applications web.xml file[...]
From: 4.5.4.1 Initial web configuration.
Also note that Spring does not call destroy on prototype-scoped beans.
You can implement the interface DisposableBean and InitializingBean for session scoped bean.
The org.springframework.beans.factory.InitializingBean interface allows a bean to perform initialization work after all necessary properties on the bean have been set by the container. The InitializingBean interface specifies a single method afterPropertiesSet().
Implementing the org.springframework.beans.factory.DisposableBean interface allows a bean to get a callback when the container containing it is destroyed. The DisposableBean interface specifies a single method destroy().
Read more about it here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-nature
I want to clear some moments about integrating spring and struts. I have only one action class per application extended from MappingDispatchAction. So, actually my app when doing something uses not Action objects, but methods from my action. All I want from spring is to initialize this action and all for now. Just simply set DAO object. I looked through documentation, but I don't understand following:
We use action path from struts-config.xml as a name of bean in action-servlet.xml. Okay, but am I supposed to write beans in action-servlet.xml for every path name and set this poor DAO ref or what ?
The Struts 1 config file will use the DelegatingActionProxy class as the type attribute for all action configurations.
The Spring config file will contain the bean definitions of each action implementation. I don't know what DAO you're talking about, but actions that require DAO or service injection need to have them listed, yes--that's what Spring configuration is.
You may also be able to use annotations if you're not interested in using XML configuration, or use bean inheritance if many beans share the same DAO/service/etc. property values.