In jar file has interfrace ILogger.
Another jars has implementations ILogger. (Example one.jar:Logger1, two.jar:Logger2,...)In main file applicationContext.xml has line:
<import resource="classpath:META-INF/applicationContext.xml"/>
And each jar has local applicationContext.xml with description one bean.
I inject all logger implementattions:
#Autowired
List<ILogger> loggers;
But list has only one implementation (only Logger2).
If i explicitly indicate beans in main applicationContext.xml:
<bean id="logger1" class="demo.Logger1" />
<bean id="logger2" class="demo.Logger2" />
All work very good - list has all beans.
But I do not want to explicitly indicate all implementations.Is there a solution to my problem?
I did not have an asterisk after classpath. My worked import:
<import resource="classpath*:META-INF/applicationContext.xml"/>
Related
Creating a bean in a Maven project is rather simple. You add the #Autowiredannotation to the bean you wish to create and then declare its config in the spring-config.xml:
#Autowired
private ExampleBean exampleBean;
.
.
.
<bean id="exampleBean" class="path.to.your.bean">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
But what if I have a multi-moduled Maven project and the bean I would like to create is from another module referenced in the build path? How do you go about creating that bean?
I thought about the annotation #Resource but it didn't seem to "detect" the bean that is coming from another module added in the build path.
UPDATE 1:
Based on RĂ©mi's answer, here's what I did:
I added the following line to the xml config file of the module I wish to create the bean in:
<import resource="classpath:\dsp2aisp-business\*\root-context.xml" />
I also kept the #Autowired annotation on the AccountService (which is the bean I would like to use in this module).
In the other module where the AccountService is declared I added the bean declaration:
<bean id="accountService" class="fr.bnp.dsp2aisp.service.AccountService">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
But I kept getting this error:
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [fr.bnp.dsp2aisp.service.AccountService] for bean with name 'accountService' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]; nested exception is java.lang.ClassNotFoundException: fr.bnp.dsp2aisp.service.AccountService
But I'm certain that the class does in fact exist in the specified path.
Is there maybe another way to use a bean that is declared in another Maven Module?
I finally got it to work. When you have a multi-moduled Maven project, and you're trying to import one of those modules into another to use its classes, you shouldn't add your module from the build path (properties -> Java Build Path -> Projects ->add) because the compiler won't be able to find those classes in runtime.
What you need to do is to simply add those modules as Maven dependencies in the POM.xml file of the module you wish to use them in.
Example:
<dependency>
<groupId>com.test</groupId>
<artifactId>test-infra</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
The solution is insanely easy but finding it was a little bit tiring. I hope it'll help somebody else with the same problem.
You could do this by importing other maven project bean context form classpath :
<import resource="classpath:path/to/another/maven/module/context.xml" />
Then you can use all the beans defined in other maven project context in your actual maven project
There are a JAR A and JAR B, both have messages.properties in classpath /
And there is WAR C, which has dependencies on JAR A and JAR B.
And when I start WAR C I can only get i18n message from JAR A or JAR B.
So, how can Spring support multiple messages.properties files in classpath?
BTW, WAR C is a spring boot project, and spring.messages.basename=messages
Problem solved.
According to this question Does Spring MessageSource Support Multiple Class Path?
have to ditch ResourceBundleMessageSource and write a custom implementation of MessageSource (most likely by subclassing AbstractMessageSource) which uses PathMatchingResourcePatternResolver to locate the various resources and expose them via the MessageSource
I make a copy of ReloadableResourceBundleMessageSource and write the code by this guide and problem solved.
Yes, Spring supports loading multiple Properties. But properties should be unique. If we have same properties in the two Properties Files then the file which will be loaded later will override the previous Properties from previous file.
For example, if the Properties file from JAR A has two properties {USERNAME, PASSWORD} and JAR B Properties file also has the same two properties then you'll get {USERNAME, PASSWORD} from the file which is loading later.
You can use wildcard to import all the Property Files with same name on your classpath.
In Spring you can mention different Properties files in the form of Array as follows:
<context:property-placeholder
location="classpath:war.properties,
classpath*:message.properties"
ignore-unresolvable="true"/>
or
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:war.properties</value>
<value>classpath*:message.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
I am using spring web mvc project, and I put all the spring related files under WEB-INF\spring, including a ormlite.xml and a jdbc.properties.
Now I want to locate the jdbc.properties file in the ormlite.xml,Like this:
<context:property-placeholder location="/WEB-INF/spring/jdbc.properties"/>
But when I run the application ,it will told me that :
Could not load properties
It can not find the properties file.
What is the problem?
From Spring forum:
The problem is that /WEB-INF isn't accessible as it isn't in the root
of the path, you must use the same path as you use in your test case
(include the src/main/webapp part but that will break your application
from running).
I suggest you move the jdbc.properties to the src/main/resources
directory and simply use classpath: prefix to load the properties.
Code:
<context:property-placeholder location="classpath:jdbc.properties"/>
The code above assumes they are on the root of the classpath (which is
where they are when they are in src/main/resources).
I hope this can help someone else.
I had the same problem - property files outside the classpath.
My solution:
First define a properties bean:
<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>/WEB-INF/your.properties</value>
</property>
</bean>
Then reference it in the property-placeholder:
<context:property-placeholder properties-ref="configProperties" />
Works perfectly well for me!
Instead of:
<context:property-placeholder location="/WEB-INF/spring/jdbc.properties"/>
Use:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/spring/jdbc.properties"/>
And your properties will be available in Spring file, and don't forget to add a namespace: xmlns:p="http://www.springframework.org/schema/p"
I think you're missing the prefix to instruct Spring how to attempt to load the properties. I think your definition needs to be:
<context:property-placeholder location="file:/WEB-INF/spring/jdbc.properties"/>
Note the addition of the file: prefix.
I am working on the spring spring-3.2.2. I have created two java projects in eclipse.
SpringTest
Testclasspath
SpringTest project is having the below beans.xml in which the one bean is defined.
<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">
<bean id="helloWorld" class="com.spring.HelloWorld" init-method="testUpdate" scope="prototype">
<property name="message" value="Hello World!"/>
</bean>
</beans>
I have created the jar springtest.jar of the project SpringTest and it is been added in the classpath of the project Testclasspath. Bean configuration file for the Testclasspath project is talentacquisition.xml and it is importing the beans.xml file of the Springtest project. Please find the below content of talentacquisition.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-3.0.xsd">
<import resource="Beans.xml"/>
<bean id="juggler" class="com.springaction.springidol.Juggler" />
</beans>
I am confused with behavior of the import tag in the talentacquisition.xml How it is able to locate the Beans.xml which is present in the jar (springtest.jar) in the classpath and able to load the beans? Why spring is not giving any error ? Don't I have to modify the import tag in the talentacqusition.xml to following
<import resource="classpath:Beans.xml"/>
If import is able to locate the file Beans.xml , then when should we use classpath: and classpath* :?
ResourceLoaders are responsible for how Spring loads the resource. From the reference manual
The location path or paths supplied to an ApplicationContext
constructor are actually resource strings, and in simple form are
treated appropriately to the specific context implementation.
ClassPathXmlApplicationContext treats a simple location path as a
classpath location. You can also use location paths (resource strings)
with special prefixes to force loading of definitions from the
classpath or a URL, regardless of the actual context type.
The ClassPathXmlApplicationContext you're instantiating "treats a simple location path as a classpath location", i.e. it treats "Beans.xml" as "classpath:Beans.xml". Similarly, FileSystemXmlApplicationContext would treat "Beans.xml" as "file:Beans.xml".
Section 6.7 of the manual has more details too.
I'm getting the following:
2013-03-27 18:51:54,944 ERROR pringframework.web.context.ContextLoader: 227 - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exporter' defined in URL ... Cannot resolve reference to bean 'dynamicNamingStrategy' while setting bean property 'namingStrategy'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'dynamicNamingStrategy' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at
and also STS is complaining:
Multiple annotations found at this line:
- Referenced bean 'dynamicNamingStrategy'
not found
with the following Spring contexts setup:
In a project, I have a jmx management context (core-app-web-common-management-context.xml) with following (excerpt):
<context:annotation-config />
<context:component-scan
base-package="com.a.b.c.management.*" />
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"
lazy-init="false">
<property name="autodetect" value="true"></property>
<property name="namingStrategy" ref="dynamicNamingStrategy"/>
where dynamicNamingStrategy is defined in a different project (and packaged into a different jar) and is referred to in the component-scan above, as follows
package com.a.b.c.management;
#Component("dynamicNamingStrategy")
public class DynamicNamingStrategy extends KeyNamingStrategy {
......
The above Spring context is in turn imported into the main context located in the same project:
<import resource="classpath*:/META-INF/spring/core-app-web-common-management-context.xml"/>
So, somehow the #Component scanning for DynamicNamingStrategy is not working...
If I instead use this property definition in exporter, then it works:
<property name="namingStrategy"><bean class="com.a.b.c.management.DynamicNamingStrategy" /></property>
but I'd like to understand why the component scanning mechanism falters in the first instance, apparently I'm missing something.
Also, Spring Explorer view in STS is missing that bean as well. Enabling support for elements in configuration files option doesn't seem to make a difference.
Drop the .* at the end of your package name in your <context:component-scan> elements base-package attribute. I would think that this is causing the component-scan to look for a package named *, which there probably isn't one (can't be one).
The base-package is just that, the base package. The component-scan will scan all children of all base packages, therefore there is no need to have the .* wildcard at the end of your package name.