mongo: repositories no longer works - spring

I'm having this configuration
<?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"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<mongo:repositories base-package="com.x.record.persistence.repo"
mongo-template-ref="mongoTemplate" />
<context:component-scan base-package="com.x.record.persistence.impl" />
</beans>
where in the package com.x.record.persistence.impl I have a component that needs the repository from com.x.record.persistence.repo.
This is working for spring-data-mongodb version 1.5.2.RELEASE
If I upgrade to the any version greater than 1.6.0.RELEASE (I tried with 1.6.2 and 1.7.0) this no longer works.
It is as if the mongo repository scan does not work and I get the error:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'noAuthRecordPersistenceService': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.x.record.persistence.repo.RecordRepository com.x.record.persistence.impl.NoAuthRecordPersistenceServiceImpl.repo;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.x.record.persistence.repo.RecordRepository] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Any ideas?
UPDATE:
If I use MongoRepository instead of PagingAndSortingRepository it works:
THIS DOES NOT WORK (with 1.6.x and up):
public interface RecordRepository extends PagingAndSortingRepository, RecordRepositoryCustom {
Page<Record> findByOrgHierarchy( String orgId, Pageable pageable );
Record findOneByIdAndOrgHierarchyIn( String id, Collection<String> orgIds );
int countByGsRunId(String gsRunId);
}
THIS WORKS (with 1.6.x and up):
public interface RecordRepository extends MongoRepository, RecordRepositoryCustom {
Page<Record> findByOrgHierarchy( String orgId, Pageable pageable );
Record findOneByIdAndOrgHierarchyIn( String id, Collection<String> orgIds );
int countByGsRunId(String gsRunId);
}
The wirdest thing is that I have other repos that DO WORK with PagingAndSortingRepository

Try sample here, if this works in latest version then its possible that some component of yours is still using a older version and an incompatible state might exists.
Paste your complete code so that community can test the issue.

Related

spring-boot cloud stream with Kafka as a stand alone library

I'm trying to integrate a library based on spring-boot cloud stream with Kafka within non-spring application.
When this library is loaded within another Spring application everything works.
When I try to initialize application context with Non-spring boot enabled application and get my bean I get the following warnings and exception:
org.springframework.core.LocalVariableTableParameterNameDiscoverer - Cannot find '.class' file for class [class com.acme.common.library.spring.service.InstrumentIdLookupServiceImpl$$EnhancerBySpringCGLIB$$59e4e4ac] - unable to determine constructor/method parameter names
org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'instrumentIdLookupServiceImpl' via constructor to bean named 'instrumentIdLookupServiceProperties'
WARN org.springframework.context.support.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.acme.common.library.spring.InstrumentIdBinding': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No factory found for binding target type: org.apache.kafka.streams.kstream.KStream among registered factories: channelFactory,messageSourceFactory
No factory found for binding target type: org.apache.kafka.streams.kstream.KStream among registered factories: channelFactory,messageSourceFactory
public interface InstrumentIdBinding {
String INSTRUMENT_IDS = "instrument-ids";
#Input(INSTRUMENT_IDS)
KStream<String, InstrumentIdMsg> processInstrumentId();
}
<?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:component-scan base-package="com.acme.common.library.spring"/>
</beans>
GenericApplicationContext ctx = new GenericApplicationContext();
final XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new FileSystemResource("applicationContext-ext.xml"));
ctx.refresh();
InstrumentIdLookupService bean = ctx.getBean(InstrumentIdLookupService.class);
Spring Cloud Stream requires Spring Boot.

Exception Autowiring Service interface in controller class

I and trying to autowire a service interface in the controller but i am getting an error, please help. Codes below :
Exception
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'todoComponentController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.rapidinstinct.avia.plat.service.component.TodoCS com.rapidinstinct.avia.plat.service.rest.controller.TodoComponentController.tocs; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.rapidinstinct.avia.plat.service.component.TodoCS] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Controller class
#RestController
#RequestMapping ("/todo")
public class TodoComponentController extends BaseController {
private static Logger _LOG = LoggerFactory.getLogger(TodoComponentController.class);
#Autowired TodoCS tocs;
#RequestMapping(method = RequestMethod.POST)
public create() {
return null;
}
}
Service Interface
#Service
public interface TodoCS extends ComponentService {
}
XML file
<?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:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
>
<context:annotation-config />
<context:component-scan base-package="com.rapidinstinct.avia.plat.service, com.rapidinstinct.avia.plat.cbo.mapper, com.rapidinstinct.avia.plat.bo.project.mapper"/>
</beans>
You have to annotate the implementation of TodoCS Not the interface itself.
#Service
public class TodoCSImpl implements TodoCS {
}
Then you can autowire the class.
You need a class which implements TodoCS interface. Then, annotation the implementation class with #Component annotation.
Spring, at time of context initialization is trying to search a bean name TodoCS in package : com.rapidinstinct.avia.plat.service.component.TodoCS.
And in configuartion file you mentioned package name as : com.rapidinstinct.avia.plat.service. Try adding com.rapidinstinct.avia.plat.service.component.TodoCS in base package scan as below:
<context:component-scan base-package="com.rapidinstinct.avia.plat.service, com.rapidinstinct.avia.plat.cbo.mapper, com.rapidinstinct.avia.plat.bo.project.mapper,com.rapidinstinct.avia.plat.service.component"/>

Junit Test failing due to Parent applicationContext bean

My test case is failing with the below error :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'acesFormFactory' defined in class path resource [/META-INF/aces-beans.xml]: Cannot resolve reference to bean 'promotionMarshaller' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'promotionMarshaller' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:629)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:148)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1049)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
Now here is my Test Class :
#WebAppConfiguration
#ContextConfiguration(locations = {
"classpath:/META-INF/aces-beans.xml",
"classpath:/META-INF/aces-flow-config.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class })
public class ApplicationContextTest {
#Resource
private AcesFormFactory acesFormFactory;
#Test
public void paymentFormFactoryAvailable() {
assertThat(acesFormFactory, is(notNullValue()));
assertThat(acesFormFactory, is(instanceOf(AcesFormFactoryImpl.class)));
}
}
Here promotionMarshaller in injected in acesFormFactory as a constructor arg in aces-beans.xml. And the definition of promotionMarshaller is there in ApplicationContext.xml of webapp-control which is there in the dependency list of pom.xml of the current component.
<dependency>
<groupId>webapp</groupId>
<artifactId>webapp-control</artifactId>
</dependency>
<dependency>
<groupId>webapp</groupId>
<artifactId>webapp-control</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
I don't get why the parent application context is not getting loaded while running the Junit Test case. Please look into this as I am stuck here for 2 days now.
Here's a snippet from aces-beans.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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean id="acesFormFactory"
class="com.company.impl.AcesFormFactoryImpl">
<constructor-arg ref="checkoutPromotionMarshaller" />
</bean>
My environment is Spring 3.2.1, Junit 4, JDK 1.7, Maven 3.0.4

Why is this Spring map not injecting into my Scala object?

I'm creating a Spring-based Scala project. One of my objects needs a simple Map[String, String] injected in to it. I have the following code:
applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:device="http://www.springframework.org/schema/mobile/device"
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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/mobile/device http://www.springframework.org/schema/mobile/device/spring-mobile-device-1.0.xsd">
<util:map id="validHosts">
<entry key="host1.domain.com" value="queue-1" />
<entry key="host2.domain.com" value="queue-2" />
</util:map>
</beans>
HostMapper.Scala
import scala.collection.JavaConversions._
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
#Component
class HostMapper() {
#Autowired private var validHosts:java.util.Map[String, String] = null
}
When running this app, I get the following error on startup:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.lang.String] found for dependency [map with value type java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency.
I attempted explicitly declaring the key and value types as java.lang.String, but that had no effect. Any ideas what I might be doing wrong?
I did not know this myself and found this actually:
As a specific consequence of this semantic difference, beans which are themselves defined as a collection or map type cannot be injected via #Autowired since type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection/map bean by unique name
And I tested this and instead of
#Autowired
I used:
#Resource
private Map<String, String> validHosts;
<util:map id="validHosts" key-type="java.lang.String" value-type="java.lang.String">
<entry key="host1.domain.com" value="queue-1" />
<entry key="host2.domain.com" value="queue-2" />
</util:map>
And it worked.

Spring component detection without xml bean definitions

Is it correct that one can create spring beans using just the #Component annotation as long as context component scanning is configured?
Using spring 3.0.5 with Java 6.
My test case is:
#ContextConfiguration(locations={"classpath:spring-bean.xml"})
public class ServerServiceUnitTest extends AbstractJUnit4SpringContextTests {
#Autowired
private ServerService serverService;
#Test
public void test_server_service() throws Exception {
serverService.doSomething();
//additional test code here
}
}
The spring-bean.xml file contains:
<?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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
My class I want to be a bean is:
#Component("ServerService")
public class ServerServiceImpl implements ServerService {
private static final String SERVER_NAME = "test.nowhere.com";
//method definitions.....'
}
Should that not be sufficient for spring to instantiate the ServerService bean and do the autowiring?
The error I get is:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [serversystem.ServerService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I'm sure I'm missing something simple.
You have not defined in your spring-beans.xml the <context:component-scan> element:
<context:component-scan base-package="the.package.with.your.service"/>
The inclusion of
<context:annotation-config/>
only allows you to use #Required, #Autowired, and #Inject annotations for configuration. By specifying the <context:component-scan>, you are telling Spring where to look for #Component annotations.
if you are using annotated controllers and other features
you should include
<mvc:annotation-driven/>
you should use
<context:component-scan base-package="spring3.example.controllers"/>
to specify the package in which controller classes are stored.

Resources