Why Spring Boot AOP pointcut not triggered - spring-boot

wanner test spring boot(1.5.20) aop with minimum code
class being aopped,
#Component
public class Test {
public Test() {
System.out.println("test constr");
}
public void print() {
System.out.println("test print");
}
}
aop class
#Aspect
#Component
public class LoggingAspect {
public LoggingAspect() {
System.out.println("aspect constr");
}
#After("execution(* *.Test.*(..))")
public void log(JoinPoint joinPoint) {
System.out.println("aspect print");
}
}
main class
#SpringBootApplication
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(AopApplication.class, args);
}
#Autowired
private Test test;
#Override
public void run(String... strings) throws Exception {
test.print();
}
}
both Test bean and LoggingAspect bean is created. Test.pring is executed. However, the pointcut log() is never triggered. I searched so and found no answer. I also tried #EnableAspectJAutoProxy with proxyTargetClass = True or False. In my understanding this params force to use cglib for Test class.
please let me know what I missed

figure out. change from .Test. to com.example.aop.Test.*, then works.

Related

Load configuration class before BeanDefinitionRegistryPostProcessor

configuration B below is using BeanDefinitionRegistryPostProcessor to dynamically register some spring beans. However I need to access Configuration class A which is autowired inside B. A always ends up being Null which is due to the fact for BeanDefinitionRegistryPostProcessor - "All regular bean definitions will have been loaded, but no beans will have been instantiated yet"
Is there anyway i can force the configuration loading so that A is instaniated before the Configuration class B so that applicationsProperties is not always null?
A
#ConfigurationProperties(prefix = "ie.test.appname.applications")
#Configuration
#EnableAutoConfiguration
#EnableConfigurationProperties
#RefreshScope
#Data
public class ApplicationProperties {
private List<Application> applications = new ArrayList<>();
}
B
#Configuration
#Import({ ApplicationProperties.class})
#Log4j
public class ConfigurationManager {
#Autowired
private ApplicationProperties applicationProperties;
#Bean
public BeanDefinitionRegistryPostProcessor beanPostProcessor(final ConfigurableEnvironment environment) {
return new BeanDefinitionRegistryPostProcessor() {
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
}
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanRegistry) throws BeansException {
doSomething();
}
};
}
private void doSomething() {
List<Application> storeNamesList = applicationProperties.getApplications(); // null pointer
}
Main with component scan
#SpringBootApplication
#EnableAspectJAutoProxy
#EnableScheduling
#EnableAsync
#ComponentScan("ie.test.appname")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication .class, args);
}
}

Why #PostConstruct not invoked in spring container?

I tried to add some entities in the db shema
config:
#Configuration
#ComponentScan(ApplicationConfig.basePackage)
public class ApplicationConfig {
public final static String basePackage = "test"
}
spring container invocation:
public class StartApp {
public static void main(String... args) throws Exception{
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
TestEntityRepository repository = (TestEntityRepository) context.getBean("testEntityRepository");
repository.save(new TestEntity("test"));
}
}
target class with annotation:
public class PersistenceService {
#Autowired
TestEntityRepository testEntityRepository;
#PostConstruct
public void initialize(){
//repository.deleteAll();
testEntityRepository.save(new TestEntity("test1"));
testEntityRepository.save(new TestEntity("test2"));
testEntityRepository.save(new TestEntity("test3"));
}
}
as the result in table only one record - "test". At the Tomcat all works fine.
https://github.com/GlebSa/TestSpringJPA
It seems your PersistenceServiceis not recognized as a Service. Can you add the #Service to PersistenceService?
#Service
public class PersistenceService {
...
}
Hope this help.

Null Pointer when using #SpringBootTest

I am using spring boot 1.4,
when using the #SpringBootTest annotation for integration test, it gives a null pointer.
#RunWith(SpringRunner.class);
#SpringBootTest
public class MyControllerTest {
#Test
public void mytest {
when().
get("/hello").
then().
body("hello");
}
}
and for main class:
#SpringApplication
#EnableCaching
#EnableAsync
public class HelloApp extends AsyncConfigureSupport {
public static void main(String[] args) {
SpringApplication.run(HelloApp.class, args);
}
#Override
public Executor getAsyncExecutor() {
...
}
}
Then in my controller:
#RestController
public class HelloController {
#Autowired
private HelloService helloService;
#RequestMapping("/hello");
public String hello() {
return helloService.sayHello();
}
}
HelloService
#Service
public class HelloService {
public String sayHello() {
return "hello";
}
}
But it ways says NullPointException when for helloService when processing request.
What am I missing?
You need to mock HelloService in your test class as your controller is calling a service .Here in your case Your Test class is not aware that there is any service available or not
The following example test class might help you. In this guide from spring an example is shown how to integration test a rest controller in a spring fashion way.
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class HelloControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void hello() throws Exception {
mockMvc.perform(get("/hello")).andExpect(content().string("hello"));
}
}

Spring Boot + DynamoDBTypeConverter dependancy injection

I'm trying to get DI working with a sample DynamoDBTypeConverter I'm playing around with and having no luck at all :( My service is always null and throws an error as a result in my jUnit test.
Here's my converter:
#Component
public class ArmTypeConverter implements DynamoDBTypeConverter<String, Arm> {
#Autowired
private ArmRepository armRepository;
#Override
public String convert(Arm Arm) {
return arm.getId();
}
#Override
public Arm unconvert(String id) {
return armRepository.findOne(id);
}
}
My application main:
#SpringBootApplication
#ComponentScan
#EnableSpringConfigured
#EnableLoadTimeWeaving(aspectjWeaving=EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableAutoConfiguration
public class ArmApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(ArmApplication.class, args);
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
}
My service:
#Service
public class ArmServiceImpl implements ArmService {
#Autowired
private ArmRepository armRepository;
#Override
public Arm create(String length, Set<Register> registers) {
Date now = new Date();
Arm arm = new Arm();
arm.setLength("85cm");
return armRepository.save(arm);
}
}
My Test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class ArmServiceTests {
#Autowired
private ArmService armService;
#Autowired
private TorsoService torsoService;
private Arm arm;
#Before
public void before() {
arm = armService.create("85cm", null);
torsoService.create("150cm", arm);
}
#After
public void after() {
// do nothing for now...
}
#Test
#WithUserDetails("admin#somewhere.com")
public void getArmTest() {
Arm c = armService.getArm(arm.getId());
assertThat(c).isNotNull();
assertThat(c.getId()).isEqualTo(arm.getId());
}
}
What am I doing wrong?
The issue was that I didn't have load time weaving configured properly

Create Spring boot standalone app

I'm trying to figure out how to build a Spring Boot standalone app. Of course to have things autowired requires some initial context starting point. If I just try to Autowire a class to run a job it is null even if I make it static.
Is there a way to use Spring #Services in a standalone non-web app?
#SpringBootApplication
public class MyApplication {
#Autowired
private static JobRunnerService job;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
job.send(); //job is null !
}
}
So first wired in a static JobRunnerService to the main running MyApplication the JobRunner(Service) Class has a non-static SshSessionService wired into it.
the SshSession(Service) finally just has a no-arg constructor.
#Service("jobRunnerService")
public final class JobRunner implements JobRunnerService{
#Autowired
private SshSessionService ssh;
#Autowired
public JobRunner(SshSessionService ssh){
this.ssh = ssh;
}
public void sendToAgent() { ....
}
#Service("sshSessionService")
public class SshSession implements SshSessionService {
public SshSession() {
}
}
It starts off being null at the JobRunnerService job reference.
Several different solutions comes to mind:
If you take a look at the SpringApplication.run() method you will notice that it returns a ApplicationContext. From that, you can fetch the JobRunnerService, e.g.
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
JobRunnerService job = ctx.getBean(JobRunnerService.class);
job.send();
}
}
Another solution is to use #PostConstruct annotation for the send() method:
#Service("jobRunnerService")
public class JobRunner implements JobRunnerService {
#PostConstruct
public void send() { ... }
}
However in your case, I would implement the ApplicationRunner interface, either as a separate bean which autowires the JobRunnerService and then calls its send() method
#Component
public class SendRunner implements ApplicationRunner {
#Autowired
private JobRunnerService job;
#Override
public void run(ApplicationArguments args) {
job.send();
}
}
or let the JobRunner implement the ApplicationRunner interface directly:
#Service("jobRunnerService")
public class JobRunner implements JobRunnerService, ApplicationRunner {
#Override
public void send() { ... }
#Override
public void run(ApplicationArguments args) {
send();
}
}
You haven't provided the code for JobRunnerService but I am assuming it has a default constructor and that it is annotated by #Component for Spring to figure it out as a bean before you can actually autowire it. your job is null probably because it's not able to find an autowired bean for JobRunnerService and that's probably because you don't have an identifier for Spring to scan and create bean of type JobRunnerService
You can use #Servicesor #Component to the JobRunnerService class then add annotation #ComponentScan("package of JobRunnerService") below #SpringBootApplication, see this link:
How to scan multiple paths using the #ComponentScan annotation?
You need a few steps to get your standalone app working:
A class with main() method.
A #SpringBootApplication annotation to your main class.
And a call to the SpringApplication.run() method.
package com.example.myproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication // same as #Configuration #EnableAutoConfiguration #ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
As noted, the #SpringBootApplication is a composite annotation which consist of #Configuration #EnableAutoConfiguration and #ComponentScan. In other words, it can be replaced by the three latter annotations. Alternatively, you can use the alias scanBasePackage or scanBasePackageClasses to customize which directories that should be used for component scanning.
The example is copied from the #SpringBootApplication paragraph in the Spring Boot reference docs (see link above). If you would like to quick start your project, complete with build scripts (Maven or Gradle), dependencies, etc, you can generate a project skeleton using the Spring Initializr
I'm trying to run as Thread/runnable now as mentioned in the Spring document 3. Task Execution and Scheduling..
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
private class MessagePrinterTask implements Runnable {
private String message;
public MessagePrinterTask(String message) {
this.message = message;
}
public void run() {
System.out.println(message);
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask("Message" + i));
}
}
}
So in my case I'm trying...
#Service("jobRunnerService")
#Component
public class JobRunner implements JobRunnerService, ApplicationRunner{
#Autowired
public TaskExecutor taskExecutor;
#Autowired
private SshSessionService ssh;
private class JobTask implements Runnable{
public void run(){
Boolean success = connectToAgent();
if(success){
log.debug("CONNECTED!!!");
}
}
}
/**
* Construct JobRunner with TaskExecutor
* #param taskExecutor
*/
#Autowired
public JobRunner(TaskExecutor taskExecutor, SshSessionService ssh) {
this.taskExecutor = taskExecutor;
this.ssh = ssh;
}
private Map<String, String> sessionParams;
private final Logger log = LoggerFactory.getLogger(this.getClass());
#Override
public void run(ApplicationArguments args) {
/**
* Starting point of application
*
*/
taskExecutor.execute(new JobTask());
}
just getting org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.core.task.TaskExecutor] found for dependency
How can i get the imported lib to be accepted as a TaskExecutor Bean ??

Resources