Autowiring not happening in spring - spring

I have been trying to use autowiring, but it fails to get autowired. Here is the code snippet,
App context file:
<context:annotation-config />
<context:component-scan base-package="com.shapes" />
<bean id = "triangle" class = "com.shapes.Triangle" autowire="byName"></bean>
Triangle class:
#Component
public class Triangle implements Shape {
#Override
public void draw() {
System.out.println("In draw");
}
}
Main class :
public class MainShapes {
#Autowired
private Triangle triangle;
/**
* #param args
*/
public static void main(String[] args) {
MainShapes shapes = new MainShapes();
shapes.triangle.draw();
}
}

Only spring-managed beans will get autowired automatically (unless you use some kind of AOP).
In your main class you create MainShapes manually, and there is nothing related to spring except annotations.
It won't magically work that way. You probably want to retrieve your MainShapes from spring ioc container (and make sure that it is in app context) ...

Related

Is there a way to use Spring boot beans in a Gatling simulation?

I am currently writing a Spring boot application that will perform loadtests on another app. I want to use Gatling to manage the tests, but I need it to access the configuration that I defined in beans of my Spring app.
Here is what I would like to see working :
public class MySimulation extends Simulation {
#Autowired
private JMSConnectionFactoryBeanClass myConnectionFactory;
public MySimulation() {
JmsProtocolBuilder jmsProtocol = jms.connectionFactory(myBean);
ScenarioBuilder scn = scenario("My Simulation Scenario")
.exec(
jms("test")
.send()
.queue("myQueue")
.textMessage("message")
);
{
setUp(
scn.injectOpen(rampUsers(10).during(5))
).protocols(jmsProtocol);
}
}
When I hardcode the configuration into the simulation class and remove all #Autowired thing, everything works, so it must be comming from the dependency injection. Does anybody know if there is a way to us spring beans in a gatling simulation ?
Following Stéphane Landelle advice, here is what I came up with, but instead of creating my app context inside of the simulation, I figured out how to run the simulation along with my spring app using gatling API :
public class GatlingRunner {
public static void run() {
GatlingPropertiesBuilder props = new GatlingPropertiesBuilder();
props.simulationClass("path.to.Simulation");
Gatling.fromMap(props.build());
}
}
This is how I modified my spring app :
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
GatlingRunner.run();
}
}
Finally, to use spring beans in the simulation, I wrote a context provider that would make the link between spring and gatling :
#Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
public static ApplicationContext getApplicationContext() {
return context;
}
#Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
ApplicationContextProvider.context = context;
}
}
Now, to get a bean inside of the simulation, all I needed was this :
Bean myBean = ApplicationContextProvider.getApplicationContext()
.getBean("myBean", Bean.class)
You can't use #Autowired. You have to create an ApplicationContext programmatically and pull the JMSConnectionFactoryBeanClass from it.
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = MySimulation.class, loader = SpringApplicationContextLoader.class)
public class MySimulation extends GatlingTest {
#Autowired
private JMSConnectionFactoryBeanClass myConnectionFactory;
#Test
public void test() {
...
}
}

Dependency injection in custom evaluator in logback in spring boot

I am writing a custom evaluator in which I want to autowire another bean. I am unable to do so as evaluator gets initialized by logger where as beans are initialized by spring context. Below is the sample of my code:
In logback-spring.xml:
<appender name="myAppender" class="ch.qos.logback.classic.net.SMTPAppender">
<evaluator class="com.package.CustomEvaluator">
<marker>FATAL</marker>
<interval>1000000</interval>
</evaluator>
</appender>
My custom evaluator:
#Slf4j
#Component
public class CustomEvaluator extends OnMarkerEvaluator {
#Autowired
private MyService myService;
#Override
public boolean evaluate(ILoggingEvent event) throws EvaluationException {
\\logic goes here
}
}
I am getting object of MyService always as null(which is expected). Is there any work around for this?
It don't think its possible because the Evaluator being an internal logback abstraction is not managed / initialized by spring, so obviously spring can't autowire anything into the evaluator.
In addition note, that logback gets initialized even before application context starts.
Of course you could provide some global holder class for the application context and set the context to it in the main method, and then get the reference to it in this evaluator, something like this:
public class ApplicationContextHolder {
private static ApplicationContext context;
// call it in main() method
public static void setContext(ApplicationContext ctx) {context = ctx;}
public static ApplicationContext getContext() {return context;}
}
class CustomEvaluator extends OnMarkerEvaluator {
public boolean evaluate(ILoggingEvent event) throws EvaluationException {
ApplicationContext ctx = ApplicationContextHolder.getContext();
if(ctx == null) {return false;} // not yet initialized / accessible
MyService myService = ctx.getBean(MyService.class);
}
}
But all-in-all I believe its a very ugly solution.
As a suggestion, I think you should consider refactoring of the logic so that the decision of whether to send an email based on logging event will be taken in the application (which is, I assume, spring boot driven so you have an access to the MyService)
Given the current implementation:
public foo() {
LOGGER.info("This should be sent by email");
}
I suggest a part of application:
#Component
public class MyLogic {
#Autowired MyService myService;
public void foo() {
if(myService.shouldSend()) {
LOGGER.info("This should be sent by email");
}
}
}

Configure App. context to use QualifierAnnotationAutowireCandidateResolver using annotations

The problem started when in Spring 4.2.5 I attempted to inject an interface having more than one implementations, below is the test class :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = VenueConfig.class)
public class BandEventTest {
#Autowired
#Qualifier("rush")
Band rush;
#Autowired
Venue venue;
#Test
public void assertBandNotNull() {
Assert.assertNotNull("Who will perform if there's no band !!!", rush);
}
#Test
public void assertVenueNotNull() {
Assert.assertNotNull("Without venue, there would be no event !!!", venue);
}
#Test
public void triggerEvent() {
venue.hostPerformance();
}
}
I have the interface Band which is implemented by two beans viz. Rush and VanHalen :
#Component("rush")
public class Rush implements Band {
/*
* (non-Javadoc)
*
* #see com.book.springinaction.chap2.autowiring.Band#play()
*/
public void play() {
// TODO Auto-generated method stub
System.out.println("Rush playing 'Limelight'");
}
}
In spite of using the Qualifier annotation(please ignore the lower/upper case current Qualifier name and the Rush bean name, I have tried all the combinations in vain). My suspicion was confirmed after I read this thread about the QualifierAnnotationAutowireCandidateResolver not being set in App. context since Spring 4.0
I wish to fit the below (mentioned even in the Spring documentation) :
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>org.springframework.beans.factory.annotation.Qualifier</value>
</set>
</property>
</bean>
in my below Configuration class WITHOUT XML i.e JUST ANNOTATIONS
#Configuration
#ComponentScan
public class VenueConfig {
/*Does using #Bean for CustomAutowireConfigurer make sense ?*/
}
I don't use Spring annotations, but your pointer to the other thread was so helpful that I did a bit of research. Based on the Spring docs, I believe you can have the same effect with:
#Configuration
#ComponentScan
public class VenueConfig {
#Bean
public CustomAutowireConfigurer qualifierAutowireConfigurer() {
CustomAutowireConfigurer customAutowireConfig = new CustomAutowireConfigurer();
customAutowireConfig.setCustomQualifierTypes( Collections.singleton( Qualifier.class ));
return customAutowireConfig;
}
}

Java 8 and Spring 4 : Use autowiring in interface

Java 8 added a new feature by which we can provide method implementation in interfaces.
Is there any way in Spring 4 by which we can inject beans in the interface which can be used inside the method body?
Below is the sample code
public interface TestWiring{
#Autowired
public Service service;// this is not possible as it would be static.
//Is there any way I can inject any service bean which can be used inside testWiringMethod.
default void testWiringMethod(){
// Call method of service
service.testService();
}
}
This is a bit tricky but it works if you need the dependency inside the interface for whatever requirement.
The idea would be to declare a method that will force the implemented class to provide that dependency you want to autowire.
The bad side of this approach is that if you want to provide too many dependencies the code won't be pretty since you will need one getter for each dependency.
public interface TestWiring {
public Service getService();
default void testWiringMethod(){
getService().testService();
}
}
public class TestClass implements TestWiring {
#Autowire private Service service;
#Override
public Service getService() {
return service;
}
}
You can created Class utils of application context and use it everywhere even not bean class .
you can have code somethins this :
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext context) {
ApplicationContextUtil.applicationContext = context;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
and add this to your spring configuration
<bean class="com.example.ApplicationContextUtil" id="applicationContextUtil"/>
now simple to use when you need :
ApplicationContextUtil.getApplicationContext().getBean(SampleBean.class)
this word in web and simple spring app.

Spring can you autowire inside an abstract class?

Spring is failing to autowire my object? Is it possible to autowire an object within an abstract class. Assume all schemas are supplied in application-context.xml
Question: What annotation should be on the base and extending classes (if any) #Service #Component?
Example
abstract class SuperMan {
#Autowire
private DatabaseService databaseService;
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
Extending class
public class SuperGirl extends SuperMan {
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
application-context.xml
<context:component-scan base-package="com.baseLocation" />
<context:annotation-config/>
I have that kind of spring setup working
an abstract class with an autowired field
public abstract class AbstractJobRoute extends RouteBuilder {
#Autowired
private GlobalSettingsService settingsService;
and several children defined with #Component annotation.
Normally, Spring should do the autowiring, as long as your abstract class is in the base-package provided for component scan.
See this and this for further reference.
#Service and #Component are both stereotypes that creates beans of the annotated type inside the Spring container. As Spring Docs state,
This annotation serves as a specialization of #Component, allowing for
implementation classes to be autodetected through classpath scanning.
What if you need any database operation in SuperGirl you would inject it again into SuperGirl.
I think the main idea is using the same object reference in different classes.
So what about this:
//There is no annotation about Spring in the abstract part.
abstract class SuperMan {
private final DatabaseService databaseService;
public SuperMan(DatabaseService databaseService) {
this.databaseService = databaseService;
}
abstract void Fly();
protected void doSuperPowerAction(Thing thing) {
//busy code
databaseService.save(thing);
}
}
#Component
public class SuperGirl extends SuperMan {
private final DatabaseService databaseService;
#Autowired
public SuperGirl (DatabaseService databaseService) {
super(databaseService);
this.databaseService = databaseService;
}
#Override
public void Fly() {
//busy code
}
public doSomethingSuperGirlDoes() {
//busy code
doSuperPowerAction(thing)
}
In my opinion, inject once run everywhere :)
In my case, inside a Spring4 Application, i had to use a classic Abstract Factory Pattern(for which i took the idea from - http://java-design-patterns.com/patterns/abstract-factory/) to create instances each and every time there was a operation to be done.So my code was to be designed like:
public abstract class EO {
#Autowired
protected SmsNotificationService smsNotificationService;
#Autowired
protected SendEmailService sendEmailService;
...
protected abstract void executeOperation(GenericMessage gMessage);
}
public final class OperationsExecutor {
public enum OperationsType {
ENROLL, CAMPAIGN
}
private OperationsExecutor() {
}
public static Object delegateOperation(OperationsType type, Object obj)
{
switch(type) {
case ENROLL:
if (obj == null) {
return new EnrollOperation();
}
return EnrollOperation.validateRequestParams(obj);
case CAMPAIGN:
if (obj == null) {
return new CampaignOperation();
}
return CampaignOperation.validateRequestParams(obj);
default:
throw new IllegalArgumentException("OperationsType not supported.");
}
}
}
#Configurable(dependencyCheck = true)
public class CampaignOperation extends EO {
#Override
public void executeOperation(GenericMessage genericMessage) {
LOGGER.info("This is CAMPAIGN Operation: " + genericMessage);
}
}
Initially to inject the dependencies in the abstract class I tried all stereotype annotations like #Component, #Service etc but even though Spring context file had ComponentScanning for the entire package, but somehow while creating instances of Subclasses like CampaignOperation, the Super Abstract class EO was having null for its properties as spring was unable to recognize and inject its dependencies.After much trial and error I used this **#Configurable(dependencyCheck = true)** annotation and finally Spring was able to inject the dependencies and I was able to use the properties in the subclass without cluttering them with too many properties.
<context:annotation-config />
<context:component-scan base-package="com.xyz" />
I also tried these other references to find a solution:
http://www.captaindebug.com/2011/06/implementing-springs-factorybean.html#.WqF5pJPwaAN
http://forum.spring.io/forum/spring-projects/container/46815-problem-with-autowired-in-abstract-class
https://github.com/cavallefano/Abstract-Factory-Pattern-Spring-Annotation
http://www.jcombat.com/spring/factory-implementation-using-servicelocatorfactorybean-in-spring
https://www.madbit.org/blog/programming/1074/1074/#sthash.XEJXdIR5.dpbs
Using abstract factory with Spring framework
Spring Autowiring not working for Abstract classes
Inject spring dependency in abstract super class
Spring and Abstract class - injecting properties in abstract classes
Spring autowire dependency defined in an abstract class
Please try using **#Configurable(dependencyCheck = true)** and update this post, I might try helping you if you face any problems.

Resources