Spring Boot Dependency with Spring 3 - spring

I have a Spring 3 dependent project which I am using in my latest spring boot project
I am facing issues with auto wiring
my spring 3 project has a Gateway Interface (IAccountGateway)
I am facing an issue like
Description:<br>
<br>Field iAccountGateway in
com.rvi.service.common.impl.RegistrationService required a bean of type
'com.rvi.jms.gateway.IAccountGateway' that could not be found. <br><br>Action:<br>
Consider defining a bean of type 'com.rvi.jms.gateway.IAccountGateway'
in your configuration.
when I put debug in my spring project I got log something like below
Registered injected element on class <br><br>
[com.rvi.service.common.impl.RegistrationService]:
AutowiredFieldElement for private com.rvi.jms.gateway.IAccountGateway
com.rvi.service.common.impl.RegistrationService.iAccountGateway

Well, if IAccountGateway is an interface, then, you need to implement it and define as a Spring Bean with #Component annotation (there are also other annotations that have similar effect).
IAccountGateway.java
public interface IAccountGateway {
// ..
}
AccountGatewayImpl.java (the IAccountGateway implementation)
import org.springframework.stereotype.Component;
#Component
public class AccountGatewayImpl implements IAccountGateway {
// ..
}
Autowiring the field:
import org.springframework.beans.factory.annotation.Autowired;
public class Clazz {
#Autowired
IAccountGateway iAccountGateway;
// ..
}
See Spring Boot Reference on Spring Beans and Dependency Injection

Related

How to get #Configuration files in Spring to run

I'm writing a micro service using dependency injection, and I have a Java class annotated with #Configuration which creates all my beans. However, my autowired fields are not detecting the beans. How do I get my #Configuration class to run before the application starts?
I tried annotating the classes with the Autowired fields as #ContextConfiguration(classes = Config.class), but this didn't work.
My spring configuration file:
#Configuration
public class Config {
#Bean
public AmazonDynamoDB amazonDynamoDB() {
return ...
}
#Bean
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
return ...
}
}
I expect the Configuration file to be run and the beans injected, but the beans are not being detected.
There's no main method, since I'm writing this in a service which is created using dependency injection in another service. I'm not sure where I'd tell my application to use my Config file.
probably place a #EnableConfigurationProperties( {Config.class}) above your #SpringBootApplication main class.

Bean overriding in Spring context that uses both annotation and xml config

There is a spring project A which is completely annotation based.
I need to override some beans conditionally in project B which is a legacy application using Spring 4.1.3 and uses xml based config.
There is FooConfig which is configuring beans using #ComponentScan. This config is a third party code for me. i.e I do not have access for this
#ComponentScan(basePackages = {"com.foo.bean"})
#Configuration
public class FooConfig {
}
I have created a BarConfig at my end, which imports this FooConfig and overrides some beans based on a condition. This is achieved using #Conditional
#Configuration
#Import(FooConfig.class)
public class BarConfig {
#Bean(name="helloService")
#Conditional(IsSpanishCondition.class)
public HelloService getHelloService() {
return new HelloService() {
#Override
public String getGreeting(String name) {
return "Hola "+name;
}
};
}
}
And I have included BarConfig in my application-context.xml
<context:annotation-config/>
<bean class="com.foo.config.BarConfig"/>
While this approach works flawlessly in Spring 5.1.2.RELEASE, it does not work in Spring 4.1.3.RELEASE
00:14:20.617 [main] INFO org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader - Skipping bean definition for [BeanMethod:name=getHelloService,declaringClass=com.foo.config.BarConfig]: a definition for bean 'helloService' already exists. This top-level bean definition is considered as an override.
Also, I have observed the same issue in Spring 4 in a completely annotation based context as well. i.e. it is not because of xml and annotation config mix but due to the Spring versions used here
Questions
What changed in Spring 5?
Is there any rule of thumb while working with a Spring application that uses both xml and annotation config especially when it comes to overriding the beans?
Also FTR, these are the solutions that worked
1.Overriding the beans using BeanPostProcessor
2.Using profiles. But this wouldn't work for complicated conditions.
#Profile("ENGLISH")
#Configuration
#Import(FooConfig.class)
public class EnglishConfig {
}
#Profile("SPANISH")
#Configuration
public class SpanishConfig {
#Bean(name="helloService")
public HelloService getHelloService() {
return new HelloService() {
#Override
public String getGreeting(String name) {
return "Hola "+name;
}
};
}
}
The issue here is that you are trying to override a xml bean from a #Configuration class, now I'm not 100% sure, but in spring 4 a xml bean still had precedence in choosing a bean, so the #Configuration beans would not get permission to overwrite the xml bean. Which was resolved in spring 5.
Your approach to use BeanPostProcessor is i guess the only viable solution for this.
I'm thinking maybe you could use a different bean name, implement your own behaviour and use #Qualifier annotation to choose which bean will get selected?

Spring Boot Application with dependency having multiple datasources

I am trying to create a Spring Boot Application, with a dependency jar which has got context.xml configured with multiple datasources.
In My spring boot application, I added #ImportResource("context.xml") to the #Configuration class and now, I get an exception that
"No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 4: XXXDataSource,YYYDataSource,ZZZDataSource,aaaaDataSource".
I read the documentation on multiple datasources in Spring Boot, but unable to fix this issue. Not sure, how I can configure my class, as I cannot change the dependency jar to change the way datasources are configured.
Please help!
You can use the "Primary" attribute on your datasource bean to make your autowiring choose it by default.
<bean primary="true|false"/>
If you are using Java configuration, use the #Primary annotation instead.
http://docs.spring.io/spring-framework/docs/4.0.4.RELEASE/javadoc-api/org/springframework/context/annotation/Primary.html
#Component
public class FooService {
private FooRepository fooRepository;
#Autowired
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
}
#Component
public class JdbcFooRepository {
public JdbcFooService(DataSource dataSource) {
// ...
}
}
#Primary
#Component
public class HibernateFooRepository {
public HibernateFooService(SessionFactory sessionFactory) {
// ...
}
}
If this still doesn't resolve the issue, you can name the bean, and use the #Qualifier annotation in your java classes, or use the "ref" attribute in your Spring XML configuration.
https://spring.io/blog/2014/11/04/a-quality-qualifier
#Autowired
#Qualifier( "ios") // the use is unique to Spring. It's darned convenient, too!
private MarketPlace marketPlace ;
If you require one of the datasources in the jar and are unable to modify the configuration, rather than importing the xml from the jar, copy the configurations you need into your own local spring context configuration.

Is it possible to construct an object partially with Spring DI and partially with Jersey DI?

I have a class JerseyWebService which uses Jersey DI to inject dependency
#Path("/baskets")
public class JerseyWebService {
#Inject
ExternalApiServiceInterface api;
...
}
The dependency is specified in the binder
public class CustomBinder extends AbstractBinder {
#Override
protected void configure() {
bind(ExternalApiService.class).to(ExternalApiServiceInterface.class);
...
}
But the problem here is that ExternalApiService has other dependencies and it uses Spring to inject them.
class ExternalApiService implements ExternalApiServiceInterface{
#Autowired
AnotherService aservice;
Is it possible to specify only some dependencies in binder which Jersey will Inject and other dependencies being injected by Spring ?
If not ,then if had been #Inject instead of #Autowired in ExternalApiService would it be mandatory to specify all bindings in the binder class?
Does Jersey DI has no Autowiring like feature or delegate injecting a dependency to Spring if it can't find any binding?
It should work. Given you have the required Spring-Jersey integration dependency[1] and have correctly configured the application[2]
1. See Spring DI support in Jersey
2. See official Jersey Spring example
What happens is HK2 (Jersey's DI framework) will look for an InjectionResolver for the #Autowired annotation, in order to resolve the dependency. The jersey-spring3 dependency has the AutowiredInjectionResolver, which holds a reference to Spring's ApplicationContext. From there it's just matter of looking it up in the application context, to resolve the dependency.

Spring : autowiring inside non spring class

I have this HTTP listener subclass
public class MigificSessionListener implements HttpSessionListener {
#Autowired
#Qualifier("notificationThread")
private NotificationThread notificationThread;
#Override
public void sessionDestroyed(HttpSessionEvent hse) {
// here notificationThread value is null
}
}
Value of notificationThread inside sessionDestroyed() is null.
How can i autowire sessionDestroyed inside this class ?
Your MigificSessionListener in not in your spring conext, spring even do not know it exists.
You can use WebApplicationContextUtils to get your spring context from ServletContext
WebApplicationContextUtils.getWebApplicationContext(sessionEvent.getSession().getServletContext())
You can enable Spring AOP with #EnableSpringConfigured and annotate your class with #Configurable. This let spring manage instances which are created outside the spring context with new. You will also need to enable either load-time weaving or compile-time weaving. This is documented in 9.8.1 Using AspectJ to dependency inject domain objects with Spring.
#Configuration
#EnableSpringConfigured
public class AppConfig {
}
#Configurable
public class MigificSessionListener implements HttpSessionListener {
#Autowired
#Qualifier("notificationThread")
private NotificationThread notificationThread;
//...
}
Convert your non-Spring managed class MigificSessionListener into a Spring-managed one by annotating it with #Configurable.
For this annotation to be recognised you need <context:spring-configured/> in your Spring XML config or #EnableSpringConfigured if you are using Spring Java config.
The #Autowired or injection of other dependencies will then succeed.

Resources