How to autowire service with implicit ExecutionContext argument - java

In a Scala project I work on we have an API that early on imports a global execution context like this
import scala.concurrent.ExecutionContext.Implicits.global
I later create a UserStorageService that requires said execution context. I'm attempting to introduce Spring Annotations into my application, but I'm getting stuck on how to handle the execution context. How do I autowire an implicit variable? I've tried this
class UserStorageService(
#Qualifier("userdb") val databaseConnector: DatabaseConnector
)(implicit executionContext: ExecutionContext) extends UserStorageTable {
that I'm trying to get as
private val userStorageService = appContext.getBean(classOf[UserStorageService])
resulting in
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'scala.concurrent.ExecutionContext' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

import this:
import scala.concurrent.ExecutionContext;
import scala.concurrent.ExecutionContext$;
and in your configuration(#Configuration) add this
#Bean
public ExecutionContext getExecutionContext() {
return ExecutionContext$.MODULE$.global();
}
And ExecutionContext bean will be added to the Spring context.

Related

Bean is no longer being autowired after Spring 5.3 Upgrade

I upgraded my package from Spring 4.3 to Spring 5.3 which has caused a issue I am completely to solve, for some reason a Bean that is created and works under 4.3 is being created, but not wired in. The bean is being created, and the configuration has not changed, yet it doesn't work?
Bean Creation:
#Configuration
#SuppressWarnings("checkstyle:HideUtilityClassConstructor")
#Slf4j
public class EnvironmentConfig {
#Bean
public static AppEnvironmentHelper environmentHelper() throws IOException {
final AppEnvironmentHelper.Config config = new AppConfigEnvironmentHelper.Confg()
// Config object is configured
return new AppEnvironmentHelper(config);
}
}
Attempted Injection of Bean:
#Configuration
#Slf4j
public class OtherConfig {
#Value("${role}")
private String someRole;
#Value("${port}")
private String somePort;
#Autowired
private EnvironmentHelper environmentHelper;
.......
}
The class path for the bean is in the configuration, and when launching the service I see logs that indicate that EnviromentConfig is created before OtherConfig
org.springframework.beans.factory.support.DefaultListableBeanFactory: Finished creating instance of bean 'environmentHelper'
But I always get
UnsatisfiedDependencyException: Error creating bean with name 'OtherConfig': Unsatisfied dependency expressed through field 'environmentHelper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.amazon.coral.spring.EnvironmentHelper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
After it errors spring goes to clean up the beans with
Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#40db2a24: defining beans [.....,EnvironmentConfig, environmentHelper ]
Which seems to indicate to me that it is finding the bean, its creating the bean, but then when it comes to wire in enviromentHelper it doesnt find it. Ive tried naming the bean using qualifiers but that did nothing. And I wrapped the EnviromentHelper and added logs during creation of the bean and destruction, so I know the bean isnt being destroyed prematurely. Im not certain what else to try to troubleshoot further.

How to add a protected configuration with access to properties to a Spring Boot Test context?

i use JUnit 5 with Spring Boot 2.5.2 . Now i want to write a Unit test, that does not load the full Application context.
Therefore i annotate my test like that:
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {ConfigurationA.class})
class Test1{
...
}
In ConfigurationA the Bean1 gets created.
The Problem is that the ConfigurationA accesses an ConfigurationB for creating Bean1, but ConfigurationB is protected.
Now i get the following Error:
Error creating bean with name 'Bean1' defined in com.package.sample.config.ConfigurationA: Unsatisfied dependency expressed through method 'createBean1' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.package.sample.config.ConfigurationB available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
When i change #ContextConfiguration... to #SpringBootTest it works but the whole Context gets loaded.
Is there any solution to load not the whole context?
Just make ConfigurationA extend ConfigurationB

Spring autowiring list of components

I have an interface:
public interface IExternalCommandExecutor {
String[] getCommandNames();
void process(String command) throws FailedOperationException;
}
And two implementations(second is similar):
#Service
public class ExecutorImpl implements IExternalCommandExecutor {
//some code...
}
And service, in which I'm using #Autowired annotation on the list of IExternalCommandExecutor:
#Service
public class ExternalCommandsService {
#Autowired
List<IExternalCommandExecutor> commandExecutors;
// other code
}
When I'm trying to run this, I'm getting this error:
NoSuchBeanDefinitionException: No qualifying bean of type
'java.util.List<com.mpcomp.entity.system.IExternalCommandExecutor>' available:
expected at least 1 bean which qualifies as autowire candidate
Which is weird behavior for Spring. As it was mentioned in this article and in the javadoc, Spring should try to autowire all elements of IExternalCommandExecutor instead of trying to find bean of type java.util.List.
If I would change List<IExternalCommandExecutor> to IExternalCommandExecutor[], error is quite similar:
NoSuchBeanDefinitionException: No qualifying bean of type
'com.mpcomp.entity.system.IExternalCommandExecutor[]' available:
expected at least 1 bean which qualifies as autowire candidate
I'm using Spring of version 4.3.8 RELEASE. Any help will be appreciated!
Edit
Interface and service are in the core module, and implementations of interface are in 'children' module which is depends on core module. When I moved service to this 'children' module, everything works fine!

Bamboo ProcessService bean does not exist?

Following https://developer.atlassian.com/bamboodev/bamboo-tasks-api/executing-external-processes-using-processservice I would like to invoke some command using ProcessService bean. The injection as described in the link, does not work.
I checked the source of several other plugins at Bitbucket, but each is using the concept as described in the link.
My class:
import com.atlassian.bamboo.process.ProcessService;
public class CheckTask implements TaskType {
private final ProcessService processService;
public CheckTask(#NotNull final ProcessService processService) {
this.processService = processService;
}
However Bamboo does not find the ProcessService bean and fail with following:
(org.springframework.beans.factory.UnsatisfiedDependencyException :
Error creating bean with name 'bamboo.tasks.CheckTask': Unsatisfied
dependency expressed through constructor argument with index 0 of type
[com.atlassian.bamboo.process.ProcessService]: : No qualifying bean of
type [com.atlassian.bamboo.process.ProcessService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations: {}; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [com.atlassian.bamboo.process.ProcessService]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations: {})
Am I missing something ?
Bamboo version: 5.13.0
AMPS version: 6.2.6
The solution in the end was quite simple, no oficial docs discuss the solution though. Hope this helps you a bit.
Finally thanks to this post I made it work: https://answers.atlassian.com/questions/33141765/testcollationservice-not-injected-into-tasktype-constructor-on-sdk-bamboo
import com.atlassian.bamboo.process.ProcessService;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
#Scanned
public class CheckTask implements TaskType {
#ComponentImport
private final ProcessService processService;
public CheckTask(#NotNull final ProcessService processService) {
this.processService = processService;
}
The rest of the project was basicaly default, as generated by atlas-create-bamboo-plugin.
Try to add in your atlassian-plugin.xml next line
<component-import key="processService"
interface="com.atlassian.bamboo.process.ProcessService"/>
That should help you

Spring #Resource Expected at least 1 bean which qualifies as autowire candidate for this dependency

I'm trying to run a web app and I'm having some issues. Basically I have a controller and a process and they both share a queue.
The controller manages the files that are uploaded to the server and it puts them in the queue. In the other side, the process takes the files in the queue and uses them for other things.
I've defined the queue as a LinkedBlockingQueue and the annotation #Resource on both of them, but when I run the app, the following exception appears:
Error creating bean with name 'csvQueueConsumerBean': Injection of resource
dependencies failed; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [java.util.concurrent.LinkedBlockingQueue] found for
dependency: expected at least 1 bean which qualifies as autowire candidate for this
dependency.
The code of both clases is the following:
#RestController
#RequestMapping("/upload")
public class FileUploadControllerW {
#Resource
protected LinkedBlockingQueue<QueueObject> csvQueue;
...
}
#Component
public class CsvQueueConsumerBean{
#Resource
protected LinkedBlockingQueue<QueueObject> csvQueue;
...
}
Just for the record, both classes are not on the same package.
The reason for this is because Spring context cannot wire the Bean called
csvQueueConsumerBean
You will need to initialize its LinkedBlockingQueue dependency in the Spring config file like this:
#Bean
public LinkedBlockingQueue<QueueObject> linkedBlockingQueue(){
LinkedBlockingQueue<QueueObject> blockingQueue = new LinkedBlockingQueue<QueueObject>();
// do what you need here...
return blockingQueue;
}

Categories