Spring context scanning behavior - spring

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.

Related

Creating A Bean From Another Maven Module

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

How to resolve "cyclic loading of class path resource"?

I have two separate projects. One is maven, spring webservices(Let's say this is project A) and the other is maven batch project(Let's call it B).
I am trying to inject a class(let's say class "batch.java") from B into a class(let's call it "api.java") of A.
One major problem statement is that B has a dependency on A( on a different class of A, not on api.java).And I believe this is causing the cyclic loading error on startup.
I will paste my code here and I request to please provide a solution to it:
file:B.xml
<import resource="classpath:A.xml" />
<bean id="batch" class="XXX">
<!-- lookup methods from project A -->
</bean>
file:A.xml
<import resource="classpath*:B.xml"/>
<bean id="api" scope="prototype" lazy-init="true">
<property name="batch" ref="batch" />
</bean>
The code compiles fine but when I try to start my wsdl I get the following error:
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:B.xml]
Offending resource: class path resource [A.xml]; nested exception is org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:A.xml]
Offending resource: class path resource [B.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Detected cyclic loading of class path resource [A.xml] - check your import definitions!
org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
Unfortunately you need to break the cyclic dependency.
Put all commonly used bean definitions into a separate context and reference this context in your sub-contexts.
Then you should end up with at least 3 context.xml's - eg:
common-context.xml (contains all bean definitions that are used in all sub-contexts)
a-context.xml (includes common-context.xml)
b-context.xml (includes common-context.xml)

Custom Document Filter - ClassNotFoundException when starting Connector

I am developing a custom document filter. So far I have created a project in eclipse, added jar files necessary and successfully built a jar file with my own document filter.
What step am I missing to make the connector find the class ??
When it comes to configuring the document filter in the file 'connectorInstance.xml' something goes wrong and its seems the jar file cannot be found in the class path...
The Java package has the following classpath :
com.google.enterprise.connector.util.filter.DocFilterWildCardSearch
or also tried the following path
com.kapsch.gsa.filter.DocFilterWildCardSearch
I copied the 'DocFilterWildCardSearch.jar' file into the following path:
C:\Program Files\GoogleConnectors\GSAConnectors1\Tomcat\webapps\connector-manager\WEB-INF\lib
Restarted the connector and got the following error message:
Nov 20, 2013 4:50:29 PM [Init] com.google.enterprise.connector.servlet.StartUp doStartup
SEVERE: Connector Manager Startup failed:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DocumentFilters' defined in ServletContext resource [/WEB-INF/documentFilters.xml]: Cannot create inner bean 'asfsdf' of type [com.kapsch.gsa.filter.DocFilterWildCardSearch] while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [com.kapsch.gsa.filter.DocFilterWildCardSearch] for bean with name 'asfsdf' defined in ServletContext resource [/WEB-INF/documentFilters.xml]; nested exception is java.lang.ClassNotFoundException: com.kapsch.gsa.filter.DocFilterWildCardSearch
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:230)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:117)
Config file for Document Filter : connectorInstance.xml
<?xml version="1.0"?>
<beans>
<bean class="com.example.connector.HelloWorldConnector" id="helloworld-connector"> </bean>
<bean class="com.google.enterprise.connector.util.filter.DocumentFilterChain" id="DocumentFilters">
<constructor-arg>
<list>
<bean class="com.kapsch.gsa.filter.DocFilterWildCardSearch" id="asfsdf">
<property value="Author" name="propertyName"/>
<property value="Roli" name="propertyValue"/>
<property value="false" name="overwrite"/>
</bean>
</list>
</constructor-arg>
</bean>
</beans>
Your settings are supposed to go inthe the documentFilters.xml file and not the connector instance file.
Google's got a support article on the subject here here.
It looks like you're attempting to nGram. I've got a filter already that I've been meaning to open source. If you would like it, drop me a note.
Finally, 7.2 is rumored to have wild carding in. We won't know for sure until it comes out.
Any chance you can include the output of jar tf on your doc filter jar file?
Michael is right in that you configure doc filters in documentfilters.xml.

Spring session factory not finding mapping files in multiple directories with same class path

I am having problems when loading hibernate mappings from multiple paths.
My Spring session factory is define as follows:
<beans>
...
<bean id="sessionFactory" class="org.springframwork.orm.hibernate3.LocalSessionFactory">
</bean>
<property name="mappingLocations">
<list>
<value>classpath:/mapping/*.hbm.xml</value>
</list>
</property>
When I put my mappings Foo.hbm.xml and Bar.hbm.xml into the directory src/main/resources/mappings, then both mappings are found when Hibernate is initialized.
But when I put Foo.hbm.xml into the directory src/main/resources/mapping and Bar.hbm.xml into the directory src/test/resources/mapping, then only the latter mapping file can be found. Hibernate will fail with "cannot find mapping for Foo" error.
I can see that the mappings are copied to the directories target/classes/mapping and target/test-classes/mapping, so why cannot hibernate (or the spring local session factory bean) find both mapping files? I thought that "classpath:/mapping/*.hbm.xml" would find both target/classes/mapping and target/test-classes/mapping directories?
edit: I am getting this problem when running unit tests, so I expect that mappings found in both src/main/resources and src/test/resources would be found.
You are using maven. And since you put your Bar mapping into the test resource directory, it is only available when running tests.
I assume you have a persistence-unit configured similar to the example below
<persistence-unit ...>
<class>something.Foo</class>
<class>something.Bar</class>
</persistence-unit>
What happens at start-up is that Spring starts Hibernate, hibernates reads the persistence-unit and asks the factory for the mappings. But remember, Bar is only a test class. So Spring finds the mappings from src/main/resources, but since it does not run as a test, it does not see src/test/resources.

Spring context:property-placeholder can't resovle nested variables

I have two projects -- project-web, and project-service, both of them use Spring core 3.1.3 and have configurations to load properties from corresponding property files:
project-web -- Spring Integration based project, in its spring config file:
<context:property-placeholder location="WEB-INF/spring-integration/spring-integration.properties" ignore-resource-not-found="true" />
<import resource="classpath*:META-INF/spring/applicationContext.xml" />
where the import is to include the spring configuration file from project-service, and in the project-service project, I have following configured:
<context:property-placeholder location="classpath:META-INF/application.properties, classpath:META-INF/db.properties" ignore-resource-not-found="true"/>
<import resource="classpath:META-INF/spring/applicationContext-data.xml"/>
where the import to include Spring configuration for the DAOs, inside the applicationContext-data.xml I have:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.${db.type}.driver}" />
<property name="url" value="${db.${db.type}.url}"/>
<property name="username" value="${db.${db.type}.username}" />
<property name="password" value="${db.${db.type}.password}" />
</bean>
When I run the unit tests for project-service, everything is fine, all the variables are resolved correctly without any problem. But when I run the project-web (project-service will be included as a .jar file in the WEB-INF/lib folder of project-web), it throws error during start up saying can't resolve ${db.type}:
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [META-INF/spring/applicationContext-data.xml]: Could not resolve placeholder 'db.type' in string value "db.${db.type}.driver"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209) ~[spring-beans-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:174) ~[spring-context-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:151) ~[spring-context-3.1.3.RELEASE.jar:3.1.3.RELEASE]
......................
Note: I can't declare everything in the project-web, because project-service will be also used by other projects. Anyone know why in project-service works when it runs alone but not when included by the project-web? It can't resolve the nested variable ${db.type}
The problem is that your first PropertyPlaceHolderConfigurer is trying to resolve the placeholder that needs to be resolved by the second one.
You can either use a different prefix for each one (e.g. !{ instead of ${ for one of them), or set
ignore-unresolvable="true"
on the first one - then it will leave the resolution to the other one.

Resources