Spring aop is not getting triggerd for external jar method in spring boot application - spring-aop

I am trying to have point cut for a method in jar and it is not getting triggered properly
I have my rest endpoint code as below :
package com.example.log.javatpoint;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class Test{
#Autowired
Operation op;
private static final Logger LOG = LogManager.getLogger(Test.class);
#RequestMapping(value = "/customs", method = RequestMethod.GET)
public String custom() {
op.msg();
op.display();
LOG.info("Hello World");
LOG.info("Hello {0}", "World 2");
return "custom";
}
}
Operation class :
#Component
public class Operation{
public void msg(){System.out.println("msg() is invoked");}
public void display(){System.out.println("display() is invoked");}
}
#Aspect
#Component
public class TrackOperation
{
#Pointcut("execution(* Operation.*(..))")
public void abcPointcut(){}
#Around("abcPointcut()")
public Object myAdvice(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("Additional Concern Before calling actual method");
Object obj=pjp.proceed();
System.out.println("Additional Concern After calling actual method");
return obj;
}
#Pointcut("execution(* org.apache.logging.log4j.LogManager.info(..))")
public void abcPointcutLog(){}
#Around("abcPointcutLog()")
public Object myAdviceLog(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("Additional Concern Before calling actual method");
Object obj=pjp.proceed();
System.out.println("Additional Concern After calling actual method");
return obj;
}
}
Note : Point cut is working for Operation class where as point cut is not working for org.apache.logging.log4j.LogManager tried also providing org.apache.logging.log4j.Logger in point cut.
I expect the output as :
Additional Concern Before calling actual method
2019-09-24 12:28:58.540 INFO 10076 --- [nio-8080-exec-1] com.example.log.javatpoint.Test : Hello World
Additional Concern After calling actual method
Additional Concern Before calling actual method
2019-09-24 12:28:58.540 INFO 10076 --- [nio-8080-exec-1] com.example.log.javatpoint.Test : Hello {0}
Additional Concern After calling actual method
but the actual output is :
2019-09-24 12:28:58.540 INFO 10076 --- [nio-8080-exec-1] com.example.log.javatpoint.Test : Hello World
2019-09-24 12:28:58.540 INFO 10076 --- [nio-8080-exec-1] com.example.log.javatpoint.Test : Hello {0}

This question is a "classic" and has been asked so many times here already...
Please read the Spring AOP manual before using a tool you don't know. It will tell you that Spring AOP can only be applied to Spring components/beans, not to non-Spring POJOs. For that you need full AspectJ which you can use within Spring or completely without Spring.
Log4J classes are not Spring components, so the above applies to your situation. Here you find information about how to use AspectJ load-time weaving (LTW) instead of Spring AOP for your purpose.

Related

Using Project Reactor with Apache Camel

I'd like to know if it is possible to use Project Reactor with Apache Camel, so applications be fully reactive and non-blocking IO. I'd like to know how does the Project Reactor support works when integrating other Apache Camel's components.
Can I read for example from S3 reactively (therefore I'll need to use the Async S3 client behind the scenes)? Or will I block when reading from S3 and then just create a Flux out of what has been returned?
Where reactiveness is needed, you should use the relevant spring and reactor libraries. there are pseudo camel code also u can db call in camel bean or processors etc
#RestController
#RequestMapping(value = "/api/books")
#RequiredArgsContructor
public class HomeController {
private final BookRepository bookRepository;
private final ProducerTemplate template
#GetMapping("")
public Flux<Book> getHome() {
List <Book> books=bookRepository.findAll();
X ret = template.requestBody("direct:something", books, X.class);
}
}
#Component
public class SomeRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:something")
.process(e-> {
List<Book> books = e.getIn.getBody(List.class)
// some logic
e.getIn.setBody(new X( ))
})
}

java ee 7 : using interceptors for centralized logging

I'd like to have one class responsible for my logging. The way I understand it, that's what interceptors can be used for. Here's my interceptor:
package logging;
import java.io.Serializable;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class LoggingInterceptor implements Serializable {
/**
*
*/
private static final long serialVersionUID = -2095670799863528243L;
#AroundInvoke
public Object intercept(InvocationContext context) throws Exception {
System.out.println("before calling method :"
+ context.getMethod().getName());
Object[] params = context.getParameters();
for (Object param : params) {
System.out.println("PARAM " + param.toString());
}
Object result = context.proceed();
System.out.println("after calling method :"
+ context.getMethod().getName());
return result;
}
}
I annotated various methods with the #Interceptor annotation.
My question is: How do I differentiate between the methods that are called? Depending on the method, I want to log a different message and maybe some parameters like folder names.
Right now, the only thing I can think of is a big if-elseif-else or switch statement to check the name of the method.
But this seems to be poor design. Am I using the interceptor for the right purpose? And if so, how would I go about implementing logging in a clean way?
I'd like to have one class responsible for logging because I want to display methods on the user interface as well as log to a file. Also, I'd like to use some java ee 7 built-in java ee 7 mechanism for such a cross-cutting concern.

Issue with Static resources when extending Spring Boot WebMvcConfigurationSupport

I extended WebMvcConfigurationSupport to implement an api versioning scheme - i.e.
#Configuration
public class ApiVersionConfiguration extends WebMvcConfigurationSupport {
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(readDateToVersionMap());
}}
This uses a custom handler mapping to version the api and works quite nicely.
However it also seems to disable the #EnableAutoConfiguration bean so that now static resources aren't served (as mentioned in this question Is it possible to extend WebMvcConfigurationSupport and use WebMvcAutoConfiguration?).
Ok, I thought, let's just add a resource handler to the class above - i.e.
#Configuration
public class ApiVersionConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("classpath:/public/").addResourceLocations("/");
}
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new ApiVersionRequestMappingHandlerMapping(readDateToVersionMap());
}}
However.. this isn't working..? I get this error when I browse to /index.html:
No mapping found for HTTP request with URI [/index.html] in DispatcherServlet with name 'dispatcherServlet'
..If I disable this class then these resources are served just fine by #EnableAutoConfiguration magic.
I've been playing with various options to serve static content having extended the WebMvcConfigurationSupport and thus far no success.
Any ideas?
I was facing the same problem and came up with a solution that just works for me. If you just want to get the resources working without worrying of repetition you can do:
#Configuration
public class StaticResourcesConfig extends WebMvcAutoConfigurationAdapter {
}
and then
#Configuration
#EnableWebMvc
#Import(StaticResourcesConfig.class)
public class WebConfig extends WebMvcConfigurationSupport {
...
}
This successfully uses the Spring Boot defaults for serving static resources, as long as you don't map /** in your controllers.

#EnableAspectJAutoProxy not work with proxyTargetClass=false

I am learning about Spring AOP at first time.
I am reading about in this sites:
Site2 and
Site1
Following this I have made the next classes
Main class:
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();
MessagePrinter printer = context.getBean(MessagePrinter.class);
System.out.println(printer.getMessage());
}
}
App config class:
#Configuration
#ComponentScan("com.pjcom.springaop")
#EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig {
#PostConstruct
public void doAlert() {
System.out.println("Application done.");
}
}
Aspect class:
#Component
#Aspect
public class AspectMonitor {
#Before("execution(* com.pjcom.springaop.message.impl.MessagePrinter.getMessage(..))")
public void beforeMessagePointCut(JoinPoint joinPoint) {
System.out.println("Monitorizando Mensaje.");
}
}
And others...
Just like that app work nice, but if I put proxyTargetClass to false. Then I get the error below.
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.pjcom.springaop.message.impl.MessagePrinter] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:318)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)
at com.pjcom.springaop.App.main(App.java:18)
Why?
#EnableAspectJAutoProxy(proxyTargetClass=false)
Indicates that JDK dynamic proxy will be created to support aspect execution on the object. And therefore as this type of proxy requires a class to implement an interface your MessagePrinter must implement some interface which declares method getMessage.
#EnableAspectJAutoProxy(proxyTargetClass=true)
On the opposite instruct to use CGLIB proxy which is able to create proxy for a class without an interface.
1> Message Printer has to be defined as a component i.e :
`
package com.pjcom.springaop.message.impl;
#Component
public class MessagePrinter{
public void getMessage(){
System.out.println("getMessage() called");
}
}`
in the same package as configuration java file if no #ComponentScan is not defined for some other packages.
2> If same type of bean class has many other dependencies then to resolve dependencies in spring Config use #Qualifier annotation.

GAE - rpc and HashMap<K,V> field

I tested my gwt app in eclipse and it worked fine; Then I tried to deploy my test app to gae... That what exception I can see in gae logs after each rpc call :
java.lang.RuntimeException: java.io.NotSerializableException
... so I am still looking the reason; but there is a point which make me confused cause one of my rpc-callback objects contains HashMap as one of its fields;
public abstract class Report implements Serializable{}
public abstract class Message implements Serializable{}
public class ErrorMessage extends Message{}
public final class Error extends Report
{
private HashMap<String,ErrorMessage> msgs;//<---?
//...
public void setMsg(HashMap<String,ErrorMessage> msgs){this.msgs=msgs;}
public HashMap<String,ErrorMessage> getMsg(){return this.msgs;}
}
...So my question is...
does gae supports java.util.HashMap ? And if not what is the most optimal collections alternative?
Thanks
It might be the "ErrorMessage" object that's not serializable.

Resources