I need to run a test for my spring batch that reads from mongodb - mongodb

I am new to testing. I have a completed Spring Batch job using mongodb and gradle. I need some help getting started with either a junit test or integration test to ensure my project is working correctly. I have searched through Stack and did not find anything that can help me understand what I am doing. A lot of the codes online does not pertain to my spring batch. Could someone help guide me to fully understand what I need to do to get started or point me in the right direction.
Thank you
here is a code i found, does not work, is there another way I can make this run?
#RunWith(SpringRunner.class)
#Configuration
#ComponentScan(basePackages = { "com." })
public class BatchTest {
#Autowired
private PaymentPortalRepository repository;
#Autowired
private MongoTemplate mongoTemplate;
#Test
public void testSaveAndFindRxBusiness() throws Exception {
PaymentAudit paymentAudit = new PaymentAudit(null, "1", false,
"RETAIL", null, null, 0, 0, 0, null, null, null, null, null, null, null,
null, null, null, null, 0, null, 0, null, null);
repository.save(paymentAudit);
PaymentAudit paymentAudit2 = new PaymentAudit(null, "2", false,
"RETAIL", null, null, 0, 0, 0, null, null, null, null, null, null, null,
null,
null, null, null, 0, null, 0, null, null);
repository.save(paymentAudit2);
assertEquals(paymentAudit, repository.findByRxBusiness("1"));
assertEquals(paymentAudit2, repository.findByRxBusiness("2"));
assertNull(repository.findByRxBusiness("3"));
}
}
ERROR:
14:53:20.862 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#60db1c0e] to prepare test instance [com..ecom.BatchTest#e25951c]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com..ecom.BatchTest': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com..ecom.spring_batchjob.repository.PaymentPortalRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:399)
at
org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.ecom.spring_batchjob.repository.PaymentPortalRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1509)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
... 28 common frames omitted
14:53:20.871 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test class: context [DefaultTestContext#81d9a72 testClass = BatchTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration#747f281 testClass = BatchTest, locations = '{}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer#0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer#10feca44, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer#1e683a3e, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer#14555e0a, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer#0], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]], attributes = map[[empty]]], class annotated with #DirtiesContext [false] with mode [null].
14:53:20.874 [Thread-0] INFO org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext#4f4c4b1a: startup date [Tue Jan 08 14:53:20 CST 2019]; root of context hierarchy
14:53:20.874 [Thread-0] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
14:53:20.876 [Thread-0] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#1ab06251: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,org.springframework.boot.test.mock.mockito.MockitoPostProcessor$SpyPostProcessor,org.springframework.boot.test.mock.mockito.Moc
kitoPostProcessor]; root of factory hierarchy

You are autowiring a bean of type PaymentPortalRepository in your test class but no beans of this type are found in your test context. Hence the error.
The problem is that your test class does not load any Spring application context. You need to add #ContextConfiguration and specify which Spring application context you want to load for this test (use the classes attribute if you use Java configuration and locations attribute if you use XML configuration). This application context should contain a bean of type PaymentPortalRepository and other beans used in your test.
Moreover, the #Configuration annotation means the annotated class is a source of bean definitions. This is not the case in your test so you can remove it.
You can find examples of how to test Spring Batch jobs here: https://docs.spring.io/spring-batch/4.1.x/reference/html/testing.html#endToEndTesting

Related

problem with postgresql sequence and hibernate

I often read this site, but this is the first time I write, hope I won't make mistakes and apologize for my bad english.
I get to the point: I have to develop code to insert records on a single table of a postgresql db, using hibernate on a Springboot project. The table has got a sequence, and I would like to use it to get the id's value.
Into the hbm.xml file of my table I have this:
table="td_tito">
<id name="idTito" column="ID_TITO">
<generator class="sequence">
<param name="sequence">seq_td_tito</param>
</generator>
</id>
<property ..../>
<property ..../>
In the bean class I have the variable idTito and its getter and setter methods.
When i try to save by calling save method of my class that implements JpaRepository interface, I get the following exception:
12:56:06.746 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
12:56:06.747 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - begin
12:56:06.756 [main] DEBUG org.hibernate.SQL - select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
12:56:06.782 [main] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper - could not extract ResultSet [n/a]
org.postgresql.util.PSQLException: ERROR: relation "hibernate_sequence" does not exist
Position: 17
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2510)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2245)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:311)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:447)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:368)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:159)
at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:109)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57)
at org.hibernate.id.enhanced.SequenceStructure$1.getNextValue(SequenceStructure.java:95)
at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40)
at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:523)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:115)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:194)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:38)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:179)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:32)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:75)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:626)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:619)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:614)
at com.xxx.hibernate.TestHIbernate.saveTdtito(TestHIbernate.java:122)
at com.xxx.hibernate.TestHIbernate.main(TestHIbernate.java:20)
12:56:06.782 [main] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42P01
12:56:06.782 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: relation "hibernate_sequence" does not exist
Position: 17
This is the Entity Class:
#Entity
public class TdTito {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long idTito;
private int lev;
...
public Long getIdTito() {
return idTito;
}
public void setIdTito(Long idTito) {
this.idTito = idTito;
}
public int getLev() {
return lev;
}
public void setLev(int lev) {
this.lev = lev;
}
}
By removing the annotations I get this error as I try to start the Application:
2020-06-16 15:26:46.394 ERROR 23244 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.xxx..entities.mappingdb.TdTito
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108) ~[spring-context-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at com.xxx..Application.main(Application.java:14) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_241]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_241]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_241]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_241]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.2.5.RELEASE.jar:2.2.5.RELEASE]
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: com.xxx..entities.mappingdb.TdTito
at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:266) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:211) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:781) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1202) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1233) ~[hibernate-core-5.4.12.Final.jar:5.4.12.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) ~[spring-orm-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
... 21 common frames omitted
Any suggestion? Thank you so much to everybody
Step
If you are using you must remove all annotations from the entity
This line is causing the search for hibernate_sequence:
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Simply remove this line.
But I recommend to use use annotations. This will look like this:
#Id
#SequenceGenerator(name = "seq_td_tito", sequenceName = "seq_td_tito")
#GeneratedValue(generator = "seq_td_tito", strategy = GenerationType.SEQUENCE)
private Long idTito;
I struggled for sometime, then following combination worked, for the same strategy
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
my application.properties has these entries.
spring.datasource.username= postgres
spring.datasource.password= mypassword
spring.datasource.driver-class-name= org.postgresql.Driver
spring.jpa.generate-ddl= true
spring.jpa.hibernate.ddl-auto= update
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect
and pom.xml has one dependency as needed.
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

Unsatisfied dependency Exception

I have a spring boot application where I need to store image into a local folder and its details like id,name and path in db.I done this with no problem. Now I want to edit the name in the folder as well as in db. I succeeded in renaming the file in the folder and i want to rename in db as well. I have written code for this but i got error like unsatisfied dependency. In my controller
#PutMapping("/updateFile")
public String updateFile(#RequestParam String oldFileName,#RequestParam String newFileName,#RequestParam UUID imageId,#RequestParam ImageModel imageModel) throws IOException {
// UUID Id=UUID.fromString(imageId);
imgserv.updateImageData(imageId, imageModel);
return fileStorageService.updateFile(oldFileName, newFileName);
}
and in service implementation
#Override
public String updateImageData(UUID imageId, ImageModel imageModel) {
ImageModel imageData = imageRepo.findImageById(imageId);
if (imageId == null) {
return "Image Data Not Found";
}
imageData.setImageName(imageModel.getImageName());
imageRepo.save(imageData);
return "Image Details Updated Successfully!";
}
and my Repository class
#Repository("imageRepo")
public interface ImageRepo extends MongoRepository<ImageModel, UUID> {
ImageModel findImageById(UUID imageId);
}
and my error code is like
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fileController': Unsatisfied dependency expressed through field 'imgserv'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'imgserv': Unsatisfied dependency expressed through field 'imageRepo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'imageRepo': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property id found for type ImageModel!
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at

Controller Test fails with MethodArgumentConversionNotSupportedException but not in the running application

Spring Boot App using 2.0.3.RELEASE of Spring Boot.
So I have REST API controller written like this:
#RestController
#RequestMapping("/root/{id}")
#Slf4j
public class RootController {
#GetMapping
public ResponseEntity<?> getXXX(
#PathVariable String id,
#RequestParam(value = "status") Status status,
#RequestParam(value = "comment") String comment,
#RequestParam(value = "other") Optional<String> other) {
log.info("Requested getXXX id={} status={} other={} comment={}", id, status, other, comment);
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}
So the interesting part is the Optional<String> other on the above definition. I have tested the above manually via calling curl:
curl -v -X GET 'http://localhost:8080/root/ID?status=OK&comment=Comment'
which results in logging output on console like this:
...Requested getXXX id=ID status=OK other=Optional.empty comment=Comment
and using curl like this:
curl -v -X GET 'http://localhost:8080/root/ID?status=OK&comment=Comment&other=MoreOther'
which results in the following output:
Requested getXXX id=ID status=OK other=Optional[MoreOther] comment=Comment
So far so good.
But of course I would like to check this via unit tests and not manually...So I wrote a REST controller test which looks like this:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = RootController.class)
#AutoConfigureMockMvc
public class RootControllerTest {
#Autowired
private MockMvc mvc;
#Test
public void shouldReturnNotImplemented() throws Exception {
//#formatter:off
mvc.perform(
get("/root/xyz?status={status}&comment={comment}&other={other}", Status.NOTOK, "COMMENT", Optional.<String>of("Other"))
.characterEncoding("UTF-8")
.accept(MediaType.ALL)
)
.andExpect(
status().isNotImplemented()
);
//#formatter:on
}
But unfortunately the above test fails with:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /root/xyz
Parameters = {status=[OK], comment=[Comment], other=[Optional[Other]]}
Headers = {Accept=[*/*]}
Body = null
Session Attrs = {}
Handler:
Type = ...RootController
Method = public org.springframework.http.ResponseEntity<?> .getRoot(java.lang.String,Status,java.lang.String,java.util.Optional<java.lang.String>)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 500
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Where the exception: org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException is the thing I don't understand.
The final question is: Why does the test fail but the running application does not? Does someone has a hint / idea for me?
Update 1:
I have tested also the following:
get("/root/xyz?status={status}&comment={comment}&other={other}", Status.NOTOK, "COMMENT", "Other")
and furthermore which means using only strings.
get("/root/xyz?status={status}&comment={comment}&other={other}", "NOTOK", "COMMENT", "Other")
The point that the running application works perfectly but unfortunately the test do not.
Update 2:
So after turning on debugging mode in test I got the following output: This brings me more and more into the direction that there is a bug within it..cause the parameters are always converted into String instead of Optional...and based on the parameters of get(..., Object... uriVars)
it looks like there is some problem in the code...
2018-07-16 15:50:21.029 DEBUG 16022 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /root/xyz
2018-07-16 15:50:21.031 DEBUG 16022 --- [main] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<?> de....RootController.getXXX(java.lang.String,de....Status,java.lang.String,java.util.Optional<java.lang.String>)]
2018-07-16 15:50:21.057 DEBUG 16022 --- [main] .w.s.m.m.a.ServletInvocableHandlerMethod : Failed to resolve argument 3 of type 'java.util.Optional'
org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Optional'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Optional': no matching editors or conversion strategy found
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:127)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:124)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:131)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:165)
at de...RootControllerTest.shouldReturnNotImplemented(RootControllerTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Optional': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:299)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:99)
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:73)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:52)
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:692)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:123)
... 50 common frames omitted
This is an issue with how you are loading the test up.
When you specify #SpringBootTest(classes = RootController.class) a class with SpringBootTest it will only load that class into the context i.e. it allows you to specify certain configurations etc. that you would want to test for some integration tests rather than using ContextConfiguration.
You can either remove the RootController and load a full test application context, effectively loading your entire application.
or just specify,
#RunWith(SpringRunner.class)
#WebMvcTest
public class RootControllerTest {
To load a slice test, which will only load the required beans to completely test the WebMVC.
working tests,
https://github.com/Flaw101/mockmvctests
Edit,
I've updated my example and introduced a second controller but only load the RootController in the RootControllerMock via #WebMvcTest(controllers = RootController.class). You can see in the logged output that it only load this controller.
2018-07-16 15:34:28.264 INFO 6176 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/root/{id}],methods=[GET]}" onto public org.springframework.http.ResponseEntity<?> com.darrenforsythe.mockmvc.RootController.getXXX(java.lang.String,java.lang.String,java.lang.String,java.util.Optional<java.lang.String>)
references,
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTest.html
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests

My execution halts while implemented the Data Driven Approach

I have included few lines of code for data driven, where I will fetch the details from a Excel sheet and it will pass to the script in Run Time. Here my script won't execute and it hangs after returning the message in Eclipse Console:
Returning cached instance of singleton bean 'todoClient1'
Below attached the Code and package com.consol.citrus.integration.Demo.
import java.util.Hashtable;
import org.apache.log4j.helpers.SyslogWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.ImportResource;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.testng.SkipException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import com.consol.citrus.TestCaseMetaInfo.Status;
import com.consol.citrus.annotations.CitrusTest;
import com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner;
import com.consol.citrus.http.client.HttpClient;
import com.consol.citrus.message.MessageType;
public class UnSuccessFullLogin extends TestNGCitrusTestDesigner {
#Autowired (required=true)
#Qualifier("todoClient1")
private HttpClient todoClient1;
public Xls_Reader xls=new Xls_Reader(Constants.DATA_XLS_PATH);
String testCaseName="UnSuccessFullLogin";
public String actualResult="";
#CitrusTest
#Test(dataProvider="getData")
public void TestPost(Hashtable<String, String> data) {
echo("i am entered");
variable("Uname", "admin2");
variable("Pwd", "admin");
if(!DataUtil.isTestExecutable(xls, testCaseName) || data.get(Constants.RUNMODE_COL).equals("N")){
throw new SkipException("Skipping the test as Rnumode is N");
}
http()
.client(todoClient1)
.send()
.post("/rest/api/user/login")
.contentType("application/json")
// .payload("{ \"userName\": \"${uN}\", \"password\": \"${pwd}\"}");
.payload("{ \"userName\": \"${Uname}\", \"password\": \"${Pwd}\"}");
http()
.client(todoClient1)
.receive()
.response(HttpStatus.ACCEPTED)
.validate("$.statusCode", "400");
}
#DataProvider
public Object[][] getData()
{
return DataUtil.getData(xls, testCaseName);
}
}
Log Here:
17:37:56,650 DEBUG tListableBeanFactory| Creating shared instance of singleton bean 'todoClient'
17:37:56,650 DEBUG tListableBeanFactory| Creating instance of bean 'todoClient'
17:37:56,651 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'todoClientConfiguration'
17:37:56,675 DEBUG tListableBeanFactory| Eagerly caching bean 'todoClient' to allow for resolving potential circular references
17:37:56,690 DEBUG tListableBeanFactory| Finished creating instance of bean 'todoClient'
17:37:56,690 DEBUG tListableBeanFactory| Creating shared instance of singleton bean 'todoClient1Configuration'
17:37:56,690 DEBUG tListableBeanFactory| Creating instance of bean 'todoClient1Configuration'
17:37:56,691 DEBUG tListableBeanFactory| Eagerly caching bean 'todoClient1Configuration' to allow for resolving potential circular references
17:37:56,697 DEBUG tListableBeanFactory| Finished creating instance of bean 'todoClient1Configuration'
17:37:56,697 DEBUG tListableBeanFactory| Creating shared instance of singleton bean 'todoClient1'
17:37:56,697 DEBUG tListableBeanFactory| Creating instance of bean 'todoClient1'
17:37:56,697 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'todoClient1Configuration'
17:37:56,699 DEBUG tListableBeanFactory| Eagerly caching bean 'todoClient1' to allow for resolving potential circular references
17:37:56,699 DEBUG tListableBeanFactory| Finished creating instance of bean 'todoClient1'
17:37:56,699 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'globalVariables'
17:37:56,699 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'com.consol.citrus.report.MessageTracingTestListener#1'
17:37:56,700 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
17:37:56,851 DEBUG icApplicationContext| Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor#655a5d9c]
17:37:56,852 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'lifecycleProcessor'
17:37:56,856 DEBUG rcesPropertyResolver| Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
17:37:56,866 DEBUG ontextLoaderDelegate| Storing ApplicationContext in cache under key [[MergedContextConfiguration#7bd7d6d6 testClass = UnSuccessFullLogin, locations = '{}', classes = '{class com.consol.citrus.config.CitrusSpringConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]
17:37:56,866 DEBUG context.cache| Spring test ApplicationContext cache statistics: [DefaultContextCache#1a6f2363 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 0, missCount = 1]
17:37:56,939 DEBUG on.InjectionMetadata| Processing injected element of bean 'com.consol.citrus.integration.Demo.UnSuccessFullLogin': AutowiredFieldElement for private com.consol.citrus.http.client.HttpClient com.consol.citrus.integration.Demo.UnSuccessFullLogin.todoClient1
17:37:56,942 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'todoClient1'
17:37:56,942 DEBUG ionBeanPostProcessor| Autowiring by type from bean name 'com.consol.citrus.integration.Demo.UnSuccessFullLogin' to bean named 'todoClient1'
17:37:56,947 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'testSuiteListeners'
17:37:56,947 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'testContextFactory'
5876 [main] INFO com.consol.citrus.Citrus -
5876 [main] INFO com.consol.citrus.Citrus - ------------------------------------------------------------------------
5876 [main] INFO com.consol.citrus.Citrus - .__ __
5876 [main] INFO com.consol.citrus.Citrus - ____ |__|/ |________ __ __ ______
5876 [main] INFO com.consol.citrus.Citrus - _/ ___\| \ __\_ __ \ | \/ ___/
5876 [main] INFO com.consol.citrus.Citrus - \ \___| || | | | \/ | /\___ \
5876 [main] INFO com.consol.citrus.Citrus - \___ >__||__| |__| |____//____ >
5876 [main] INFO com.consol.citrus.Citrus - \/ \/
5876 [main] INFO com.consol.citrus.Citrus -
5876 [main] INFO com.consol.citrus.Citrus - C I T R U S T E S T S 2.7.2
5876 [main] INFO com.consol.citrus.Citrus -
5876 [main] INFO com.consol.citrus.Citrus - ------------------------------------------------------------------------
5876 [main] INFO com.consol.citrus.Citrus -
5876 [main] INFO com.consol.citrus.Citrus -
5876 [main] INFO com.consol.citrus.Citrus - BEFORE TEST SUITE: SUCCESS
5876 [main] INFO com.consol.citrus.Citrus - ------------------------------------------------------------------------
5876 [main] INFO com.consol.citrus.Citrus -
17:37:56,974 DEBUG estExecutionListener| Before test class: context [DefaultTestContext#740fb309 testClass = UnSuccessFullLogin, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration#7bd7d6d6 testClass = UnSuccessFullLogin, locations = '{}', classes = '{class com.consol.citrus.config.CitrusSpringConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class annotated with #DirtiesContext [false] with mode [null].
17:37:56,975 DEBUG estExecutionListener| Performing dependency injection for test context [[DefaultTestContext#740fb309 testClass = UnSuccessFullLogin, testInstance = com.consol.citrus.integration.Demo.UnSuccessFullLogin#5524cca1, testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration#7bd7d6d6 testClass = UnSuccessFullLogin, locations = '{}', classes = '{class com.consol.citrus.config.CitrusSpringConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]].
17:37:56,975 DEBUG ontextLoaderDelegate| Retrieved ApplicationContext from cache with key [[MergedContextConfiguration#7bd7d6d6 testClass = UnSuccessFullLogin, locations = '{}', classes = '{class com.consol.citrus.config.CitrusSpringConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]
17:37:56,975 DEBUG context.cache| Spring test ApplicationContext cache statistics: [DefaultContextCache#1a6f2363 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 1, missCount = 1]
17:37:56,976 DEBUG on.InjectionMetadata| Processing injected element of bean 'com.consol.citrus.integration.Demo.UnSuccessFullLogin': AutowiredFieldElement for private com.consol.citrus.http.client.HttpClient com.consol.citrus.integration.Demo.UnSuccessFullLogin.todoClient1
17:37:56,976 DEBUG tListableBeanFactory| Returning cached instance of singleton bean 'todoClient1'
Please see the following working sample how to use TestNG data provider with Citrus:
public class DataProviderJavaIT extends TestNGCitrusTestDesigner {
#CitrusTest
#CitrusParameters( {"message", "delay"} )
#Test(dataProvider = "sampleDataProvider")
public void dataProvider(String message, Long sleep) {
echo(message);
sleep(sleep);
echo("${message}");
echo("${delay}");
}
#DataProvider
public Object[][] sampleDataProvider() {
return new Object[][] {
{ "Hello World!", 300L },
{ "Hallo Welt!", 1000L },
{ "Hallo Citrus!", 500L },
};
}
}
According to the sample you are missing the #CitrusParameters annotation that translates data provider arguments to Citrus test variables.

NullPointerException from Jboss LdapExtLoginModule

I am attempting to configure Ldap authentication for a Jboss web-app. Jboss loads my module, but does not authenticate credentials that are known to be good. I should point out that my module just extends LdapExtLoginModule without adding any logic. I get the same error when defering directly to LdapExtLoginModule. The error:
PBOX000070: Password invalid/Password required
is returned when I attempt to login. I tracked the error down to a null pointer being thrown by a hashtable.put() operation in org.jboss.security.auth.spi.LdapExtLoginModule.constructInitialLdapContext. Here is the stack trace:
javax.security.auth.login.FailedLoginException: PBOX000070: Password invalid/Password required
at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:284)
at com.alstom.auth.login.ldap.CustomLdapLoginModule.login(CustomLdapLoginModule.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:762)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:690)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:687)
at javax.security.auth.login.LoginContext.login(LoginContext.java:595)
at org.springframework.security.authentication.jaas.AbstractJaasAuthenticationProvider.authenticate(AbstractJaasAuthenticationProvider.java:149)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at com.etse.security.SecureMethodAuthenticationManager.authenticate(SecureMethodAuthenticationManager.java:29)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149)
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:336)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:920)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:514)
at org.jboss.security.auth.spi.LdapExtLoginModule.constructInitialLdapContext(LdapExtLoginModule.java:742)
at org.jboss.security.auth.spi.LdapExtLoginModule.createLdapInitContext(LdapExtLoginModule.java:463)
at org.jboss.security.auth.spi.LdapExtLoginModule.validatePassword(LdapExtLoginModule.java:340)
at com.alstom.auth.login.ldap.CustomLdapLoginModule.validatePassword(CustomLdapLoginModule.java:152)
at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:281)
... 40 more
The function:
private InitialLdapContext constructInitialLdapContext(String dn, Object credential) throws NamingException
{
String protocol = (String)options.get(Context.SECURITY_PROTOCOL);
String providerURL = (String) options.get(Context.PROVIDER_URL);
if (providerURL == null)
providerURL = "ldap://localhost:" + ((protocol != null && protocol.equals("ssl")) ? "636" : "389");
Properties env = constructLdapContextEnvironment(providerURL, dn, credential);
return new InitialLdapContext(env, null);
}
No hashtable.put() operations there so it must come from the InitialLdapContext constructor right?
public InitialLdapContext(Hashtable<?,?> environment,Control[] connCtls) throws NamingException {
super(true); // don't initialize yet
// Clone environment since caller owns it.
Hashtable env = (environment == null)
? new Hashtable(11)
: (Hashtable)environment.clone();
// Put connect controls into environment. Copy them first since
// caller owns the array.
if (connCtls != null) {
Control[] copy = new Control[connCtls.length];
System.arraycopy(connCtls, 0, copy, 0, connCtls.length);
env.put(BIND_CONTROLS_PROPERTY, copy);
}
// set version to LDAPv3
env.put("java.naming.ldap.version", "3");
// Initialize with updated environment
init(env);
}
connCtls is null (see constructor call) so the only put operation is env.put("java.naming.ldap.version", "3") which is obviously fine.
Any idea what's going on here? Thanks.
HashTable does not allow keys to be null. Verify that none of the keys you put into Hashtable env is not null. For example, for
env.put(BIND_CONTROLS_PROPERTY, copy);
BIND_CONTROLS_PROPERTY must not be null.
Hope that helps
IMO, You have a code from another version of the LdapExtLoginModule. The correct one could be this one on GitHub.
The code there is:
private InitialLdapContext constructInitialLdapContext(String dn, Object credential) throws NamingException
{
Properties env = new Properties();
Iterator iter = options.entrySet().iterator();
while (iter.hasNext())
{
Entry entry = (Entry) iter.next();
env.put(entry.getKey(), entry.getValue()); /* this is the line 742 */
}
So there seems to be a login module option with null value. Try to check your configuration.
Please, share more details about your environment next time. It will help a lot to evaluate your problem. The most important details:
application server version
used server configuration (i.e. configuration of the security domain in this case)

Categories