In a project we use annotions to define aspects.
Unfortunately I can't get eclipse to show a marker next to the advised methods.
In another project we use XML to define the aspects and eclipse shows markers.
Best I post some code to clarify:
First a bean to be advised:
package aop.test;
import org.springframework.stereotype.Service;
#Service
public class Worker {
public void work() {}
}
Then the aspect:
package aop.test;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;
#Aspect
#Service
public class WorkerLogger {
#Before("execution(void aop.test.Worker.work())")
public void log() {
System.out.println("working...");
}
}
And finally a main method to prepare the ApplicationContext, get the bean and run the advised method:
package aop.test;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context;
context = new AnnotationConfigApplicationContext();
context.register(AnnotationAwareAspectJAutoProxyCreator.class);
context.scan("aop.test");
context.refresh();
context.getBean(Worker.class).work();
}
}
I tried this in eclipse using the STS plugin and the STS itself. I never get a red arrow next to work() indicating it is advised.
What am I missing?
Have you installed the STS plugin on your Eclipse? It should be available on the Help > Eclipse Marketplace
Related
I'm trying to mplement custom LockService class like it said in this answer: https://stackoverflow.com/a/15567073/5182320
package liquibase.ext;
import liquibase.exception.DatabaseException;
import liquibase.lockservice.StandardLockService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
#Slf4j
#Configuration
public class TimeoutLockService extends StandardLockService {
#SneakyThrows
#Override
public void waitForLock() {
forceReleaseLock();
}
#Override
public int getPriority() {
return super.getPriority() + 1;
}
#Override
public void init() throws DatabaseException {
super.init();
log.info("Init called");
}
}
Placed the class in the package liquibase.ext
But when I'm running my application it's ignoring this class and still trying to acquire the lock.
I was trying to do something similar and I had a similar issue, where my changes were not pickup, even though it was in package liquibase.ext . I am using liquibase 4.3.5 and the following document helped me.
Starting with 4.0, we switched to the standard java.util.ServiceLoader system to find extension classes.
https://docs.liquibase.com/tools-integrations/extensions/extension-upgrade-guides/lb-4.0-upgrade-guide.html
I had to crate the liquibase.lockservice.LockService file in META-INF/services with my implementation and solve the issue.
I working with java code in AEM.
We use maven and in pom.xml is exist all needed dependencies and aspectj-maven-plugin
I prepared aspect with pointcut:
package org.xxx.aop.aspects;
import javax.jcr.Node;
import org.apache.sling.api.SlingHttpServletRequest;
import org.aspectj.lang.*;
import org.aspectj.lang.annotation.*;
import org.slf4j.*;
#Aspect
public class NodeAspect {
private final Logger LOG = LoggerFactory.getLogger(NodeAspect.class);
#Pointcut("execution(public * javax.jcr.Node.*(..)")
public void jcrNodeAccess() {}
#Around("jcrNodeAccess()")
public Object jcrNodeMethodCall(ProceedingJoinPoint thisJoinPoint) throws Throwable {
LOG.info("--- LOG NodeAspect ---");
Object result = thisJoinPoint.proceed();
// some code
// ..
return result;
}
But when I installed my package in AEM, my aspect does not work.
Maybe my aspect I will need to activate?
Maybe this problem related with behavior of OSGI (felix) in AEM?
Please provide to me ideas how to fix it
I am still a beginner in Spring Framework so I tried to code a program about "introduction" in Spring AOP but I am facing an error while compiling. Please find below the classes in the package concert:
PerformanceImp.java
package concert;
import org.springframework.stereotype.Component;
#Component
public class PerformanceImp implements Performance {
public void perform() {
System.out.println("This is the performance function");
}
}
Performance.java
package concert;
public interface Performance {
public void perform();
}
Encoreable.java
package concert;
public interface Encoreable {
void performEncore();
}
DefaultEncoreable.java
package concert;
import org.springframework.stereotype.Component;
#Component
public class DefaultEncoreable implements Encoreable {
public void performEncore() {
System.out.println("This is the performEncore function");
}
}
EncoreableIntroducer.java
package concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
#Component
#Aspect
public class EncoreableIntroducer {
#DeclareParents(value="concert.Performance+",
defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
ConcertConfig.java
package concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("concert")
public class ConcertConfig {
}
And the main class:
Main.java
package concert;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ConcertConfig.class);
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
((Encoreable) pi).performEncore();
pi.perform();
}
}
I am getting the error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'concert.PerformanceImp' available
Any help please ?
You cannot access the implementation (PerformanceImp) by default, because you enabled AOP, which sets to target interfaces instead of implementation. If you would remove EnableAspectJAutoProxy, you would see the code would work fine.
To understand a bit more about how AOP targeting works, take a look at this Spring Documentation
Spring AOP can also use CGLIB proxies. This is necessary to proxy
classes rather than interfaces. CGLIB is used by default if a business
object does not implement an interface. As it is good practice to
program to interfaces rather than classes; business classes normally
will implement one or more business interfaces. It is possible to
force the use of CGLIB, in those (hopefully rare) cases where you need
to advise a method that is not declared on an interface, or where you
need to pass a proxied object to a method as a concrete type.
So you have two options:
Take the interface when trying to get the bean from the ApplicationContext.
Enable AOP to target concrete classes instead.
To do this point #2, modify your annotation as follows:
#EnableAspectJAutoProxy(proxyTargetClass = true)
Try:
Performance pi = context.getBean("performanceImp", Performance.class);
instead of:
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
I am trying to hook into the creation of the context using a custom application listener like this
#Component
public class ContextStartedListener implements ApplicationListener<ContextStartedEvent> {
#Override
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("Context started"); // this never happens
}
}
But the onApplicationEvent method never fires. If I use a different event such as ContextRefreshedEvent then it works just fine, but I need to hook into before it is created. Any advice? Thanks!
[Edit]
Editing answer adding more info because of the downvote.
The reason why you are not getting a callback by the listener is because you are not explicitly calling the LifeCycle start() method (JavaDoc).
This cascades down to your ApplicationContext normally via the AbstractApplicationContext on in Spring Boot case via the ConfigurableApplicationContext.
Example of working code below demonstrating how your callback would work (just explicitly call the start() method)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
applicationContext.start();
}
#Component
class ContextStartedListener implements ApplicationListener<ContextStartedEvent> {
#Override
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("Context started");
}
}
}
The reason why I suggested below the ContextRefreshedEvent callback instead is because behind the scenes the refresh() code is getting invoked.
If you drill down the SpringApplication#run() method you'll eventually see it.
Again here's a working example of how this would work using the ContextRefreshedEvent:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Component
class ContextStartedListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("Context refreshed");
}
}
}
[Before Edit]
Change the Generic type to ContextRefreshedEvent instead and then it should work.
For more details read this article from the Spring Blog. Just to quote the part about the ContextRefreshedEvent:
[..]This allows MyListener to be notified when the context has refreshed
and one can use that to run arbitrary code when the application
context has fully started.[..]
I am new to the Play framework and Java in general. What is wrong with this Global.java file? I get the error no interface expected here on the line public class Global extends GlobalSettings {
import play.*;
import play.libs.*;
import com.avaje.ebean.Ebean;
import models.*;
import java.util.*;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import play.api.Application;
import play.api.GlobalSettings;
public class Global extends GlobalSettings {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
#Override
public void onStart(Application app) {
if(User.find.findRowCount() == 0){
Ebean.save((List) Yaml.load("initial-data.yml"));
}
//Start Spring WS framework
applicationContext.start();
}
#Override
public void onStop(Application app) {
applicationContext.stop();
}
}
I am trying to create a simple SOAP web service within Play Java using the Spring framework. Perhaps I am going about this the wrong way?
Remove the play.api.GlobalSettings import. Do the same for play.api.Application. These...
import play.api.Application;
import play.api.GlobalSettings;
It looks like your project has defaulted to a Scala project rather than a Java one, I think. You should be using the play.GlobalSettings and play.Application objects for a Java Play application, covered by your current play.* import.