Aspect from External Jar is getting executed - spring-boot

I have an aspect written in a project called connector and generated a jar for that project. I have integrated that jar into another spring boot application as a Gradle dependency. This aspect is not working.
JAR FILE CODE
TrackExecutionTime.java
package a.b.aspect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface TrackExecutionTime {}
ConnectorAOPConfig.java
package a.b.aspect;
#Aspect
#Component
public class ConnectorAOPConfig {
public ConnectorAOPConfig() {
}
#Around("#annotation(a.b.aspect.TrackExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Inside Aspect");
return joinPoint.proceed();
}
}
MAIN CODE
AOPConfig.java
package a.c.config;
// Imports here
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackages = {"a.b.aspect"})
public class AOPConfig {
#Bean
public ConnectorAOPConfig aopHandler()
{
return new ConnectorAOPConfig();
}
}
Code targeted by aspect:
#TrackExecutionTime
public static ApplicationDTO fetchApplicationByName(String name) {
//code
return application;
}
Note: I added that annotation in the connector jar only. Still it is not getting triggered.

Related

Error : Field job in required a bean of type 'org.springframework.batch.core.JobLauncher' that could not be found

The below are my 2 classes for the App and the config
package com.spring;
import org.springframework.batch.core.Job;
import org.springframework.context.annotation.Bean;
public class Configuration {
#Bean
Job testRun() {
return null;
}
}
package com.spring;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class App implements CommandLineRunner {
#Autowired
JobLauncher jobLauncher;
#Autowired
Job testRun;
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
System.out.println("RUNNING ...");
jobLauncher.run(testRun, null);
}
}
However, when I try to execute this, I am getting the error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field jobLauncher in com.spark.spring.App required a bean of type org.springframework.batch.core.launch.JobLauncher that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type org.springframework.batch.core.launch.JobLauncher in your configuration.
Am I missing something here? I believe I do have both a JobLauncher and Job bean defined. Also why do I need to define a bean for the Job Launcher?
You need to make your Configuration class a Spring configuration class, meaning annotate it with #Configuration as follows:
#Configuration
public class Configuration {
#Bean
Job testRun() {
return null;
}
}
Moreover, according to the error you reported, you need to define a bean of type JobLauncher in that configuration class (or somewhere else), or add the #EnableBatchProcessing annotation which will create it automatically for you:
#Configuration
#EnableBatchProcessing
public class Configuration {
#Bean
Job testRun() {
return null;
}
}

I am trying to get NoUniqueBeanDefinitionException but i am not getting it any clue why i am not getting

I am trying to get NoUniqueBeanDefinitionException but i am not getting it any clue why i am not getting
package com.example.demo;
public interface IDateGen {
}
package com.example.demo;
import org.springframework.stereotype.Service;
#Service
public class DateGen implements IDateGen {
}
package com.example.demo;
import org.springframework.stereotype.Service;
#Service
public class DateGen2 implements IDateGen {
}
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class DateGenUtil {
#Autowired
private IDateGen dateGen;
public IDateGen getDateGen() {
return dateGen;
}
public void setDateGen(IDateGen dateGen) {
this.dateGen = dateGen;
}
}
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Demo3Application {
public static void main(String[] args) {
ApplicationContext appContext = SpringApplication.run(Demo3Application.class, args);
DateGenUtil util = appContext.getBean(DateGenUtil.class);
System.out.println(util.getDateGen());
}
}
When i run the main method i getting
com.example.demo.DateGen#6075b2d3
Can anyone tell why i am not getting NoUniqueBeanDefinitionException ? Thanks in advance
The dependency injection first checks for autoWiring by type and then autowire by name, wen it looks for dateGen dependency in class DateGenUtil it checks by type then it is getting two Objects, then again it tries to do autoWiringByName it gets the one object
if we rename the variable like in the below code it gives the exception, hope anyone can confirm this
#Component
public class DateGenUtil {
#Autowired
//private IDateGen dateGen;
private IDateGen date;
}

Controller not getting mapped

My controller is not getting mapped in the console.
My main class Application
package com.ruchi.web.sbfirst;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SbFirstApplication {
public static void main(String[] args) {
SpringApplication.run(SbFirstApplication.class, args);
}
}
LoginController
package com.ruchi.web.sbfirst.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class LoginController {
#RequestMapping("/login")
public String loginMessage() {
return "Hello";
}
}
Add #RestController annotation before the LoginController class
#RestController
public class LoginController {
#RequestMapping("/login")
public String loginMessage() {
return "Hello";
}
}
Reason you are using spring boot and also if you want to use #Controller annotation enable WebMVC.
click on the your project and go to the gradle or maven (which ever you have used) and refresh it then built your project and now re-run it this time it will not disappoint your :)

JUnit Platform Launcher start TestClass with Injected Spring Beans

I try to run a testclass with the JUnit Platform Launcher. The Testclass contains some #Autowired Components. The issue is, that the injection doesn't seem to work. Is that even possible with JUnit Platform?
My code is as follows:
App.java
#SpringBootApplication(scanBasePackages = "com.mytests")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Component
import org.springframework.stereotype.Component;
#Component
public class SomeBean {
public String returnSuccess() {
return "SUCCESS";
}
}
Testclass
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class SomeTests {
#Autowired
private SomeBean aBean;
#Test
public void testSuccess() throws Exception {
String result = aBean.returnSuccess();
assertTrue(result.equals("SUCCESS"));
}
}
Controller which calls the test class
#RestController
public class TestController {
#RequestMapping("/tests")
public void executeTests() throws Throwable {
LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectPackage("com.mytests"), selectClass(SomeTests.class))
.build();
Launcher launcher = LauncherFactory.create();
SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
listener.getSummary();
}
}

Multiple #SpringBootApplication Annotation in a Project

In my project created by SpringBoot,
I have added 2 main classes with #SpringBootApplication.
Because if I use STS I can choose one main application when start to debug.
But I found that while SpringDemoApplication is up ,RabbitMQApplication is also running.
Is this specification ? working appropriately?
Here this is sample to reproduce
https://github.com/MariMurotani/SpringDemo/tree/6_rabbitMQ
SpringDemoApplication
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringDemoApplication.class);
ApplicationContext context = application.run(args);
}
}
RabbitMQApplication
package demo;
import java.util.Date;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import demo.configs.Const;
import demo.dto.Mail;
#SpringBootApplication
public class RabbitMQApplication implements CommandLineRunner {
#Autowired
ApplicationContext context;
#Autowired
RabbitTemplate rabbitTemplate;
#Bean
Queue queue() {
return new Queue(Const.RabbitMQMessageQue, false);
}
#Bean
TopicExchange exchange() {
return new TopicExchange("spring-boot-exchange");
}
#Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(Const.RabbitMQMessageQue);
}
#Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(Const.RabbitMQMessageQue);
//container.setMessageListener(listenerAdapter);
return container;
}
/*
For asyncronized receiving
#Bean
Receiver receiver() {
return new Receiver();
}
#Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}*/
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(RabbitMQApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println("Waiting five seconds...");
while(0 < 1){
for(int i = 0 ; i < 5 ; i++){
String object = (String)rabbitTemplate.receiveAndConvert(Const.RabbitMQMessageQue);
if(object != null){
try{
System.out.println(new Date().toGMTString() + ": " + object);
ObjectMapper mapper = new ObjectMapper();
Mail mail = mapper.readValue(object, Mail.class);
System.out.println(mail.getToAddress() + " , " + mail.getStrContent());
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
Thread.sleep(10000);
}
}
}
The #SpringBootApplication annotation is a shortcut annotation for #Configuration, #EnableAutoConfiguration, and #ComponentScan.
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html
The default behavior of #ComponentScan is to look for #Configuration and #Component classes within the same package and all sub-packages of the annotated class. Since all your classes are in the same package, when you start any one of them Spring will find the others and treat them like #Configuration classes, and register their beans, etc.
So yes, this is expected behavior given your project setup. Put each #SpringBootApplication class in a separate subpackage if you don't want this to happen for local testing. If this moves beyond a demo at some point you'll probably want to come up with a better setup (subprojects for each #SpringBootApplication perhaps).
I recently faced the same scenario here and I solved with a simple solution.
My projected uses Maven and is configured with sub-modules like this:
my-parent
|__ my-main (depends on my-other module)
|__ my-other
Each module has its own main App class annotated with #SpringBootApplication. The problem is that both classes reside in the same package even though they are in different modules.
Once I start MyMainApp it also starts MyOtherApp. To avoid this I just had to do the following.
In the my-main module I have:
#SpringBootApplication
public class MyMainApp ... { ... }
and in the my-other module I have:
#SpringBootApplication
#ConditionalOnProperty(name = "my.other.active", havingValue = "true", matchIfMissing = false)
public class MyOtherApp ... { ... }
with application.properties with:
my.other.active=true
It works as expected.

Resources