To use jamon in spring, it's described to use JamonPerformanceMonitorInterceptor and put it to springs AOP-mechanism via a applicationContext.xml. It's explained, and there's an example within the tests in it's sources. Unfortunately, I want to build a spring-boot application without any xml-configuration.
Is it possible to use some annotations to include the JamonPerformanceMonitorInterceptor to spring?
Better late than never...
I had the very same situation: I needed to configure JAMon without any XML configuration. Most of the examples online (including the comments in the JAMon source code) advertise XML configuration flexibility, but I couldn't find any examples with annotation based configuration. Also annotation-based configs are not necessarily less flexible, they just need to be conceptually separated and not confused with functional parts of the application. I think such advisor can be a good example:
#Component
public class MonitoringAdvisor extends AbstractPointcutAdvisor {
private final StaticMethodMatcherPointcut pointcut = new StaticMethodMatcherPointcut() {
#Override
public boolean matches(Method method, Class<?> targetClass) {
return targetClass.isAnnotationPresent(RestController.class);
}
};
#Override
public Pointcut getPointcut() {
return this.pointcut;
}
#Override
public Advice getAdvice() {
return new JamonPerformanceMonitorInterceptor(true, true);
}
}
This advisor would let Spring/AOP know to run JAMon monitoring advice on any method of Spring bean annotated with #RestContrller. This advisor should be configured/added to the same Spring context as rest controllers.
Note, that in my case I specifically wanted to monitor my rest controllers. One can adapt the advisor according to his/her own needs. (In my code I use a more advanced/configurable version of the presented advisor)
Is this Spring Boot sample application helpful?
Here is the relevant part of the Spring AOP manual.
Related
In my Java app that based on Spring Boot, I am trying to implement a caching mechanism for the following service method:
#Override
public List<EmployeeDTO> findAllByCountry(Country country) {
final Map<Pair<UUID, String>, List<CountryTranslatable>> valueList
= countryRepository...
// code omitted for brevity
}
After several examples regarding to this issue, I decided on the approach mentioned on A Guide To Caching in Spring.
However, I am a little bit confused as it contains Spring and Spring Boot implementations and uses different annotation examples. I think I should start from 3.1. Using Spring Boot section as I use Spring Boot, but I am not sure about which Caching Annotation I should use (4.1. #Cacheable seems to be ok but I am not sure).
So, where should I put SimpleCacheCustomizer and how can I apply that approach for my service method above (findAllByCountry)? Any simple example would really be appreciated as I am new in Spring.
You don't need any customizations if you are a starter, and you want only the basics then do the following
#Configuration
#EnableCaching
public class CachingConfig {
#Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
The provided article states, return new ConcurrentMapCacheManager("addresses"); but you can use the default constructor and the relevant cache for adresses will be created later with #Cacheable("addresses"). So no need for this to be in configuration.
You also need
#Cacheable("employeesList")
#Override
public List<EmployeeDTO> findAllByCountry(Country country) {
final Map<Pair<UUID, String>, List<CountryTranslatable>> valueList
= countryRepository...
// code omitted for brevity
}
ready to go, that is the basic setup
If you want to customize the autoconfigured cachemanager then only you should implement CacheManagerCustomizer interface.
In usual cases you don't need to customize the autoconfigured cachemanager. The example has been given in the link you attached.
Your understanding on the cacheable annotation is also correct and it should work fine for you.
You can put that component class with other classes in the component scan range.
You should put your SimpleCacheCustomizer along with your others Spring configuration class. That way, your component will be scanned and loaded by Spring.
#Component
public class SimpleCacheCustomizer
implements CacheManagerCustomizer<ConcurrentMapCacheManager> {
#Override
public void customize(ConcurrentMapCacheManager cacheManager) {
cacheManager.setCacheNames(asList("employeesList", "otherCacheName"));
}
}
To use the cache with your service, add the annotation #Cacheable("employeesList")
#Cacheable("employeesList")
#Override
public List<EmployeeDTO> findAllByCountry(Country country) {
final Map<Pair<UUID, String>, List<CountryTranslatable>> valueList
= countryRepository...
// code omitted for brevity
}
If you want to verify the cache is working, just enable sql_query in your Spring configuration and check that findAllByCountry is no longer making any request to the DB.
I'm trying to use Spring AOP to add logging to methods coming from a third party library. So there is a class, ProxyServlet, that is being used by my Spring Boot application, and I just want to apply logging to it.
#Pointcut("within(com.common.httpproxy.ProxyServlet)")
private void proxyServlet() {}
#Before("proxyServlet()")
public void testLog() {
log.info("THIS IS WORKING");
}
This is just some test AOP code right here. I know that my Spring AOP is set up, because I can get log output for any classes included in my codebase. However, I can't get log output for any classes from a third party library, like the ProxyServlet.
Is there anything I can do to get this AOP advice to work?
You should annotate the class containing this code with:
#Aspect
#Component
Assuming that the ProxyServer instance is a bean, you can achieve it by defining an aspect for the logging something like below.
#Aspect
public class LoggingAspect {
#Before(execution(* the.package.ProxyServlet.*(..)))
public void loggingAdvice(JoinPoint joinPoint){
System.out.println("Started loggingAdvice on method="+joinPoint.toString());
System.out.println("The aruguments are =" + Arrays.toString(joinPoint.getArgs()));
}
}
Please note that it is not necessary to have a custom point-cut like #LoggingAdvice here and annotate the target method using it (I am pointing it because you mentioned that the class is in third party library by which means you are expressing the concern that you may not be able to annotate meothod(s) with a pointcut) . Custom point-cuts are useful when you define widely applicable Aspects and limit the application of it to certain joint pints (thru the custom pointcut)
As your target is a single class and is third party library, you are good without a custom point-cut but with an aspect specifically targeting the required class.
The above define Aspect will be executed for every method defined in the ProxyBean class.
AOP can pointcut like #Controller or #Service.
But it doesn't work well on Class without spring's annotation.
package com.erp.module;
#Slf4j
public class SalesOrderModule {
public void cancel(){
log.info("test");
}
public static SalesOrderModule init(int type) {
SalesOrderModule salesOrderModule = new SalesOrderModule(salesOrder);
*****
return salesOrderModule;
My Aspect.java like below
#Aspect
#Component
#Slf4j
public class WebLogAspect {
#Pointcut("execution(public * com.erp.controller.*.*(..)) || execution(public * com.erp.module.*.*(..))")
public void logPointCut() {
}
I invoke cancel like below:
SalesOrderModule so = SalesOrderModule.init(3);
so.cancel();
I know this problem is relative to proxy. But how can I
Spring Docs says:
Thus, for example, the Spring Frameworkâs AOP functionality is normally used in conjunction with the Spring IoC container. Aspects are configured using normal bean definition syntax (although this allows powerful "autoproxying" capabilities): this is a crucial difference from other AOP implementations. There are some things you cannot do easily or efficiently with Spring AOP, such as advise very fine-grained objects (such as domain objects typically): AspectJ is the best choice in such cases. However, our experience is that Spring AOP provides an excellent solution to most problems in enterprise Java applications that are amenable to AOP.
So if you need to intercept non-spring managed code, you need to use AspectJ instead of Spring AOP. TBH, I didn't need that so far.
I was wondering if there was a sort of compromise that allowed you to emulate/leverage the Google Guice style EDSL way of writing modules which binds interfaces to implementations in Spring.
For example, say I had a Google Guice Module that looked like this:
public class BillingModule extends AbstractModule {
protected void configure() {
bind(BillingService.class).to(RealBillingService.class);
}
}
This binds the BillingService interface to the RealBillingService implementation.
One way that I think I can do utilizing Spring's Java configuration class is something that looks like this
#Configuration
public class BillingConfiguration {
#Bean
public BillingService getRealBillingService() {
return new RealBillingService();
}
}
I was wondering if there was a better way to do this or if this broke down with increasingly complex usage.
I really like Google Guice and how it does Dependency Injection but that's kind of all it does. Spring does a lot more (yes, its dependency injection mechanism is still not 'as-nice' as Guice) but undeniably has some great projects that we would like to utilize like Spring Data, Spring Data REST, etc. which eliminate the need for writing a ton of boilerplate code.
The way to do this is to use #Profile to include different implementations of the same interface.
A simple example would be DataSource. This can however easily be extended to any other interfaces with multiple implementations.
As an example:
#Configuration
public class LocalDataConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
and then for use in production:
#Configuration
#Profile("production")
public class JndiDataConfig {
#Bean
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
Then all you need to do is declare which profiles are active when you start your application context and #Inject/#Autowire DataSource where you need it.
I've used both Guice and Spring a fair bit. As far as I know, the spring usage you show in the question is the only way to achieve the same as the binding in Guice with Spring. If you need to inject dependencies you can always include those as arguments to the #Bean method and have spring inject them for you.
It's definitely not as clean but it works the same way. One key thing to watch out for is that the default scope in spring is Singleton rather than a new instance every time (spring calls this scope prototype)
Is it possible to use #DeclareMixin with Spring AOP? Or do they only support #DeclareParents?
I want to write an aspect that mixes in the java.beans.PropertyChangeSupport into a java bean:
public class PropertyChangeSupportWithInterface extends PropertyChangeSupport
implements IObservableBean {
public PropertyChangeSupportWithInterface(Object sourceBean) {
super(sourceBean);
}
}
(IObservableBean simply contains all public methods from the PropertyChangeSupport)
#Aspect
#Named
public class ObservableAspect{
#DeclareMixin("#ObservableBean *")
public static IObservableBean createDelegate(Object object) {
return new PropertyChangeSupportWithInterface(object);
}
}
It seems that this aspect is never used, which makes me think that the #DeclareMixin is not supported by the runtime weaving done by Spring AOP.
Is there any way to get this working with Spring AOP?
You can find a (not) running example here (Maven multi module project):
https://github.com/BernhardBln/SpringAOPObservableBean
See the (only) test case in the springaop-observable-bean-aspect submodule.
No, it's not supported by Spring AOP out the box. I see two options:
Create a DeclareMixinIntroductionInterceptor for Spring AOP.
Switch to Aspectj
I think that PropertyChange interface fits better in Aspectj because usually you will create a lot of proxies for prototype beans and them could be created easily out of the framework, by an ORM for example.
Edit
However I'm interested in this feature too and I already done some work for use it:
A DelegateFactoryIntroductionInterceptor to support creating delegates from the aspect instance.
A DeclareMixinAdvisor to join the inteceptor with the type pattern.
A DeclareMixinAspectJAdvisorFactory to support the DeclareMixin annotation.
To use it you only need to declare a bean of type DeclareMixinAutoProxyCreatorConfigurer
for configuring the AnnotationAwareAspectJAutoProxyCreator with the AdvisorFactory above.
I'm just testing, but seem that work fine.