Why won't spring autowire my test? - spring

I've got the following spring configuration (actually, the configuration is more extensive, but I've included relevant parts):
testApplicationContext.xml
<!-- Business -->
<import resource="contexts/testBusinessContext.xml" />
<!-- Dao -->
<import resource="contexts/testDaoContext.xml" />
<!-- Persistence configuration -->
<import resource="contexts/testPersistenceContext.xml" />
<!-- Service actions -->
<import resource="contexts/testServiceActionContext.xml" />
testBusinessContext.xml
<bean id="basketBusiness" class="com.company.salesdataservice.business.BasketBusiness">
<property name="basketDao" ref="basketDao" />
<property name="tokenDao" ref="tokenDao" />
<property name="houseDao" ref="houseDao" />
<property name="currencyDao" ref="currencyDao" />
</bean>
testDaoContext.xml
<bean id="currencyDao" class="com.company.salesdataservice.dao.CurrencyDao">
<property name="dataSource" ref="companyDomainDataSource" />
</bean>
<bean id="houseDao" class="com.company.salesdataservice.dao.HouseDao"/>
<bean id="basketDao" class="com.company.salesdataservice.dao.BasketDao">
<property name="dataSource" ref="companyBookingDataSource" />
</bean>
<bean id="tokenDao" class="com.company.salesdataservice.dao.JavaRandomTokenDao" />
testPersistenceContext.xml
<bean id="companyBookingTransactionManager" class="com.company.utils.data.TransactionManager">
<property name="manager" ref="companyBookingSpringTransactionManager" />
</bean>
<bean id="companyBookingSpringTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="companyBookingDataSource" />
</bean>
<!-- initialised by a DataSourceInitializer. Left out for brevity. -->
<jdbc:embedded-database id="companyBookingDataSource" type="H2"/>
<!-- initialised by a DataSourceInitializer. Left out for brevity. -->
<jdbc:embedded-database id="companyDomainDataSource" type="H2"/>
testServiceActionContext.xml
<bean id="createBasketServiceAction" class="com.company.salesdataservice.serviceaction.CreateBasketServiceAction">
<property name="transactionManager" ref="companyBookingTransactionManager" />
<property name="basketBusiness" ref="basketBusiness" />
</bean>
I'm trying to autowire a field of the type CreateBasketServiceAction in one of my tests:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/testApplicationContext.xml"})
public class CreateBasketServiceActionTest {
#Autowired
CreateBasketServiceAction createBasketServiceAction;
}
However, Spring keeps telling me that it can't autowire:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.company.utils.data.serviceaction.TransactionalServiceAction] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
If i replace that field with a BasketBusiness basketBusiness field, then Spring is perfectly capable of doing it.
As far as I can see, both CreateBasketServiceAction and BasketBusiness is defined as a <bean /> in the XML configuration.
I've been banging my head against the wall for the past few hours on this. What am I doing wrong?

Related

Spring factory-bean with property resolution

Is it possible to have property resolution on the factory-bean field of a Spring bean declaration?
Example:
<bean factory-bean="$APP{some.factory.bean}" factory-method="...">
Spring version: 3.2.4
Adding a PropertyPlaceholderConfigurer to your spring context should work:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:yourfile.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
</bean>
You can declare your propertyName in the file and then use it like:
<bean factory-bean="${propertyName}" factory-method="...">
Just encountered the same issue (using Spring 4.2.0). It seems that property resolution for factory beans does not work despite what they say in SPR-12638. I've ended up using ProxyFactoryBean as a workaround.
The desired configuration, which does not work:
<!-- The bean to be created: factory type determined in runtime -->
<bean id="..." factory-bean="factory-${factory.type}" factory-method="..." />
<!-- Possible factories -->
<bean id="factory-A" class="..." />
<bean id="factory-B" class="..." />
<bean id="factory-C" class="..." />
The workaround that I've found:
<!-- The bean to be created: use factory proxy -->
<bean id="..." factory-bean="factory-proxy" factory-method="..." />
<!-- The factory proxy: real factory type determined in runtime -->
<bean id="factory-proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="factory-${factory-type}" />
</bean>
<!-- Possible factories -->
<bean id="factory-A" class="..." />
<bean id="factory-B" class="..." />
<bean id="factory-C" class="..." />
Enjoy :)

Issue with JMS + AOP + JNDI Resources

Hi and happy new year
I'm working on a project which need to implement jms, aop and some jndi resources.
So far, the project works fine when there are only jms and jndi but when i activated aop, i had some troubles.. here is the configuration :
<!-- JMS implementation -->
<bean id="jmsRefConnectionFactory.activemq" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/activeMQConnectionFactory" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.QueueConnectionFactory" />
</bean>
<bean id="jmsRefQueue.activemq" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/activeMQQueue" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.Queue" />
</bean>
<bean id="jmsConnectionFactory.activemq" class="org.springframework.jms.connection.SingleConnectionFactory">
<constructor-arg ref="jmsRefConnectionFactory.activemq" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsConnectionFactory.activemq" />
<property name="defaultDestination" ref="jmsRefQueue.activemq" />
<property name="destinationResolver" ref="jmsDestinationResolver.amq" />
<property name="sessionTransacted" value="true" />
<property name="sessionAcknowledgeMode" value="#{T(javax.jms.Session).CLIENT_ACKNOWLEDGE}" />
</bean>
<bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsRefConnectionFactory.activemq" />
</bean>
<bean id="jmsDestinationResolver.amq"
class="org.springframework.jms.support.destination.DynamicDestinationResolver" />
When I start the application, I get this error :
Caused by: org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public abstract javax.jms.Connection javax.jms.ConnectionFactory.createConnection() throws javax.jms.JMSException] on target [org.apache.activemq.ActiveMQConnectionFactory#239f 6]; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class
Context.xml content :
<!-- APACHE MQ -->
<Resource name="jms/activeMQConnectionFactory" auth="Container"
type="org.apache.activemq.ActiveMQConnectionFactory" description="JMS Connection Factory"
factory="org.apache.activemq.jndi.JNDIReferenceFactory" HOST="localhost"
PORT="61616" CHAN="" TRAN="1" QMGR="MyQCF" />
<Resource name="jms/activeMQQueue" auth="Container"
type="org.apache.activemq.command.ActiveMQQueue" description="my Queue"
factory="org.apache.activemq.jndi.JNDIReferenceFactory" physicalName="userQueue" />
Web.xml content :
<resource-ref>
<res-ref-name>jms/activeMQConnectionFactory</res-ref-name>
<res-type>javax.jms.QueueConnectionFactory</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref>
<res-ref-name>jms/activeMQQueue</res-ref-name>
<res-type>javax.jms.Queue</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
This configuration is OK when aop is not activated but for some reasons, it doesn't work when aop is on..
Spring version : 3.1.2
I'm using activemq (5.7)
I found out what was the problem..
Turns out the aop was not even involved (at least not the configuration that i put). I had some jar in my tomcat server that was not taken for some reasons (i think it's about lib priority/ parent first/last)...
I changed the location and directly put into my project and it works now ! :)

Multiples Project Persist Spring Data

I'm Having a Weird problem with Spring Data.
I Have 2 different projects, witch one have your schema on postgres.
on the first project i can do the CRUD in any entity and everything work's fine.
And in the second project, i have dependency of the first project, i can do the CRUD in anything of the second project and list anything of the first project. But i can't persist anything of the first project
I Realize that if i throw this line
<import resource="classpath*:applicationContext.xml" />
in the end of my Application context of the second application, i CAN persist anything of the first project on the second project, BUT i CAN'T persist anymore the things of the second project.
And if i let this line in the begginning of the application-context.xml of the second aplication it will persist normal the model of the second projet.
here it is the complete XML Application-context of the second project:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Carregar os dados applicationOrcamento.properties na memória -->
<!-- <context:property-placeholder location="classpath*:applicationOrcamento.properties"
ignore-unresolvable="true"/> -->
<import resource="classpath*:applicationContext.xml" /> <!-- this line that i'm having problem Application Context of the first project if this line is here, i can persist anything of the second project, if i put on the end will persist any thing of the first project, but nothing of the second project... -->
<!-- Activates scanning of #Autowired -->
<context:annotation-config />
<context:component-scan
base-package="br.com.secondProject.package.repository" />
<context:component-scan base-package="br.com.secondProject.package.services" />
<!-- <context:component-scan base-package="br.com.firstProject.package.repository"
/> -->
<!-- <context:component-scan base-package="br.com.firstProject.package.services"
/> -->
<jpa:repositories base-package="br.com.secondProject.package.repository"
entity-manager-factory-ref="entityManagerFactoryOrcamento" />
<bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator" />
<!-- Database -->
<bean id="datasourceOrcamento"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url"
value="jdbc:postgresql://localhost:5432/DB?searchpath=second_project" />
<property name="username" value="postgres" />
<property name="password" value="123456" />
</bean>
<!-- Entity Manager -->
<bean id="entityManagerFactoryOrcamento"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasourceOrcamento" />
<property name="persistenceUnitName" value="second-project-pu" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<!-- <property name="generateDdl" value="true" /> -->
</bean>
</property>
<property name="packagesToScan" value="br.com.secondProject.package.model" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<!-- Alterar para JTA quando for para produção! -->
<!-- <jee:jndi-lookup jndi-name="java:/prject-ds" id="datasource" resource-ref="true"/> -->
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryOrcamento" />
</bean>
<tx:annotation-driven />
`
Ther Persistence.xml of the second application is also importing the classes of the first project, th real problem is persist an entity of the first project on the second project
i have already tried to put on my controller the
#ContextHierarchy({
#ContextConfiguration(locations = { "/applicationContextOrcamento.xml"}), //second Project xml
#ContextConfiguration(locations = { "classpath*:applicationContext.xml" })// first project xml
})
but doens't work...
i just need to persist an entity of the first project inside the second project

Spring resource

Problem: I want to make the below bean definitions (specified in aaplicationContext.xml) optional for "org.springframework.web.context.ContextLoaderListener". If i am not providing the "emsPropLocation" context parameter correctly, tomcat web container is not able to initialized properly and it is obvious reason. Is there any way to make it optional?
appicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false"/>
<property name="location" value="file:/#{contextParameters.emsPropLocation}" />
</bean>
<!-- TIBCO Connection Factory Bean -->
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<constructor-arg value="${emsServerURL}"/>
<property name="userName" value="${emsUserName}"/>
<property name="userPassword" value="${emsPassword}"/>
<property name="connAttemptCount" value="${connAttemptCount}"/>
<property name="connAttemptDelay" value="${connAttemptDelay}"/>
<property name="connAttemptTimeout" value="${connAttemptTimeout}"/>
<property name="reconnAttemptCount" value="${reconnAttemptCount}"/>
<property name="reconnAttemptDelay" value="${reconnAttemptDelay}"/>
<property name="reconnAttemptTimeout" value="${reconnAttemptTimeout}"/>
</bean>
<!-- bean id="tibcoUtil" class="com.nr.ns.upload.TibcoUtil" scope="singleton">
<constructor-arg value="true"/>
</bean-->
<bean id="jmsExceptionListener" class="com.nr.ns.upload.LogMsgExceptionListener"/>
<!-- Spring CachingConnectionFactory Bean -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="tibcoConnectionFactory"/>
<property name="reconnectOnException" value="${reconnectOnException}"/>
<property name="sessionCacheSize" value="${sessionCacheSize}"/>
<property name="exceptionListener" ref="jmsExceptionListener"/>
</bean>
<!-- JMSTemplate Bean -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="connectionFactory"/>
<property name="receiveTimeout" value="${receiveTimeout}"/>
<property name="deliveryMode" value="${deliveryMode}"/>
</bean>
We are keeping WAR file outside tomcat and to make it happen we have "app.xml" file inside TOMCAT_HOME/conf/Catalina/localhost.
app.xml:
<Context path="/app"
docBase="/abc/ccp/app.war"
reloadable="true"
unpackWAR="false">
<Parameter name="emsPropLocation"
value="/xyz/config/EMSServerConf.properties"
override="false"/>
</Context>
have a try to change the ignoreResourceNotFound property of your propertyConfigurer to true.
If contextParameters.emsPropLocation is not set, this will default to what is afer the colon.
<property name="location" value="file:/#{contextParameters.emsPropLocation:/xyz/config/EMSServerConf.properties}" />

How do I set up custom Mongo formatters in Spring?

I've been at this for a few hours and haven't found anyone that's gotten this working yet. I want to persist a BigDecimal object in Mongo, but Mongo doesn't natively support BigDecimal. I followed Spring's docs here but no luck.
From what I can tell Spring isn't injecting my custom converter classes into Mongo when it's writing to the db. Here's what I have done:
My applicationContext-services.xml
...
<!-- Factory bean that creates the Mongo instance -->
<mongo:mongo
host="localhost"
port="1234" />
<mongo:db-factory
dbname="solar"
mongo-ref="mongo"/>
<mongo:mapping-converter>
<mongo:custom-converters>
<mongo:converter>
<bean class="com.mine.BigDecimalReadConverter"/>
</mongo:converter>
<mongo:converter>
<bean class="com.mine..BigDecimalWriteConverter"/>
</mongo:converter>
</mongo:custom-converters>
</mongo:mapping-converter>
<!-- Use this post processor to translate any MongoExceptions thrown in #Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="mongoDbTest"
class="com.mine.MongoDbTest">
<property name="mongoTemplate">
<ref local="mongoTemplate" />
</property>
</bean>
The error I'm getting is:
java.lang.IllegalArgumentException: Multiple constructors with arguments found in class java.math.BigDecimal! Annotate one with #PreferedConstructor explicitly to select it to be used in persistence operations.
at org.springframework.data.mapping.PreferredConstructorDiscoverer.<init>(PreferredConstructorDiscoverer.java:81)
Try using this for converter support:
<bean id="mappingContext"
class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" lazy-init="true"/>
<bean id="defaultMongoTypeMapper"
class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper" lazy-init="true">
<constructor-arg name="typeKey"><null/></constructor-arg>
</bean>
<bean id="mappingMongoConverter"
class="org.springframework.data.mongodb.core.convert.MappingMongoConverter" lazy-init="true" >
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mappingContext" ref="mappingContext" />
<property name="typeMapper" ref="defaultMongoTypeMapper" />
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate" lazy-init="true">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
</bean>
Here is how I solved this. The order in which you define the beans matters. So my app.xml that I got it working with is:
<bean id="mappingContext" class="org.springframework.data.document.mongodb.mapping.MongoMappingContext"/>
<bean id="readConverter" class="com.mine.BigDecimalReadConverter"/>
<bean id="writeConverter" class="com.mine.BigDecimalWriteConverter"/>
<mongo:mapping-converter id="mappingConverter">
<mongo:custom-converters>
<mongo:converter ref="readConverter" />
<mongo:converter ref="writeConverter" />
</mongo:custom-converters>
</mongo:mapping-converter>
<!-- Factory bean that creates the Mongo instance -->
<mongo:mongo
host="${${environment}.mongodb.host}"
port="${${environment}.mongodb.port}" />
<mongo:db-factory
dbname="${${environment}.mongodb.databaseName}"
mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mongoConverter" ref="mappingConverter"/>
</bean>
<!-- Use this post processor to translate any MongoExceptions thrown in #Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

Resources