I am very new to Spring Framework. I am using NetBeans for IDE. I followed couple of tutorials to learn it by myself. However, I am stuck in the middle and cannot proceed further. Let me breakdown my project here:
My project folder structure looks like this:
There are two classes; the major one MainApp.java contains following code:
package com.myprojects.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context;
context = new ClassPathXmlApplicationContext("classpath*:beans.xml");
FirstPage obj;
obj = (FirstPage) context.getBean("firstPage");
obj.getMessage();
}
}
Second class file FirstPage.java looks like this:
package com.myprojects.spring;
public class FirstPage {
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
The beans.xml file looks like below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.0.RELEASE.xsd
">
<bean id = "firstPage" class = "com.myprojects.spring.FirstPage">
<property name = "message" value = "Hello World!"/>
</bean>
</beans>
Now, the error I am getting is like below:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'firstPage' is defined
I know I have been doing some silly mistake here.
Thank you in Advance !
Almost similar problem have been discussed before. I think your program is unable to locate beans.xml.
Try doing this:
context = new ClassPathXmlApplicationContext("META-INF/beans.xml");
EDIT:
This new error XmlBeanDefinitionStoreException means that your schema is not valid. Try changing your schema as described in one of these answers:
https://stackoverflow.com/a/21525719/2815219
https://stackoverflow.com/a/25782515/2815219
Spring configuration XML schema: with or without version?
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id = "firstPage" class = "com.myprojects.spring.FirstPage">
<property name = "message" value = "Hello World!"/>
</bean>
</beans>
According to the directory structure you posted it is very likely that src/main/resources is on your classpath. If you like to reference your spring context file beans.xml you have to specify it relative to the folders on your classpath. Hence you should try:
context = new ClassPathXmlApplicationContext("classpath:/META-INF/beans.xml");
Besides: the notation classpath*:beans.xml means you want to read in all context files having a name of beans.xml.
Put beans.xml to outside Meta-inf ,
or use new ClassPathXmlApplicationContext("META-INF/beans.xml");
And http://www.springframework.org/schema/beans/spring-beans-4.0.0.RELEASE.xsd
should change to
http://www.springframework.org/schema/beans/spring-beans-4.0.0.xsd , as spring's xsd filenames don't contain "RELEASE".
The xsd files are in org.springframework.beans.factory.xml package in spring-beans.jar, see if the xsd file is in that package.
Doing following two things solved my issue.
1) There was an incorrect beans.xml path. I changed that to context = new ClassPathXmlApplicationContext("META-INF/beans.xml");.
2) Also, there was an invalid xsi:schemaLocation attribute value. I changed that attribute's value to http://www.springframework.org/schema/beans/spring-beans-3.0.xsd.
Thank you all for your help.
Related
I have two packages A and B with a class X within package B. I need to use an instance of a X in A.
Catch here is package B contains Java Bean spring configuration while A uses XML.
Here is how package B's AppConfig looks like.
#Configuration
public class PackageBJavaBeans {
#Bean
public X getX(final String paramOne, final String paramTwo) {
String value = doSomeProcessingWithParameters(paramOne, paramTwo);
return new X(value);
}
private String getXValue(final String paramOne, final String paramTwo){
final String value = //do-some-calculation
return value;
}
}
I need to create a bean of class X in package "A" with XML. How do I pass parameters via XML from package A?
Thanks.
I think this is what you're asking for.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Definition for X bean -->
<bean id="X" class="A.X">
<constructor-arg value="The value this bean holds"/>
</bean>
</beans>
I'm a little confused on what exactly you want. Do you still want us to use the provided function that would concatenate the two strings together before creating X? That is possible using a factory method. Let me know if you want an example of a factory method bean.
So I have been using the 3.2.0.RELEASE Spring XML configurations for most of my beans but now I am faced with a unique situation where the Getters and Setters can't be used (bad legacy code - can't get around it).
As such, I want to use Spring #Configuration class and the XML to workaround this problem.
However, I am getting "Class Not Found" exception when it tries to read my #Configuration Class.
Caused by: java.lang.ClassNotFoundException: v1.inventory.item.myJavaConfig
My XML file which is failing looks like this:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="v1.inventory.item.myJavaConfig"/>
</beans>
My #Configuration class looks like this:
package v1.inventory.item;
#Configuration
#ImportResource("classpath:v1/inventory/item/baseItemConfigs.xml")
public class myJavaConfig {
#Autowired
#Qualifier("parentItem")
Item baseItem;
#Bean
public Item realItem(){
Item modifiedBean = baseItem;
modifiedBean.setManufacturer("Fake Setter for Manufacturer");
modifiedBean.setDesigner("Fake Setter for Designer");
return modifiedBean;
}
}
I need this to be read by the ApplicationContext so I need to make sure these beans can be found. Is this a bug with Spring 3.2.0.RELEASE? Or my code?
For the record, I am pulling in the #Configuration last (parentItem is scanned first in XML).
I figured out the issue here.
It seems that maven/spring (not sure which) wasn't looking in my "resource" directory for the file. Only my "java" directory. When I moved my file into the "java" directory, Spring found the file just fine.
The tests which were passing in JUnit now pass using the Maven compiler (which was throwing the above error during the test phase)
I'm fairly new to spring so excuse me if this is a dumb question. When I try to launch a program I get the following error: java.lang.IllegalArgumentException: Could not resolve placeholder 'appclient' in string value [${appclient}]. The error is thrown when the following code is executed:
package ca.virology.lib2.common.config.spring.properties;
import ca.virology.lib2.config.spring.PropertiesConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
#Configuration
#Import({PropertiesConfig.class})
#PropertySource("${appclient}")
public class AppClientProperties {
private static final Logger log = LoggerFactory.getLogger(AppClientProperties.class);
{
//this initializer block will execute when an instance of this class is created by Spring
log.info("Loading AppClientProperties");
}
#Value("${appclient.port:}")
private int appClientPort;
#Value("${appclient.host:}")
private String appClientHost;
public int getAppClientPort() {
return appClientPort;
}
public String getAppClientHost() {
return appClientHost;
}
}
A property file called appclient.properties exists in the resources folder with the information for host and port. I'm not sure where the "${appclient}" is defined, if it is at all. Maybe it is not even defined and that is causing the problem. Do I need to change the "${appclient}" to something like "{classpath:/appclient.properties}" or am I missing something else?
You are not reading the properties file correctly. The propertySource should pass the parameter as: file:appclient.properties or classpath:appclient.properties. Change the annotation to:
#PropertySource(value={"classpath:appclient.properties"})
However I don't know what your PropertiesConfig file contains, as you're importing that also. Ideally the #PropertySource annotation should have been kept there.
If you are using Spring 3.1 and above, you can use something like...
#Configuration
#PropertySource("classpath:foo.properties")
public class PropertiesWithJavaConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
You can also go by the xml configuration like...
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:property-placeholder location="classpath:foo.properties" />
</beans>
In earlier versions.
Hopefully it will be still helpful, the application.properties (or application.yml) file must be in both the paths:
src/main/resource/config
src/test/resource/config
containing the same property you are referring
If your config file is in a different path than classpath, you can add the configuration file path as a system property:
java -Dapp.config.path=path_to_config_file -jar your.jar
I know It is an old message , but i want to add my case.
If you use more than one profile(dev,test,prod...), check your execute profile.
In my case , I forgot to add the new property in my application.properties under test folder.Adding it resolved the issue
For properties that need to be managed outside of the WAR:
<context:property-placeholder location="file:///C:/application.yml"/>
For example if inside application.yml are name and id
Then you can create bean in runtime inside xml spring
<bean id="id1" class="my.class.Item">
<property name="name" value="${name}"/>
<property name="id" value="${id}"/>
</bean>
in my case, the war file generated didn't pick up the properties file so had to clean install again in IntelliJ editor.
If the issue occurs in IntelliJ, all you have to do is to install the plugin https://plugins.jetbrains.com/plugin/7861-envfile and follow the steps given.
My solution was to add a space between the $ and the {.
For example:
#Value("${appclient.port:}")
becomes
#Value("$ {appclient.port:}")
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);
Can you enlighten me on this problem I encountered while experimenting with Spring.
I have 2 context here. let's name them springA.xml and springB.xml
springA.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="springB.xml" />
<bean name="name2" class="java.lang.String"/>
</beans>
springB.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="name2,name3" class="java.lang.String"/>
</beans>
springC.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="name3,name2" class="java.lang.String"/>
</beans>
And this is my Java File.
public static void main(String[] args) {
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("springA.xml"));
Object obj1 = factory.getBean("name2");
Object obj2 = factory.getBean("name3");
System.out.println(obj1.getClass().getName() + " " + obj2.getClass().getName());
}
And the result, I get a "java.lang.String java.lang.String". If I change the position of
the name "name2,name3" to "name3,name2" (springC.xml), I get a "java.lang.Object java.lang.Object".
I am just confused as to why the result is like that. I was expecting that the function will return java.lang.String for name2 and java.lang.Object for name3 (since name2 is already used in the springA.xml, I am assuming this name will not be used and instead, will use name3 for springB.xml)
Thanks!
PS:
Spring 2.5
Eclipse 3.5
From Spring's documentation:
Every bean has one or more ids (also
called identifiers, or names; these
terms refer to the same thing). These
ids must be unique within the
BeanFactory or ApplicationContext the
bean is hosted in.
According to this, your combined application context is invalid as it contains two different beans which have the same ID - your bean named "name2" from ContextA.xml and your bean named "name2", aliased "name3" in ContextC.xml. I would expect Spring to issue at least a warning about this.
To answer your question: You shouldn't expect any sane results from this kind of setup. Bean names have to be unique and if they aren't the results are undefined. And by "undefined" I mean "unlikely to be helpful" :)
Hope this helps.
I believe you are seeing different results because Spring is loading the beans in the context in different orders in each scenario. Spring makes no guarantee as to which order it will load it's beans other than the fact that any beans used as "ref"'s in other bean definitions will be loaded before the beans that depend on them.
The correct solution to your problem is DO NOT use duplicate bean identifiers and then you won't have to guess as to which bean you will get when you look one up.
I've ran your code on Spring 2.5.6 and 3.0.0.M1 and both version produce the same result.
java.lang.String java.lang.String
My advice is if you want two strings and you are getting strange results with 2.5, then bump to 2.5.6 or 3.0.0.M1.