Refering parent bean using ApplicationContext - java

As a Spring beginner I get used to use BeanFactory :
Resource res1 = new ClassPathResource("bus.xml");
BeanFactory factory1 = new XmlBeanFactory(res1);
Resource res2 = new ClassPathResource("travel.xml");
BeanFactory factory2 = new XmlBeanFactory(res2,factory1);
Those configuration comes since I'm using 2 separate XML configs. which using <ref parent="bus"> in travel.xml.
bus.xml
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="bus" class="java4s.Bus">
<property name="maxSpeed" value="80" />
</bean>
</beans>
Travel.xml
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="travel" class="java4s.Travel">
<property name="v">
<ref parent="bus" />
</property>
</bean>
</beans>
Thinking about using ApplicationContext I have a question how to make those configs to be equally to ApplicationContext, since in the above example factory1 instance need to be passed to XmlBeanFactory (...,...) as second argument of the constructor, I've tried to google it many times since this morning but can't find the exact example. I need to transform them to something like :
ApplicationContext con1 = new ClassPathXmlApplicationContext("bus.xml");
ApplicationContext con2 = new ClassPathXmlApplicationContext("travel.xml",con1);
Thanks.
Edit : I try #JorgeCampos's suggestion :
ApplicationContext con1 = new ClassPathXmlApplicationContext("bus.xml","travel.xml");
Object o = con1.getBean("travel");
Journey j = (Journey)o;
But throwing me an error :
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'travel' defined in class path resource
[travel.xml]: Cannot resolve reference to bean 'bus' while setting
bean property 'v'; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'travel' defined in class path resource
[travel.xml]: Can't resolve reference to bean 'bus' in parent factory:
no parent factory available
EDIT : I FOUND THE ANSWER:
it's :
new ClassPathXmlApplicationContext(new String[]{"travel.xml"}, new ClassPathXmlApplicationContext("bus.xml"));
which is written in docs as (is it ?)
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent),
Thank you very much everyone! (specially #M. Deinum)

You should be able to compose multiple xml configuration files using the import element.

Related

Did not find bean NoSuchBeanDefinitionException

I try to get bean, by using ClassPathXmlApplicationContext. But I receive: NoSuchBeanDefinitionException: No bean named 'newsController' is defined
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("classpath*:conf/Spring_Config.xml");
NewsController newsController = (NewsController)
applicationContext.getBean("newsController");
In xml:
<bean id="newsController" class="NewsController"/>
Add full path to the bean class tag
class=com.foo.NewsController

Define '*.properties' file location in Spring

I have Spring context with several beans, like:
<bean id="anyBean" class="com.my.app.AnyBean"
p:test_user="${any1}"
p:test_pass="${any2}">
</bean>
To resolve these placeholders (${any1} and ${any2}) I use:
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="my.properties" />
It works fine, but I need to define location of the 'my.properties' from 'main' method of the main class. Like this:
ApplicationContext context = new ClassPathXmlApplicationContext(my_xml_config.xml);
PropertyPlaceholderConfigurer ppc = context.getBean("propertyPlaceholderConfigurer", PropertyPlaceholderConfigurer.class);
Resource resource = context.getResource("path/to/my.properties");
ppc.setLocation(resource);
But when I try to launch it:
Exception in thread "main"
org.springframework.beans.factory.BeanDefinitionStoreException:
Invalid bean definition with name 'AnyBean' defined in class path
resource [my_xml_config.xml]: Could not resolve placeholder 'any1' in
string value "${any1}"
Could you hint is there any way to resolve this problem?
By the time you try to get a bean
PropertyPlaceholderConfigurer ppc = context.getBean("propertyPlaceholderConfigurer", PropertyPlaceholderConfigurer.class);
Spring has already tried to refresh your context and failed since the property isn't present. You need to prevent Spring from doing this by specifying it in the constructor
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"my_xml_config.xml"}, false);
Since the ApplicationContext is not refreshed, the PropertyPlaceholderConfigurer bean doesn't exist.
For this to work, you need to use a PropertySourcesPlaceholderConfigurer instead of a PropertyPlaceholderConfigurer (thanks M.Deinum). You can declare it in the XML in the same way as you did for the PropertyPlaceholderConfigurer bean, or use
<context:property-placeholder />
You need to take advantage of the fact that PropertySourcesPlaceholderConfigurer has its own locations, but also uses the PropertySource instances registered in the ApplicationContext's Environment.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"your_config.xml"}, false);
// all sorts of constructors, many options for finding the resource
ResourcePropertySource properties = new ResourcePropertySource("path/to/my.properties");
context.getEnvironment().getPropertySources().addLast(properties);
context.refresh();

How to configure Spring lookup-method with Spring property

I'm trying to inject a property everytime a bean (myBean) is called using a lookup method and Spring dependency injection :
<bean id="myBean" class="com.myclass"
<property name="default" ref="myDefault" >
<lookup-method name="getUri" bean="defaultUri" />
</property>
</bean>
<bean id="defaultUri" scope="prototype" class="DefaultUri" >
</bean>
class myclass {
public String getUri(){
return "test"
}
}
Above XML returns this error on startup :
"XML document from PortletContext resource is invalied"
The error seems to be because <lookup-method name="getUri" bean="defaultUri" /> is configured incorrectly.
How can I configure a Spring lookup method within a String 'property' as I'm trying to implement in above XML ?
Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container.
Now, suppose you want to get a new instance of DefaultUri (which is a prototype bean) every time you call a method (let it be createDefaultUri) in myclass (which is a singleton bean). Then you can define MyClass as this:
class abstract Myclass {
public String getUri(){
// create a new instance of DefaultUri
DefaultUri defaultUri = createDefaultUri();
return "test"
}
protected abstract DefaultUri createDefaultUri();
}
The Spring Framework will generate a dynamic subclass of Myclass that will override the createDefaultUri method to provide a new instance of DefaultUri every time it is requested for.
You can now define the name of lookup-method name in the Myclass bean definition as this:
<bean id="defaultUri" scope="prototype" class="DefaultUri">
</bean>
<bean id="myBean" class="com.myclass"
<lookup-method name="createDefaultUri" bean="defaultUri" />
</bean>
Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A(getBeanB()), we expect to get new instance of bean B for every request. But The container only creates the singleton bean A once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed. To get new new instance of bean B for every request we need to use lookup-method injection
Please refer to http://www.javapointer.com/spring/spring-core/spring-lookup-method-injection/

how to do runtime bean deployement and destroy a bean in spring ioc container?

I have an application which is having a ClassPathXMLApplicationContext which has loaded some beans from spring xml files.
I want to add a bean at runtime. So i created another instance of ClassPathXMLApplicationContext which reads the new bean definitions from new xml files. Now i have two appContexts.
My Question is: how do i copy the beans from the new context to the old context? is it necessary to copy? cant i just merge these two contexts? is there an api for merging?
Later i want to undeploy the bean a runtime. I also want classloader to unload the bean class when i delete the bean.
How to delete a bean from an ApplicationContext and also unload the bean class.
Thanks,
Regards,
Vimal
You don't need second instance of ClassPathXMLAplicationContext. I think this will help you :
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Module.xml");
Product myProduct = (Product) context.getBean("Batery");
//when you want to change the bean with another
myProduct = (Product) context.getBean("CD-RW");
In the XML file you need two beans where "Batery" could initialize with what you want, but "CD-RW" can't be initialized with constructor. Here is an example with setter initialize :
<bean id="Batery" class="com.seller.springtest1.Battery">
<property name="name" value="AAA" />
<property name="price" value="2.5" />
</bean>
<bean id="CD-RW" class="com.seller.springtest1.Disc">
<property name="name" value="CD-RW" />
<property name="price" value="1.5" />
</bean>
I don't get the aquestion about deletion(it's garbage collector function) if you have special needs(when you retained the myProduct reference) you could do myProduct = null

Spring OXM doesn't work with Struts 1

I use Spring OXM as well as Struts 1 but without using integrating Struts with Spring IOC. This is because the application is an old one and I'm just adding a module that involves the XML binding and I have no intention to change the architecture of the application.
I have an action class calls ClasspathXmlApplicationContext for bean injection for the OXM.
Here is my spring context XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/oxm
http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd">
<bean id="xmlMapper" class="com.st.mas.wmr.utils.xml.stifbinconv.XmlMapper">
<property name="marshaller" ref="jaxbMarshaller" />
<property name="unmarshaller" ref="jaxbMarshaller" />
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="com.st.mas.wmr.utils.xml.jaxb.stifbinconv"/>
<property name="validating" value="true"/>
</bean>
</beans>
The action class:
public class StifBinConversionAction extends AnyDispatchAction {
private IProcessStifOliBinConversion svc;
public StifBinConversionAction() {
super();
svc = new ProcessStifOliBinConversion();
}
The service class:
public class ProcessStifOliBinConversion
implements
IProcessStifOliBinConversion {
private BasicDataSource ds;
private IAtomStifOliBinConversion dao;
private ApplicationContext ctx;
private XmlMapper xmlMapper;
public ProcessStifOliBinConversion() {
super();
ds = new BasicDataSource();
//TODO consts
ds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
ds.setUrl("jdbc:oracle:thin:#sglx482:1521:wmr");
ds.setUsername("wmr_online");
ds.setPassword("wmr_online");
dao = new AtomStifOliBinConversion(ds);
ctx = new ClassPathXmlApplicationContext("com/st/mas/wmr/utils/xml/stifbinconv/oxm-context.xml");
xmlMapper = ctx.getBean(XmlMapper.class);
}
The web application gives HTTP 500 WITHOUT any error message or stack trace. However, if I change the config location of the ClasspathXmlApplicationContext to an invalid one, Spring throws an exception.
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [classes/com/st/mas/wmr/utils/xml/stifbinconv/oxm-context.xml]; nested exception is java.io.FileNotFoundException: class path resource [classes/com/st/mas/wmr/utils/xml/stifbinconv/oxm-context.xml] cannot be opened because it does not exist
Seems that the problem is within the Spring injection.
It's irritating when there's an error but there's no error message. It makes you stuck for days.
Thanks
Will
It's irritating when there's an error
but there's no error message. It makes
you stuck for days.
??? There is an error message: your XML can't be found at this location:
classes/com/st/mas/wmr/utils/xml/stifbinconv/oxm-context.xml
I'd say you are passing bad parameters to the ApplicationContext. Take a look at the example in 4.7.1.1 Constructing ClassPathXmlApplicationContext instances - shortcuts
Consider a directory layout that
looks like this:
com/
foo/
services.xml
daos.xml
MessengerService.class
A ClassPathXmlApplicationContext
instance composed of the beans defined
in the 'services.xml' and 'daos.xml'
could be instantiated like so...
ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "daos.xml"}, MessengerService.class
Perhaps you should also use that Pattern with this Constructor:
ctx = new ClassPathXmlApplicationContext("oxm-context.xml", XmlMapper.class);

Categories